From 60e1ae421946f7e7dc2f5b453f8e91391d7865f4 Mon Sep 17 00:00:00 2001 From: MarcoHampel Date: Sun, 12 Nov 2023 21:08:23 -0500 Subject: [PATCH] steam api implementation --- .../Running/PlayerRunning.fbx.meta | 31 +- .../Running/X Bot@Pistol Run Down.fbx.meta | 31 +- .../Running/X Bot@Pistol Run Up.fbx.meta | 31 +- .../Extension/ILProcessorExtensions.cs | 20 - .../Extension/MethodDefinitionExtensions.cs | 131 - .../Extension/TypeDefinitionExtensions.cs | 254 -- .../Extension/TypeReferenceExtensions.cs | 59 - Assets/FishNet/CodeGenerating/FN_README.txt | 9 - .../FishNet/CodeGenerating/FN_README.txt.meta | 7 - .../CodeGenerating/Helpers/AttributeHelper.cs | 94 - .../Helpers/AttributeHelper.cs.meta | 11 - .../CodeGenerating/Helpers/CodegenSession.cs | 194 - .../Helpers/CodegenSession.cs.meta | 11 - .../Helpers/CreatedSyncVarGenerator.cs | 121 - .../Helpers/CreatedSyncVarGenerator.cs.meta | 11 - .../CodeGenerating/Helpers/Extension.meta | 8 - .../Extension/CustomAttributeExtensions.cs | 54 - .../CustomAttributeExtensions.cs.meta | 11 - .../Helpers/Extension/Diagnostics.cs | 41 - .../Helpers/Extension/Diagnostics.cs.meta | 11 - .../Extension/FieldReferenceExtensions.cs | 38 - .../FieldReferenceExtensions.cs.meta | 11 - .../Helpers/Extension/GetConstructor.cs | 191 - .../Helpers/Extension/GetConstructor.cs.meta | 11 - .../Extension/ILProcessorExtensions.cs | 169 - .../Extension/ILProcessorExtensions.cs.meta | 11 - .../Extension/InstructionExtensions.cs | 12 - .../Extension/InstructionExtensions.cs.meta | 11 - .../Extension/MethodDefinitionExtensions.cs | 55 - .../MethodDefinitionExtensions.cs.meta | 11 - .../Extension/MethodReferenceExtensions.cs | 155 - .../MethodReferenceExtensions.cs.meta | 11 - .../Extension/ModuleDefinitionExtensions.cs | 63 - .../ModuleDefinitionExtensions.cs.meta | 11 - .../ParameterDefinitionExtensions.cs | 24 - .../ParameterDefinitionExtensions.cs.meta | 11 - .../Extension/TypeDefinitionExtensions.cs | 521 --- .../TypeDefinitionExtensions.cs.meta | 11 - .../Extension/TypeReferenceExtensions.cs | 138 - .../Extension/TypeReferenceExtensions.cs.meta | 11 - .../CodeGenerating/Helpers/GeneralHelper.cs | 1412 ------ .../Helpers/GeneralHelper.cs.meta | 11 - .../Helpers/GenericReaderHelper.cs | 1 - .../Helpers/GenericReaderHelper.cs.meta | 11 - .../Helpers/GenericWriterHelper.cs | 1 - .../Helpers/GenericWriterHelper.cs.meta | 11 - .../Helpers/NetworkBehaviourHelper.cs | 443 -- .../Helpers/NetworkBehaviourHelper.cs.meta | 11 - .../Helpers/NetworkConnectionHelper.cs | 1 - .../Helpers/NetworkConnectionHelper.cs.meta | 11 - .../Helpers/NetworkConnectionImports.cs | 42 - .../Helpers/NetworkConnectionImports.cs.meta | 11 - .../CodeGenerating/Helpers/ObjectHelper.cs | 94 - .../Helpers/ObjectHelper.cs.meta | 11 - .../CodeGenerating/Helpers/PhysicsHelper.cs | 117 - .../Helpers/PhysicsHelper.cs.meta | 11 - .../Helpers/PredictedObjectHelper.cs | 15 - .../Helpers/PredictedObjectHelper.cs.meta | 11 - .../CodeGenerating/Helpers/ReaderGenerator.cs | 1 - .../Helpers/ReaderGenerator.cs.meta | 11 - .../CodeGenerating/Helpers/ReaderHelper.cs | 1 - .../Helpers/ReaderHelper.cs.meta | 11 - .../CodeGenerating/Helpers/ReaderImports.cs | 71 - .../Helpers/ReaderImports.cs.meta | 11 - .../Helpers/TimeManagerHelper.cs | 22 - .../Helpers/TimeManagerHelper.cs.meta | 11 - .../CodeGenerating/Helpers/TransportHelper.cs | 36 - .../Helpers/TransportHelper.cs.meta | 11 - .../FishNet/CodeGenerating/Helpers/Typed.meta | 8 - .../CodeGenerating/Helpers/Typed/Comparers.cs | 34 - .../Helpers/Typed/Comparers.cs.meta | 11 - .../Helpers/Typed/CreatedSyncType.cs | 49 - .../Helpers/Typed/CreatedSyncType.cs.meta | 11 - .../Helpers/Typed/GeneratorHelper.cs | 190 - .../Helpers/Typed/GeneratorHelper.cs.meta | 11 - .../Helpers/Typed/QOLAttributeType.cs | 12 - .../Helpers/Typed/QOLAttributeType.cs.meta | 11 - .../Helpers/Typed/SerializatierType.cs | 20 - .../Helpers/Typed/SerializatierType.cs.meta | 11 - .../Helpers/Typed/SyncIndexData.cs | 17 - .../Helpers/Typed/SyncIndexData.cs.meta | 11 - .../CodeGenerating/Helpers/Typed/SyncType.cs | 14 - .../Helpers/Typed/SyncType.cs.meta | 11 - .../CodeGenerating/Helpers/WriterGenerator.cs | 1 - .../Helpers/WriterGenerator.cs.meta | 11 - .../CodeGenerating/Helpers/WriterHelper.cs | 1 - .../Helpers/WriterHelper.cs.meta | 11 - .../CodeGenerating/Helpers/WriterImports.cs | 100 - .../Helpers/WriterImports.cs.meta | 11 - Assets/FishNet/CodeGenerating/ILCore.meta | 8 - .../CodeGenerating/ILCore/FishNetILPP.cs | 505 --- .../CodeGenerating/ILCore/FishNetILPP.cs.meta | 11 - .../CodeGenerating/ILCore/ILCoreHelper.cs | 38 - .../ILCore/ILCoreHelper.cs.meta | 11 - .../ILCore/PostProcessorAssemblyResolver.cs | 139 - .../PostProcessorAssemblyResolver.cs.meta | 11 - .../ILCore/PostProcessorReflectionImporter.cs | 22 - .../PostProcessorReflectionImporter.cs.meta | 11 - ...PostProcessorReflectionImporterProvider.cs | 12 - ...rocessorReflectionImporterProvider.cs.meta | 11 - Assets/FishNet/CodeGenerating/Processing.meta | 8 - .../CodeGenerating/Processing/CodegenBase.cs | 61 - .../Processing/CodegenBase.cs.meta | 11 - .../Processing/CustomSerializerProcessor.cs | 359 -- .../CustomSerializerProcessor.cs.meta | 11 - .../Processing/NetworkBehaviourProcessor.cs | 637 --- .../NetworkBehaviourProcessor.cs.meta | 11 - .../NetworkBehaviourSyncProcessor.cs | 1453 ------ .../NetworkBehaviourSyncProcessor.cs.meta | 11 - .../CodeGenerating/Processing/Prediction.meta | 12 - .../Prediction/PredictionProcessor.cs | 960 ---- .../Prediction/PredictionProcessor.cs.meta | 11 - .../Processing/QOLAttributeProcessor.cs | 164 - .../Processing/QOLAttributeProcessor.cs.meta | 11 - .../Processing/ReaderProcessor.cs | 1114 ----- .../Processing/ReaderProcessor.cs.meta | 11 - .../CodeGenerating/Processing/Rpc.meta | 8 - .../Processing/Rpc/AttributeData.cs | 68 - .../Processing/Rpc/AttributeData.cs.meta | 11 - .../Processing/Rpc/Attributes.cs | 166 - .../Processing/Rpc/Attributes.cs.meta | 11 - .../Processing/Rpc/CreatedRpc.cs | 58 - .../Processing/Rpc/CreatedRpc.cs.meta | 11 - .../Processing/Rpc/RpcProcessor.cs | 1084 ----- .../Processing/Rpc/RpcProcessor.cs.meta | 11 - .../CodeGenerating/Processing/Typed.meta | 8 - .../Processing/Typed/ProcessedSync.cs | 24 - .../Processing/Typed/ProcessedSync.cs.meta | 11 - .../Processing/WriterProcessor.cs | 1158 ----- .../Processing/WriterProcessor.cs.meta | 11 - .../Unity.FishNet.CodeGen.asmdef | 19 - .../FishNet/CodeGenerating/cecil-0.11.4.meta | 8 - .../cecil-0.11.4/Directory.Build.props | 30 - .../CodeGenerating/cecil-0.11.4/LICENSE.txt | 21 - .../cecil-0.11.4/Mono.Cecil.Cil.meta | 8 - .../cecil-0.11.4/Mono.Cecil.Cil/Code.cs | 234 - .../cecil-0.11.4/Mono.Cecil.Cil/Code.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.Cil/CodeReader.cs | 663 --- .../Mono.Cecil.Cil/CodeReader.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.Cil/CodeWriter.cs | 651 --- .../Mono.Cecil.Cil/CodeWriter.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.Cil/Document.cs | 123 - .../Mono.Cecil.Cil/Document.cs.meta | 11 - .../Mono.Cecil.Cil/ExceptionHandler.cs | 71 - .../Mono.Cecil.Cil/ExceptionHandler.cs.meta | 11 - .../Mono.Cecil.Cil/ILProcessor.cs | 291 -- .../Mono.Cecil.Cil/ILProcessor.cs.meta | 11 - .../Mono.Cecil.Cil/Instruction.cs | 296 -- .../Mono.Cecil.Cil/Instruction.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.Cil/MethodBody.cs | 426 -- .../Mono.Cecil.Cil/MethodBody.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.Cil/OpCode.cs | 439 -- .../Mono.Cecil.Cil/OpCode.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.Cil/OpCodes.cs | 894 ---- .../Mono.Cecil.Cil/OpCodes.cs.meta | 11 - .../Mono.Cecil.Cil/PortablePdb.cs | 591 --- .../Mono.Cecil.Cil/PortablePdb.cs.meta | 11 - .../Mono.Cecil.Cil/SequencePoint.cs | 76 - .../Mono.Cecil.Cil/SequencePoint.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.Cil/Symbols.cs | 1226 ------ .../Mono.Cecil.Cil/Symbols.cs.meta | 11 - .../Mono.Cecil.Cil/VariableDefinition.cs | 29 - .../Mono.Cecil.Cil/VariableDefinition.cs.meta | 11 - .../Mono.Cecil.Cil/VariableReference.cs | 42 - .../Mono.Cecil.Cil/VariableReference.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.Metadata.meta | 8 - .../Mono.Cecil.Metadata/BlobHeap.cs | 54 - .../Mono.Cecil.Metadata/BlobHeap.cs.meta | 11 - .../Mono.Cecil.Metadata/Buffers.cs | 499 --- .../Mono.Cecil.Metadata/Buffers.cs.meta | 11 - .../Mono.Cecil.Metadata/CodedIndex.cs | 29 - .../Mono.Cecil.Metadata/CodedIndex.cs.meta | 11 - .../Mono.Cecil.Metadata/ElementType.cs | 55 - .../Mono.Cecil.Metadata/ElementType.cs.meta | 11 - .../Mono.Cecil.Metadata/GuidHeap.cs | 36 - .../Mono.Cecil.Metadata/GuidHeap.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.Metadata/Heap.cs | 24 - .../Mono.Cecil.Metadata/Heap.cs.meta | 11 - .../Mono.Cecil.Metadata/MetadataToken.cs | 94 - .../Mono.Cecil.Metadata/MetadataToken.cs.meta | 11 - .../Mono.Cecil.Metadata/PdbHeap.cs | 32 - .../Mono.Cecil.Metadata/PdbHeap.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.Metadata/Row.cs | 152 - .../Mono.Cecil.Metadata/Row.cs.meta | 11 - .../Mono.Cecil.Metadata/StringHeap.cs | 59 - .../Mono.Cecil.Metadata/StringHeap.cs.meta | 11 - .../Mono.Cecil.Metadata/TableHeap.cs | 101 - .../Mono.Cecil.Metadata/TableHeap.cs.meta | 11 - .../Mono.Cecil.Metadata/TokenType.cs | 49 - .../Mono.Cecil.Metadata/TokenType.cs.meta | 11 - .../Mono.Cecil.Metadata/UserStringHeap.cs | 36 - .../UserStringHeap.cs.meta | 11 - .../Mono.Cecil.Metadata/Utilities.cs | 649 --- .../Mono.Cecil.Metadata/Utilities.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.PE.meta | 8 - .../Mono.Cecil.PE/BinaryStreamReader.cs | 53 - .../Mono.Cecil.PE/BinaryStreamReader.cs.meta | 11 - .../Mono.Cecil.PE/BinaryStreamWriter.cs | 88 - .../Mono.Cecil.PE/BinaryStreamWriter.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.PE/ByteBuffer.cs | 335 -- .../Mono.Cecil.PE/ByteBuffer.cs.meta | 11 - .../ByteBufferEqualityComparer.cs | 47 - .../ByteBufferEqualityComparer.cs.meta | 11 - .../Mono.Cecil.PE/DataDirectory.cs | 30 - .../Mono.Cecil.PE/DataDirectory.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.PE/Image.cs | 169 - .../cecil-0.11.4/Mono.Cecil.PE/Image.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.PE/ImageReader.cs | 793 ---- .../Mono.Cecil.PE/ImageReader.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.PE/ImageWriter.cs | 860 ---- .../Mono.Cecil.PE/ImageWriter.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.PE/Section.cs | 22 - .../Mono.Cecil.PE/Section.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.PE/TextMap.cs | 106 - .../Mono.Cecil.PE/TextMap.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil.Tests.props | 16 - .../cecil-0.11.4/Mono.Cecil.meta | 8 - .../cecil-0.11.4/Mono.Cecil.nunit | 9 - .../cecil-0.11.4/Mono.Cecil.nunit.meta | 7 - .../cecil-0.11.4/Mono.Cecil.nuspec | 42 - .../cecil-0.11.4/Mono.Cecil.nuspec.meta | 7 - .../cecil-0.11.4/Mono.Cecil/ArrayType.cs | 145 - .../cecil-0.11.4/Mono.Cecil/ArrayType.cs.meta | 11 - .../Mono.Cecil/AssemblyDefinition.cs | 189 - .../Mono.Cecil/AssemblyDefinition.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/AssemblyFlags.cs | 24 - .../Mono.Cecil/AssemblyFlags.cs.meta | 11 - .../Mono.Cecil/AssemblyHashAlgorithm.cs | 22 - .../Mono.Cecil/AssemblyHashAlgorithm.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/AssemblyInfo.cs | 22 - .../Mono.Cecil/AssemblyInfo.cs.meta | 11 - .../Mono.Cecil/AssemblyLinkedResource.cs | 37 - .../Mono.Cecil/AssemblyLinkedResource.cs.meta | 11 - .../Mono.Cecil/AssemblyNameDefinition.cs | 32 - .../Mono.Cecil/AssemblyNameDefinition.cs.meta | 11 - .../Mono.Cecil/AssemblyNameReference.cs | 269 -- .../Mono.Cecil/AssemblyNameReference.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/AssemblyReader.cs | 3889 ----------------- .../Mono.Cecil/AssemblyReader.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/AssemblyWriter.cs | 3336 -------------- .../Mono.Cecil/AssemblyWriter.cs.meta | 11 - .../Mono.Cecil/BaseAssemblyResolver.cs | 406 -- .../Mono.Cecil/BaseAssemblyResolver.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/CallSite.cs | 105 - .../cecil-0.11.4/Mono.Cecil/CallSite.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/Consts.cs | 4 - .../cecil-0.11.4/Mono.Cecil/Consts.cs.meta | 11 - .../Mono.Cecil/CustomAttribute.cs | 221 - .../Mono.Cecil/CustomAttribute.cs.meta | 11 - .../Mono.Cecil/DefaultAssemblyResolver.cs | 61 - .../DefaultAssemblyResolver.cs.meta | 11 - .../Mono.Cecil/EmbeddedResource.cs | 98 - .../Mono.Cecil/EmbeddedResource.cs.meta | 11 - .../Mono.Cecil/EventAttributes.cs | 21 - .../Mono.Cecil/EventAttributes.cs.meta | 11 - .../Mono.Cecil/EventDefinition.cs | 156 - .../Mono.Cecil/EventDefinition.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/EventReference.cs | 40 - .../Mono.Cecil/EventReference.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/ExportedType.cs | 238 - .../Mono.Cecil/ExportedType.cs.meta | 11 - .../Mono.Cecil/FieldAttributes.cs | 41 - .../Mono.Cecil/FieldAttributes.cs.meta | 11 - .../Mono.Cecil/FieldDefinition.cs | 281 -- .../Mono.Cecil/FieldDefinition.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/FieldReference.cs | 68 - .../Mono.Cecil/FieldReference.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/FileAttributes.cs | 17 - .../Mono.Cecil/FileAttributes.cs.meta | 11 - .../Mono.Cecil/FunctionPointerType.cs | 111 - .../Mono.Cecil/FunctionPointerType.cs.meta | 11 - .../Mono.Cecil/GenericInstanceMethod.cs | 77 - .../Mono.Cecil/GenericInstanceMethod.cs.meta | 11 - .../Mono.Cecil/GenericInstanceType.cs | 75 - .../Mono.Cecil/GenericInstanceType.cs.meta | 11 - .../Mono.Cecil/GenericParameter.cs | 360 -- .../Mono.Cecil/GenericParameter.cs.meta | 11 - .../Mono.Cecil/GenericParameterAttributes.cs | 27 - .../GenericParameterAttributes.cs.meta | 11 - .../Mono.Cecil/GenericParameterResolver.cs | 175 - .../GenericParameterResolver.cs.meta | 11 - .../Mono.Cecil/IConstantProvider.cs | 44 - .../Mono.Cecil/IConstantProvider.cs.meta | 11 - .../Mono.Cecil/ICustomAttributeProvider.cs | 44 - .../ICustomAttributeProvider.cs.meta | 11 - .../Mono.Cecil/IGenericInstance.cs | 47 - .../Mono.Cecil/IGenericInstance.cs.meta | 11 - .../Mono.Cecil/IGenericParameterProvider.cs | 58 - .../IGenericParameterProvider.cs.meta | 11 - .../Mono.Cecil/IMarshalInfoProvider.cs | 38 - .../Mono.Cecil/IMarshalInfoProvider.cs.meta | 11 - .../Mono.Cecil/IMemberDefinition.cs | 82 - .../Mono.Cecil/IMemberDefinition.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/IMetadataScope.cs | 23 - .../Mono.Cecil/IMetadataScope.cs.meta | 11 - .../Mono.Cecil/IMetadataTokenProvider.cs | 17 - .../Mono.Cecil/IMetadataTokenProvider.cs.meta | 11 - .../Mono.Cecil/IMethodSignature.cs | 56 - .../Mono.Cecil/IMethodSignature.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/Import.cs | 858 ---- .../cecil-0.11.4/Mono.Cecil/Import.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/LinkedResource.cs | 42 - .../Mono.Cecil/LinkedResource.cs.meta | 11 - .../Mono.Cecil/ManifestResourceAttributes.cs | 21 - .../ManifestResourceAttributes.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/MarshalInfo.cs | 153 - .../Mono.Cecil/MarshalInfo.cs.meta | 11 - .../Mono.Cecil/MemberDefinitionCollection.cs | 73 - .../MemberDefinitionCollection.cs.meta | 11 - .../Mono.Cecil/MemberReference.cs | 102 - .../Mono.Cecil/MemberReference.cs.meta | 11 - .../Mono.Cecil/MetadataResolver.cs | 391 -- .../Mono.Cecil/MetadataResolver.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/MetadataSystem.cs | 431 -- .../Mono.Cecil/MetadataSystem.cs.meta | 11 - .../Mono.Cecil/MethodAttributes.cs | 48 - .../Mono.Cecil/MethodAttributes.cs.meta | 11 - .../Mono.Cecil/MethodCallingConvention.cs | 22 - .../MethodCallingConvention.cs.meta | 11 - .../Mono.Cecil/MethodDefinition.cs | 558 --- .../Mono.Cecil/MethodDefinition.cs.meta | 11 - .../Mono.Cecil/MethodImplAttributes.cs | 36 - .../Mono.Cecil/MethodImplAttributes.cs.meta | 11 - .../Mono.Cecil/MethodReference.cs | 202 - .../Mono.Cecil/MethodReference.cs.meta | 11 - .../Mono.Cecil/MethodReferenceComparer.cs | 144 - .../MethodReferenceComparer.cs.meta | 11 - .../Mono.Cecil/MethodReturnType.cs | 97 - .../Mono.Cecil/MethodReturnType.cs.meta | 11 - .../Mono.Cecil/MethodSemanticsAttributes.cs | 25 - .../MethodSemanticsAttributes.cs.meta | 11 - .../Mono.Cecil/MethodSpecification.cs | 83 - .../Mono.Cecil/MethodSpecification.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/Modifiers.cs | 112 - .../cecil-0.11.4/Mono.Cecil/Modifiers.cs.meta | 11 - .../Mono.Cecil/ModuleDefinition.cs | 1353 ------ .../Mono.Cecil/ModuleDefinition.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/ModuleKind.cs | 55 - .../Mono.Cecil/ModuleKind.cs.meta | 11 - .../Mono.Cecil/ModuleReference.cs | 49 - .../Mono.Cecil/ModuleReference.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/NativeType.cs | 55 - .../Mono.Cecil/NativeType.cs.meta | 11 - .../Mono.Cecil/PInvokeAttributes.cs | 44 - .../Mono.Cecil/PInvokeAttributes.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/PInvokeInfo.cs | 120 - .../Mono.Cecil/PInvokeInfo.cs.meta | 11 - .../Mono.Cecil/ParameterAttributes.cs | 27 - .../Mono.Cecil/ParameterAttributes.cs.meta | 11 - .../Mono.Cecil/ParameterDefinition.cs | 146 - .../Mono.Cecil/ParameterDefinition.cs.meta | 11 - .../ParameterDefinitionCollection.cs | 60 - .../ParameterDefinitionCollection.cs.meta | 11 - .../Mono.Cecil/ParameterReference.cs | 57 - .../Mono.Cecil/ParameterReference.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/PinnedType.cs | 35 - .../Mono.Cecil/PinnedType.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/PointerType.cs | 43 - .../Mono.Cecil/PointerType.cs.meta | 11 - .../Mono.Cecil/PropertyAttributes.cs | 23 - .../Mono.Cecil/PropertyAttributes.cs.meta | 11 - .../Mono.Cecil/PropertyDefinition.cs | 245 -- .../Mono.Cecil/PropertyDefinition.cs.meta | 11 - .../Mono.Cecil/PropertyReference.cs | 43 - .../Mono.Cecil/PropertyReference.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/ReferenceType.cs | 43 - .../Mono.Cecil/ReferenceType.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/Resource.cs | 58 - .../cecil-0.11.4/Mono.Cecil/Resource.cs.meta | 11 - .../Mono.Cecil/SecurityDeclaration.cs | 201 - .../Mono.Cecil/SecurityDeclaration.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/SentinelType.cs | 35 - .../Mono.Cecil/SentinelType.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/TargetRuntime.cs | 19 - .../Mono.Cecil/TargetRuntime.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/Treatments.cs | 61 - .../Mono.Cecil/Treatments.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/TypeAttributes.cs | 63 - .../Mono.Cecil/TypeAttributes.cs.meta | 11 - .../Mono.Cecil/TypeComparisonMode.cs | 11 - .../Mono.Cecil/TypeComparisonMode.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/TypeDefinition.cs | 618 --- .../Mono.Cecil/TypeDefinition.cs.meta | 11 - .../Mono.Cecil/TypeDefinitionCollection.cs | 98 - .../TypeDefinitionCollection.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/TypeParser.cs | 531 --- .../Mono.Cecil/TypeParser.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/TypeReference.cs | 352 -- .../Mono.Cecil/TypeReference.cs.meta | 11 - .../TypeReferenceEqualityComparer.cs | 253 -- .../TypeReferenceEqualityComparer.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/TypeResolver.cs | 220 - .../Mono.Cecil/TypeResolver.cs.meta | 11 - .../Mono.Cecil/TypeSpecification.cs | 66 - .../Mono.Cecil/TypeSpecification.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/TypeSystem.cs | 330 -- .../Mono.Cecil/TypeSystem.cs.meta | 11 - .../cecil-0.11.4/Mono.Cecil/VariantType.cs | 37 - .../Mono.Cecil/VariantType.cs.meta | 11 - .../Mono.Cecil/WindowsRuntimeProjections.cs | 959 ---- .../WindowsRuntimeProjections.cs.meta | 11 - .../Mono.Collections.Generic.meta | 8 - .../Mono.Collections.Generic/Collection.cs | 427 -- .../Collection.cs.meta | 11 - .../ReadOnlyCollection.cs | 101 - .../ReadOnlyCollection.cs.meta | 11 - .../Mono.Security.Cryptography.meta | 8 - .../CryptoConvert.cs | 290 -- .../CryptoConvert.cs.meta | 11 - .../CryptoService.cs | 202 - .../CryptoService.cs.meta | 11 - .../CodeGenerating/cecil-0.11.4/Mono.meta | 8 - .../cecil-0.11.4/Mono/Disposable.cs | 45 - .../cecil-0.11.4/Mono/Disposable.cs.meta | 11 - .../CodeGenerating/cecil-0.11.4/Mono/Empty.cs | 62 - .../cecil-0.11.4/Mono/Empty.cs.meta | 11 - .../cecil-0.11.4/Mono/MergeSort.cs | 66 - .../cecil-0.11.4/Mono/MergeSort.cs.meta | 11 - .../cecil-0.11.4/MonoFN.Cecil.asmdef | 15 - .../cecil-0.11.4/ProjectInfo.cs | 20 - .../cecil-0.11.4/ProjectInfo.cs.meta | 11 - .../CodeGenerating/cecil-0.11.4/README.md | 17 - .../CodeGenerating/cecil-0.11.4/cecil.snk | Bin 596 -> 0 bytes .../cecil-0.11.4/cecil.snk.meta | 7 - .../CodeGenerating/cecil-0.11.4/rocks.meta | 8 - .../cecil-0.11.4/rocks/Mono.Cecil.Rocks.meta | 8 - .../rocks/Mono.Cecil.Rocks/AssemblyInfo.cs | 15 - .../Mono.Cecil.Rocks/AssemblyInfo.cs.meta | 11 - .../rocks/Mono.Cecil.Rocks/DocCommentId.cs | 261 -- .../Mono.Cecil.Rocks/DocCommentId.cs.meta | 11 - .../rocks/Mono.Cecil.Rocks/Functional.cs | 41 - .../rocks/Mono.Cecil.Rocks/Functional.cs.meta | 11 - .../rocks/Mono.Cecil.Rocks/ILParser.cs | 228 - .../rocks/Mono.Cecil.Rocks/ILParser.cs.meta | 11 - .../rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs | 411 -- .../Mono.Cecil.Rocks/MethodBodyRocks.cs.meta | 11 - .../Mono.Cecil.Rocks/MethodDefinitionRocks.cs | 72 - .../MethodDefinitionRocks.cs.meta | 11 - .../Mono.Cecil.Rocks/ModuleDefinitionRocks.cs | 32 - .../ModuleDefinitionRocks.cs.meta | 11 - .../ParameterReferenceRocks.cs | 11 - .../ParameterReferenceRocks.cs.meta | 11 - .../SecurityDeclarationRocks.cs | 157 - .../SecurityDeclarationRocks.cs.meta | 11 - .../Mono.Cecil.Rocks/TypeDefinitionRocks.cs | 65 - .../TypeDefinitionRocks.cs.meta | 11 - .../Mono.Cecil.Rocks/TypeReferenceRocks.cs | 87 - .../TypeReferenceRocks.cs.meta | 11 - Assets/FishNet/DOCUMENTATION.txt | 3 - Assets/FishNet/Demos.meta | 8 - Assets/FishNet/Demos/FishNet.Demos.asmdef | 15 - .../FishNet/Demos/FishNet.Demos.asmdef.meta | 7 - Assets/FishNet/Demos/Network LOD.meta | 8 - .../Network LOD/Network LOD Demo README.txt | 7 - .../Network LOD Demo README.txt.meta | 7 - Assets/FishNet/Demos/Network LOD/Prefabs.meta | 8 - .../Prefabs/NetworkLOD_Prefab.prefab | 311 -- .../Prefabs/NetworkLOD_Prefab.prefab.meta | 7 - .../Demos/Network LOD/Prefabs/New Controls.cs | 196 - .../Network LOD/Prefabs/New Controls.cs.meta | 11 - .../Prefabs/New Controls.inputactions | 78 - .../Prefabs/New Controls.inputactions.meta | 14 - .../Network LOD/Prefabs/PlayerInputDriver.cs | 73 - .../Prefabs/PlayerInputDriver.cs.meta | 11 - .../Network LOD/Prefabs/PowerCore.prefab | 977 ----- .../Network LOD/Prefabs/PowerCore.prefab.meta | 7 - .../Demos/Network LOD/Prefabs/mydef.asmdef | 17 - .../Network LOD/Prefabs/mydef.asmdef.meta | 7 - Assets/FishNet/Demos/Network LOD/Scenes.meta | 8 - .../Network LOD/Scenes/NetworkLOD_Demo.unity | 1395 ------ .../Scenes/NetworkLOD_Demo.unity.meta | 7 - Assets/FishNet/Demos/Network LOD/Scripts.meta | 8 - .../Demos/Network LOD/Scripts/MoveRandomly.cs | 66 - .../Network LOD/Scripts/MoveRandomly.cs.meta | 11 - .../Network LOD/Scripts/NetworkLodTester.cs | 51 - .../Scripts/NetworkLodTester.cs.meta | 11 - Assets/FishNet/Example.meta | 8 - Assets/FishNet/Example/All.meta | 8 - Assets/FishNet/Example/All/Authenticator.meta | 8 - .../All/Authenticator/Authenticator.unity | 360 -- .../Authenticator/Authenticator.unity.meta | 7 - .../Example/All/Authenticator/Scripts.meta | 8 - .../All/Authenticator/Scripts/Broadcasts.cs | 21 - .../Authenticator/Scripts/Broadcasts.cs.meta | 11 - .../Scripts/HostAuthenticator.cs | 152 - .../Scripts/HostAuthenticator.cs.meta | 11 - .../Scripts/PasswordAuthenticator.cs | 132 - .../Scripts/PasswordAuthenticator.cs.meta | 11 - .../FishNet/Example/All/CustomSyncType.meta | 8 - .../CustomSyncType/Component State Sync.meta | 8 - .../Component State Sync/AMonoScript.cs | 17 - .../Component State Sync/AMonoScript.cs.meta | 11 - .../ComponentStateSync.cs | 155 - .../ComponentStateSync.cs.meta | 11 - .../ComponentSyncStateBehaviour.cs | 43 - .../ComponentSyncStateBehaviour.cs.meta | 11 - .../CustomSyncType/Custom Struct Sync.meta | 8 - .../Custom Struct Sync/StructSyncBehaviour.cs | 41 - .../StructSyncBehaviour.cs.meta | 11 - .../Custom Struct Sync/StructySync.cs | 256 -- .../Custom Struct Sync/StructySync.cs.meta | 11 - Assets/FishNet/Example/All/Prediction.meta | 8 - .../All/Prediction/CharacterController.meta | 8 - .../CharacterControllerPrediction.unity | 1276 ------ .../CharacterControllerPrediction.unity.meta | 7 - .../CharacterController/Prefabs.meta | 8 - .../CharacterControllerPrediction.prefab | 272 -- .../CharacterControllerPrediction.prefab.meta | 7 - .../CharacterController/Scripts.meta | 8 - .../Scripts/CharacterControllerPrediction.cs | 127 - .../CharacterControllerPrediction.cs.meta | 11 - .../Example/All/Prediction/Materials.meta | 8 - .../All/Prediction/Materials/BlueMat.mat | 77 - .../All/Prediction/Materials/BlueMat.mat.meta | 8 - .../All/Prediction/Materials/GroundMat.mat | 77 - .../Prediction/Materials/GroundMat.mat.meta | 8 - .../All/Prediction/Materials/PurpleMat.mat | 77 - .../Prediction/Materials/PurpleMat.mat.meta | 8 - .../All/Prediction/Materials/YellowishMat.mat | 77 - .../Materials/YellowishMat.mat.meta | 8 - .../Example/All/Prediction/Rigidbody.meta | 8 - .../New Physic Material.physicMaterial | 14 - .../New Physic Material.physicMaterial.meta | 8 - .../All/Prediction/Rigidbody/Prefabs.meta | 8 - .../Rigidbody/Prefabs/PredictedBullet.prefab | 256 -- .../Prefabs/PredictedBullet.prefab.meta | 7 - .../Prefabs/PredictedSphereSorta.prefab | 246 -- .../Prefabs/PredictedSphereSorta.prefab.meta | 7 - .../Prefabs/RigidbodyPrediction.prefab | 478 -- .../Prefabs/RigidbodyPrediction.prefab.meta | 7 - .../Rigidbody/RigidbodyPrediction.unity | 1517 ------- .../Rigidbody/RigidbodyPrediction.unity.meta | 7 - .../All/Prediction/Rigidbody/Scripts.meta | 8 - .../Rigidbody/Scripts/BulletTest.cs | 59 - .../Rigidbody/Scripts/BulletTest.cs.meta | 11 - .../Rigidbody/Scripts/PredictedBullet.cs | 106 - .../Rigidbody/Scripts/PredictedBullet.cs.meta | 11 - .../Rigidbody/Scripts/RigidbodyPrediction.cs | 285 -- .../Scripts/RigidbodyPrediction.cs.meta | 11 - .../Example/All/Prediction/Transform.meta | 8 - .../All/Prediction/Transform/Prefabs.meta | 8 - .../Prefabs/TransformPrediction.prefab | 250 -- .../Prefabs/TransformPrediction.prefab.meta | 7 - .../All/Prediction/Transform/Scripts.meta | 8 - .../Transform/Scripts/TransformPrediction.cs | 222 - .../Scripts/TransformPrediction.cs.meta | 11 - .../Transform/TransformPrediction.unity | 890 ---- .../Transform/TransformPrediction.unity.meta | 7 - Assets/FishNet/Example/All/SceneManager.meta | 8 - .../Example/All/SceneManager/Materials.meta | 8 - .../All/SceneManager/Materials/Black.mat | 78 - .../All/SceneManager/Materials/Black.mat.meta | 8 - .../All/SceneManager/Materials/Blue.mat | 78 - .../All/SceneManager/Materials/Blue.mat.meta | 8 - .../All/SceneManager/Materials/Green.mat | 78 - .../All/SceneManager/Materials/Green.mat.meta | 8 - .../All/SceneManager/Materials/Red.mat | 78 - .../All/SceneManager/Materials/Red.mat.meta | 8 - .../Example/All/SceneManager/Prefabs.meta | 8 - .../All/SceneManager/Prefabs/Player.prefab | 337 -- .../SceneManager/Prefabs/Player.prefab.meta | 7 - .../SceneManager Event Diagram.png | Bin 45367 -> 0 bytes .../SceneManager Event Diagram.png.meta | 92 - .../Example/All/SceneManager/Scenes.meta | 8 - .../All/SceneManager/Scenes/Additive.meta | 8 - .../Scenes/Additive/AdditiveConnection.unity | 264 -- .../Additive/AdditiveConnection.unity.meta | 7 - .../Scenes/Additive/AdditiveGlobal.unity | 264 -- .../Scenes/Additive/AdditiveGlobal.unity.meta | 7 - .../Scenes/Additive/AdditiveMain.unity | 1265 ------ .../Scenes/Additive/AdditiveMain.unity.meta | 7 - .../All/SceneManager/Scenes/Replace.meta | 8 - .../Scenes/Replace/ReplaceConnection.unity | 624 --- .../Replace/ReplaceConnection.unity.meta | 7 - .../Scenes/Replace/ReplaceGlobal.unity | 724 --- .../Scenes/Replace/ReplaceGlobal.unity.meta | 7 - .../Scenes/Replace/ReplaceMain.unity | 1271 ------ .../Scenes/Replace/ReplaceMain.unity.meta | 7 - .../Example/All/SceneManager/Scripts.meta | 8 - .../SceneManager/Scripts/PlayerController.cs | 75 - .../Scripts/PlayerController.cs.meta | 11 - .../Scripts/SceneLoaderExample.cs | 148 - .../Scripts/SceneLoaderExample.cs.meta | 11 - .../Scripts/SceneUnloaderExample.cs | 91 - .../Scripts/SceneUnloaderExample.cs.meta | 11 - Assets/FishNet/Example/FishNet.Example.asmdef | 15 - .../Example/FishNet.Example.asmdef.meta | 7 - Assets/FishNet/Example/Prefabs.meta | 8 - .../Example/Prefabs/NetworkHudCanvas.prefab | 529 --- .../Prefabs/NetworkHudCanvas.prefab.meta | 7 - .../Example/Prefabs/NetworkManager.prefab | 190 - .../Prefabs/NetworkManager.prefab.meta | 7 - Assets/FishNet/Example/Scripts.meta | 8 - .../Example/Scripts/NetworkHudCanvases.cs | 248 -- .../Scripts/NetworkHudCanvases.cs.meta | 11 - Assets/FishNet/LICENSE.txt | 35 - Assets/FishNet/LICENSE.txt.meta | 7 - Assets/FishNet/Plugins/CodeAnalysis.meta | 8 - .../FishNet.CodeAnalysis.Analyzers.dll | Bin 21504 -> 0 bytes .../FishNet.CodeAnalysis.Analyzers.dll.meta | 72 - .../CodeAnalysis/FishNet.CodeAnalysis.dll | Bin 5120 -> 0 bytes .../FishNet.CodeAnalysis.dll.meta | 33 - .../Plugins/CodeAnalysis/LICENSE.txt.meta | 7 - .../FishNet/Plugins/CodeAnalysis/README.txt | 2 - .../Plugins/CodeAnalysis/README.txt.meta | 7 - Assets/FishNet/Plugins/FishyFacepunch.meta | 8 - .../Plugins/FishyFacepunch/CHANGELOG.txt | 30 - .../Plugins/FishyFacepunch/CHANGELOG.txt.meta | 7 - .../FishNet/Plugins/FishyFacepunch/Core.meta | 8 - .../Core/BidirectionalDictionary.cs | 92 - .../Core/BidirectionalDictionary.cs.meta | 11 - .../FishyFacepunch/Core/ClientHostSocket.cs | 126 - .../Core/ClientHostSocket.cs.meta | 11 - .../FishyFacepunch/Core/ClientSocket.cs | 238 - .../FishyFacepunch/Core/ClientSocket.cs.meta | 11 - .../FishyFacepunch/Core/CommonSocket.cs | 177 - .../FishyFacepunch/Core/CommonSocket.cs.meta | 11 - .../Core/FishyConnectionManager.cs | 12 - .../Core/FishyConnectionManager.cs.meta | 11 - .../FishyFacepunch/Core/FishySocketManager.cs | 13 - .../Core/FishySocketManager.cs.meta | 11 - .../FishyFacepunch/Core/LocalPacket.cs | 25 - .../FishyFacepunch/Core/LocalPacket.cs.meta | 11 - .../FishyFacepunch/Core/ServerSocket.cs | 425 -- .../FishyFacepunch/Core/ServerSocket.cs.meta | 11 - .../Plugins/FishyFacepunch/FishyFacepunch.cs | 518 --- .../FishyFacepunch/FishyFacepunch.cs.meta | 11 - .../Plugins/FishyFacepunch/VERSION.txt | 1 - .../Plugins/FishyFacepunch/VERSION.txt.meta | 7 - Assets/FishNet/Runtime/Authenticating.meta | 8 - .../Runtime/Authenticating/Authenticator.cs | 51 - .../Authenticating/Authenticator.cs.meta | 11 - Assets/FishNet/Runtime/Broadcast.meta | 8 - Assets/FishNet/Runtime/Broadcast/Helping.meta | 8 - .../Broadcast/Helping/BroadcastHelper.cs | 19 - .../Broadcast/Helping/BroadcastHelper.cs.meta | 11 - .../FishNet/Runtime/Broadcast/IBroadcast.cs | 8 - .../Runtime/Broadcast/IBroadcast.cs.meta | 11 - Assets/FishNet/Runtime/Config.json | 3 - Assets/FishNet/Runtime/Config.json.meta | 7 - Assets/FishNet/Runtime/Connection.meta | 8 - Assets/FishNet/Runtime/Connection/Buffer.cs | 259 -- .../FishNet/Runtime/Connection/Buffer.cs.meta | 11 - .../Connection/NetworkConnection.Buffer.cs | 110 - .../NetworkConnection.Buffer.cs.meta | 11 - .../Connection/NetworkConnection.LOD.cs | 48 - .../Connection/NetworkConnection.LOD.cs.meta | 11 - .../Connection/NetworkConnection.PingPong.cs | 103 - .../NetworkConnection.PingPong.cs.meta | 11 - .../Connection/NetworkConnection.QOL.cs | 69 - .../Connection/NetworkConnection.QOL.cs.meta | 11 - .../Runtime/Connection/NetworkConnection.cs | 404 -- .../Connection/NetworkConnection.cs.meta | 11 - Assets/FishNet/Runtime/Documenting.meta | 8 - .../FishNet/Runtime/Documenting/Attributes.cs | 8 - .../Runtime/Documenting/Attributes.cs.meta | 11 - .../FishNet/Runtime/Editor/CodeStripping.cs | 118 - .../Runtime/Editor/CodeStripping.cs.meta | 11 - .../FishNet/Runtime/Editor/Configuring.meta | 8 - .../Editor/Configuring/ConfigurationData.cs | 146 - .../Configuring/ConfigurationData.cs.meta | 11 - .../Editor/Configuring/ConfigurationEditor.cs | 126 - .../Configuring/ConfigurationEditor.cs.meta | 11 - .../Runtime/Editor/Configuring/Configuring.cs | 102 - .../Editor/Configuring/Configuring.cs.meta | 11 - .../FIshNetGettingStartedEditor.cs | 172 - .../FIshNetGettingStartedEditor.cs.meta | 11 - .../Configuring/ReviewReminderEditor.cs | 171 - .../Configuring/ReviewReminderEditor.cs.meta | 11 - .../Editor/Configuring/SettingsProvider.cs | 86 - .../Configuring/SettingsProvider.cs.meta | 11 - Assets/FishNet/Runtime/Editor/Constants.cs | 13 - .../FishNet/Runtime/Editor/Constants.cs.meta | 11 - .../Runtime/Editor/DefaultPrefabsFinder.cs | 126 - .../Editor/DefaultPrefabsFinder.cs.meta | 11 - Assets/FishNet/Runtime/Editor/Finding.cs | 216 - Assets/FishNet/Runtime/Editor/Finding.cs.meta | 11 - .../FishNet/Runtime/Editor/PlayModeTracker.cs | 51 - .../Runtime/Editor/PlayModeTracker.cs.meta | 11 - .../Editor/PrefabCollectionGenerator.meta | 8 - .../PrefabCollectionGenerator/Generator.cs | 619 --- .../Generator.cs.meta | 11 - .../PrefabCollectionGenerator/Settings.cs | 103 - .../Settings.cs.meta | 11 - .../SettingsProvider.cs | 238 - .../SettingsProvider.cs.meta | 11 - .../FishNet/Runtime/Editor/PrefabProcessor.cs | 85 - .../Runtime/Editor/PrefabProcessor.cs.meta | 11 - .../Runtime/Editor/ScriptingDefines.cs | 74 - .../Runtime/Editor/ScriptingDefines.cs.meta | 11 - Assets/FishNet/Runtime/Editor/Textures.meta | 8 - .../FishNet/Runtime/Editor/Textures/Icon.meta | 8 - .../Editor/Textures/Icon/fishnet_light.png | Bin 41016 -> 0 bytes .../Textures/Icon/fishnet_light.png.meta | 92 - .../FishNet/Runtime/Editor/Textures/UI.meta | 8 - .../UI/Button_Dark_Client_Background.png | Bin 7098 -> 0 bytes .../UI/Button_Dark_Client_Background.png.meta | 116 - .../Textures/UI/Button_Dark_Indicator.png | Bin 2891 -> 0 bytes .../UI/Button_Dark_Indicator.png.meta | 116 - .../UI/Button_Dark_Server_Background.png | Bin 9320 -> 0 bytes .../UI/Button_Dark_Server_Background.png.meta | 116 - .../Editor/Textures/UI/Logo_With_Text.png | Bin 37614 -> 0 bytes .../Textures/UI/Logo_With_Text.png.meta | 96 - Assets/FishNet/Runtime/FishNet.Runtime.asmdef | 17 - .../Runtime/FishNet.Runtime.asmdef.meta | 7 - Assets/FishNet/Runtime/Generated.meta | 8 - .../FishNet/Runtime/Generated/Component.meta | 8 - .../Generated/Component/NetworkAnimator.meta | 8 - .../Component/NetworkAnimator/Editor.meta | 8 - .../Editor/NetworkAnimatorEditor.cs | 187 - .../Editor/NetworkAnimatorEditor.cs.meta | 11 - .../NetworkAnimator/NetworkAnimator.cs | 1449 ------ .../NetworkAnimator/NetworkAnimator.cs.meta | 11 - .../Generated/Component/NetworkTransform.meta | 8 - .../Component/NetworkTransform/Editor.meta | 8 - .../Editor/NetworkTransformEditor.cs | 134 - .../Editor/NetworkTransformEditor.cs.meta | 11 - .../NetworkTransform/NetworkTransform.cs | 2042 --------- .../NetworkTransform/NetworkTransform.cs.meta | 11 - .../NetworkTransform/SynchronizedProperty.cs | 13 - .../SynchronizedProperty.cs.meta | 11 - .../Generated/Component/Prediction.meta | 8 - .../Component/Prediction/Editor.meta | 8 - .../Editor/PredictedObjectEditor.cs | 152 - .../Editor/PredictedObjectEditor.cs.meta | 11 - .../Component/Prediction/OfflineRigidbody.cs | 130 - .../Prediction/OfflineRigidbody.cs.meta | 11 - .../Prediction/PredictedObject.Rigidbodies.cs | 1148 ----- .../PredictedObject.Rigidbodies.cs.meta | 11 - .../Component/Prediction/PredictedObject.cs | 605 --- .../Prediction/PredictedObject.cs.meta | 11 - .../PredictedObjectOwnerSmoother.cs | 299 -- .../PredictedObjectOwnerSmoother.cs.meta | 11 - .../PredictedObjectSpectatorSmoother.cs | 884 ---- .../PredictedObjectSpectatorSmoother.cs.meta | 11 - .../Component/Prediction/RigidbodyPauser.cs | 361 -- .../Prediction/RigidbodyPauser.cs.meta | 11 - .../Component/Prediction/RigidbodyState.cs | 140 - .../Prediction/RigidbodyState.cs.meta | 11 - .../Component/Prediction/RigidbodyType.cs | 12 - .../Prediction/RigidbodyType.cs.meta | 11 - .../Runtime/Generated/Component/Spawning.meta | 8 - .../Component/Spawning/PlayerSpawner.cs | 159 - .../Component/Spawning/PlayerSpawner.cs.meta | 11 - .../Generated/Component/TakeOwnership.meta | 8 - .../Component/TakeOwnership/PredictedOwner.cs | 121 - .../TakeOwnership/PredictedOwner.cs.meta | 11 - .../Component/TakeOwnership/PredictedSpawn.cs | 96 - .../TakeOwnership/PredictedSpawn.cs.meta | 11 - .../Runtime/Generated/Component/Utility.meta | 8 - .../Component/Utility/BandwidthDisplay.cs | 192 - .../Utility/BandwidthDisplay.cs.meta | 11 - .../Component/Utility/DefaultScene.cs | 239 - .../Component/Utility/DefaultScene.cs.meta | 11 - .../Component/Utility/PingDisplay.cs | 118 - .../Component/Utility/PingDisplay.cs.meta | 11 - .../FishNet/Runtime/Generated/SyncTypes.meta | 8 - .../Generated/SyncTypes/SyncStopwatch.cs | 364 -- .../Generated/SyncTypes/SyncStopwatch.cs.meta | 11 - .../SyncTypes/SyncStopwatchOperation.cs | 36 - .../SyncTypes/SyncStopwatchOperation.cs.meta | 11 - .../Runtime/Generated/SyncTypes/SyncTimer.cs | 407 -- .../Generated/SyncTypes/SyncTimer.cs.meta | 11 - .../Generated/SyncTypes/SyncTimerOperation.cs | 40 - .../SyncTypes/SyncTimerOperation.cs.meta | 11 - Assets/FishNet/Runtime/InstanceFinder.cs | 219 - Assets/FishNet/Runtime/InstanceFinder.cs.meta | 11 - Assets/FishNet/Runtime/Managing.meta | 8 - Assets/FishNet/Runtime/Managing/Client.meta | 8 - .../Client/ClientManager.Broadcast.cs | 179 - .../Client/ClientManager.Broadcast.cs.meta | 11 - .../Managing/Client/ClientManager.LOD.cs | 197 - .../Managing/Client/ClientManager.LOD.cs.meta | 11 - .../Runtime/Managing/Client/ClientManager.cs | 503 --- .../Managing/Client/ClientManager.cs.meta | 11 - .../Runtime/Managing/Client/Editor.meta | 8 - .../Client/Editor/ClientManagerEditor.cs | 46 - .../Client/Editor/ClientManagerEditor.cs.meta | 11 - .../Runtime/Managing/Client/Object.meta | 8 - .../Client/Object/ClientObjects.RpcLinks.cs | 87 - .../Object/ClientObjects.RpcLinks.cs.meta | 11 - .../Managing/Client/Object/ClientObjects.cs | 688 --- .../Client/Object/ClientObjects.cs.meta | 11 - .../Managing/Client/Object/ObjectCaching.cs | 605 --- .../Client/Object/ObjectCaching.cs.meta | 11 - .../FishNet/Runtime/Managing/Debugging.meta | 8 - .../Managing/Debugging/DebugManager.cs | 20 - .../Managing/Debugging/DebugManager.cs.meta | 11 - .../Runtime/Managing/Debugging/ParseLogger.cs | 73 - .../Managing/Debugging/ParseLogger.cs.meta | 11 - Assets/FishNet/Runtime/Managing/Editor.meta | 8 - .../Managing/Editor/NetworkManagerEditor.cs | 71 - .../Editor/NetworkManagerEditor.cs.meta | 11 - Assets/FishNet/Runtime/Managing/Logging.meta | 8 - .../Logging/LevelLoggingConfiguration.cs | 142 - .../Logging/LevelLoggingConfiguration.cs.meta | 11 - .../Managing/Logging/LoggingConfiguration.cs | 57 - .../Logging/LoggingConfiguration.cs.meta | 11 - .../Runtime/Managing/Logging/LoggingType.cs | 25 - .../Managing/Logging/LoggingType.cs.meta | 11 - .../Managing/NetworkManager.Logging.cs | 121 - .../Managing/NetworkManager.Logging.cs.meta | 11 - .../Runtime/Managing/NetworkManager.Pro.cs | 20 - .../Managing/NetworkManager.Pro.cs.meta | 11 - .../Runtime/Managing/NetworkManager.QOL.cs | 259 -- .../Managing/NetworkManager.QOL.cs.meta | 11 - .../Runtime/Managing/NetworkManager.cs | 573 --- .../Runtime/Managing/NetworkManager.cs.meta | 11 - Assets/FishNet/Runtime/Managing/Object.meta | 8 - .../Runtime/Managing/Object/DespawnWriter.cs | 1 - .../Managing/Object/DespawnWriter.cs.meta | 11 - .../Runtime/Managing/Object/DualPrefab.cs | 16 - .../Managing/Object/DualPrefab.cs.meta | 11 - .../Object/ManagedObjects.Spawning.cs | 380 -- .../Object/ManagedObjects.Spawning.cs.meta | 11 - .../Runtime/Managing/Object/ManagedObjects.cs | 414 -- .../Managing/Object/ManagedObjects.cs.meta | 11 - .../Managing/Object/ObjectSpawnType.cs | 31 - .../Managing/Object/ObjectSpawnType.cs.meta | 11 - .../Managing/Object/PrefabObjects.meta | 8 - .../PrefabObjects/DefaultPrefabObjects.cs | 104 - .../DefaultPrefabObjects.cs.meta | 11 - .../Object/PrefabObjects/DualPrefabObjects.cs | 136 - .../PrefabObjects/DualPrefabObjects.cs.meta | 11 - .../Object/PrefabObjects/PrefabObjects.cs | 36 - .../PrefabObjects/PrefabObjects.cs.meta | 11 - .../PrefabObjects/SinglePrefabObjects.cs | 128 - .../PrefabObjects/SinglePrefabObjects.cs.meta | 11 - .../Managing/Object/SpawnParentType.cs | 10 - .../Managing/Object/SpawnParentType.cs.meta | 11 - .../Runtime/Managing/Object/SpawnWriter.cs | 1 - .../Managing/Object/SpawnWriter.cs.meta | 11 - .../FishNet/Runtime/Managing/Observing.meta | 8 - .../Runtime/Managing/Observing/Editor.meta | 8 - .../Observing/Editor/ObserverManagerEditor.cs | 53 - .../Editor/ObserverManagerEditor.cs.meta | 11 - .../Managing/Observing/ObserverManager.cs | 324 -- .../Observing/ObserverManager.cs.meta | 11 - .../FishNet/Runtime/Managing/Prediction.meta | 12 - .../Runtime/Managing/Prediction/Editor.meta | 8 - .../Editor/PredictionManagerEditor.cs | 74 - .../Editor/PredictionManagerEditor.cs.meta | 11 - .../Managing/Prediction/PredictionManager.cs | 323 -- .../Prediction/PredictionManager.cs.meta | 11 - Assets/FishNet/Runtime/Managing/Scened.meta | 8 - .../Runtime/Managing/Scened/Broadcast.meta | 8 - .../Scened/Broadcast/SceneBroadcasts.cs | 38 - .../Scened/Broadcast/SceneBroadcasts.cs.meta | 11 - .../Managing/Scened/DefaultSceneProcessor.cs | 155 - .../Scened/DefaultSceneProcessor.cs.meta | 11 - .../Runtime/Managing/Scened/Events.meta | 8 - .../Events/ClientPresenceChangeEventArgs.cs | 34 - .../ClientPresenceChangeEventArgs.cs.meta | 11 - .../Scened/Events/LoadSceneEventArgs.cs | 78 - .../Scened/Events/LoadSceneEventArgs.cs.meta | 11 - .../Scened/Events/UnloadSceneEventArgs.cs | 74 - .../Events/UnloadSceneEventArgs.cs.meta | 11 - .../Managing/Scened/LoadUnloadDatas.meta | 8 - .../Scened/LoadUnloadDatas/LoadOptions.cs | 39 - .../LoadUnloadDatas/LoadOptions.cs.meta | 11 - .../Scened/LoadUnloadDatas/LoadParams.cs | 19 - .../Scened/LoadUnloadDatas/LoadParams.cs.meta | 11 - .../Scened/LoadUnloadDatas/LoadQueueData.cs | 51 - .../LoadUnloadDatas/LoadQueueData.cs.meta | 11 - .../Scened/LoadUnloadDatas/ReplaceOption.cs | 25 - .../LoadUnloadDatas/ReplaceOption.cs.meta | 11 - .../Scened/LoadUnloadDatas/SceneLoadData.cs | 201 - .../LoadUnloadDatas/SceneLoadData.cs.meta | 11 - .../Scened/LoadUnloadDatas/SceneScopeTypes.cs | 18 - .../LoadUnloadDatas/SceneScopeTypes.cs.meta | 11 - .../Scened/LoadUnloadDatas/SceneUnloadData.cs | 116 - .../LoadUnloadDatas/SceneUnloadData.cs.meta | 11 - .../Scened/LoadUnloadDatas/UnloadOptions.cs | 36 - .../LoadUnloadDatas/UnloadOptions.cs.meta | 11 - .../Scened/LoadUnloadDatas/UnloadParams.cs | 19 - .../LoadUnloadDatas/UnloadParams.cs.meta | 11 - .../Scened/LoadUnloadDatas/UnloadQueueData.cs | 53 - .../LoadUnloadDatas/UnloadQueueData.cs.meta | 11 - .../Managing/Scened/SceneLookupData.cs | 322 -- .../Managing/Scened/SceneLookupData.cs.meta | 11 - .../Runtime/Managing/Scened/SceneManager.cs | 2138 --------- .../Managing/Scened/SceneManager.cs.meta | 11 - .../Managing/Scened/SceneProcessorBase.cs | 93 - .../Scened/SceneProcessorBase.cs.meta | 11 - .../Runtime/Managing/Scened/SceneSpawner.cs | 356 -- .../Managing/Scened/SceneSpawner.cs.meta | 11 - .../Runtime/Managing/Scened/UnloadedScene.cs | 21 - .../Managing/Scened/UnloadedScene.cs.meta | 11 - Assets/FishNet/Runtime/Managing/Server.meta | 8 - .../Server/ClientConnectionBroadcast.cs | 18 - .../Server/ClientConnectionBroadcast.cs.meta | 11 - .../Runtime/Managing/Server/Editor.meta | 8 - .../Server/Editor/ServerManagerEditor.cs | 64 - .../Server/Editor/ServerManagerEditor.cs.meta | 11 - .../Runtime/Managing/Server/KickReasons.cs | 36 - .../Managing/Server/KickReasons.cs.meta | 11 - .../Runtime/Managing/Server/Object.meta | 8 - .../Server/Object/ServerObjects.Observers.cs | 522 --- .../Object/ServerObjects.Observers.cs.meta | 11 - .../Server/Object/ServerObjects.Parsing.cs | 45 - .../Object/ServerObjects.Parsing.cs.meta | 11 - .../Managing/Server/Object/ServerObjects.cs | 876 ---- .../Server/Object/ServerObjects.cs.meta | 11 - .../Server/ServerManager.Broadcast.cs | 457 -- .../Server/ServerManager.Broadcast.cs.meta | 11 - .../Managing/Server/ServerManager.LOD.cs | 231 - .../Managing/Server/ServerManager.LOD.cs.meta | 11 - .../Managing/Server/ServerManager.QOL.cs | 199 - .../Managing/Server/ServerManager.QOL.cs.meta | 11 - .../Managing/Server/ServerManager.RpcLinks.cs | 78 - .../Server/ServerManager.RpcLinks.cs.meta | 11 - .../Runtime/Managing/Server/ServerManager.cs | 759 ---- .../Managing/Server/ServerManager.cs.meta | 11 - .../FishNet/Runtime/Managing/Statistic.meta | 8 - .../Managing/Statistic/NetworkTrafficArgs.cs | 21 - .../Statistic/NetworkTrafficArgs.cs.meta | 11 - .../Statistic/NetworkTrafficStatistics.cs | 203 - .../NetworkTrafficStatistics.cs.meta | 11 - .../Managing/Statistic/StatisticsManager.cs | 22 - .../Statistic/StatisticsManager.cs.meta | 11 - Assets/FishNet/Runtime/Managing/Timing.meta | 8 - .../Runtime/Managing/Timing/Editor.meta | 8 - .../Timing/Editor/TimeManagerEditor.cs | 79 - .../Timing/Editor/TimeManagerEditor.cs.meta | 11 - .../Runtime/Managing/Timing/MovingAverage.cs | 81 - .../Managing/Timing/MovingAverage.cs.meta | 11 - .../Runtime/Managing/Timing/PhysicsMode.cs | 23 - .../Managing/Timing/PhysicsMode.cs.meta | 11 - .../Runtime/Managing/Timing/PreciseTick.cs | 47 - .../Managing/Timing/PreciseTick.cs.meta | 11 - .../Runtime/Managing/Timing/TickRounding.cs | 23 - .../Managing/Timing/TickRounding.cs.meta | 11 - .../Runtime/Managing/Timing/TickType.cs | 10 - .../Runtime/Managing/Timing/TickType.cs.meta | 11 - .../Runtime/Managing/Timing/TimeManager.cs | 1054 ----- .../Managing/Timing/TimeManager.cs.meta | 11 - .../Runtime/Managing/Transporting.meta | 8 - .../Transporting/IntermediateLayer.cs | 36 - .../Transporting/IntermediateLayer.cs.meta | 11 - .../Managing/Transporting/LatencySimulator.cs | 376 -- .../Transporting/LatencySimulator.cs.meta | 11 - .../Managing/Transporting/SplitReader.cs | 99 - .../Managing/Transporting/SplitReader.cs.meta | 11 - .../Transporting/TransportManager.QOL.cs | 65 - .../Transporting/TransportManager.QOL.cs.meta | 11 - .../Managing/Transporting/TransportManager.cs | 668 --- .../Transporting/TransportManager.cs.meta | 11 - Assets/FishNet/Runtime/Managing/Utility.meta | 8 - .../Runtime/Managing/Utility/Utility.cs | 63 - .../Runtime/Managing/Utility/Utility.cs.meta | 11 - Assets/FishNet/Runtime/Object.meta | 8 - Assets/FishNet/Runtime/Object/Attributes.cs | 170 - .../FishNet/Runtime/Object/Attributes.cs.meta | 11 - .../Object/ChangedTransformProperties.cs | 35 - .../Object/ChangedTransformProperties.cs.meta | 11 - Assets/FishNet/Runtime/Object/Delegates.cs | 13 - .../FishNet/Runtime/Object/Delegates.cs.meta | 11 - Assets/FishNet/Runtime/Object/DespawnType.cs | 13 - .../Runtime/Object/DespawnType.cs.meta | 11 - .../Runtime/Object/EmptyNetworkBehaviour.cs | 13 - .../Object/EmptyNetworkBehaviour.cs.meta | 11 - Assets/FishNet/Runtime/Object/Helping.meta | 8 - .../FishNet/Runtime/Object/Helping/Hashing.cs | 153 - .../Runtime/Object/Helping/Hashing.cs.meta | 11 - .../FishNet/Runtime/Object/Helping/RpcLink.cs | 39 - .../Runtime/Object/Helping/RpcLink.cs.meta | 11 - .../FishNet/Runtime/Object/Helping/RpcType.cs | 13 - .../Runtime/Object/Helping/RpcType.cs.meta | 11 - .../Runtime/Object/Helping/StaticShortcuts.cs | 49 - .../Object/Helping/StaticShortcuts.cs.meta | 11 - .../Object/NetworkBehaviour.Callbacks.cs | 184 - .../Object/NetworkBehaviour.Callbacks.cs.meta | 11 - .../Object/NetworkBehaviour.Logging.cs | 22 - .../Object/NetworkBehaviour.Logging.cs.meta | 11 - .../Object/NetworkBehaviour.Prediction.cs | 746 ---- .../NetworkBehaviour.Prediction.cs.meta | 11 - .../Runtime/Object/NetworkBehaviour.QOL.cs | 258 -- .../Object/NetworkBehaviour.QOL.cs.meta | 11 - .../Object/NetworkBehaviour.RPCLinks.cs | 140 - .../Object/NetworkBehaviour.RPCLinks.cs.meta | 11 - .../Runtime/Object/NetworkBehaviour.RPCs.cs | 364 -- .../Object/NetworkBehaviour.RPCs.cs.meta | 11 - .../Object/NetworkBehaviour.SyncTypes.cs | 429 -- .../Object/NetworkBehaviour.SyncTypes.cs.meta | 11 - .../Runtime/Object/NetworkBehaviour.cs | 190 - .../Runtime/Object/NetworkBehaviour.cs.meta | 11 - .../Runtime/Object/NetworkObject.Broadcast.cs | 31 - .../Object/NetworkObject.Broadcast.cs.meta | 11 - .../Runtime/Object/NetworkObject.Callbacks.cs | 150 - .../Object/NetworkObject.Callbacks.cs.meta | 11 - .../Runtime/Object/NetworkObject.Observers.cs | 213 - .../Object/NetworkObject.Observers.cs.meta | 11 - .../Runtime/Object/NetworkObject.QOL.cs | 313 -- .../Runtime/Object/NetworkObject.QOL.cs.meta | 11 - .../Object/NetworkObject.ReferenceIds.cs | 213 - .../Object/NetworkObject.ReferenceIds.cs.meta | 11 - .../Runtime/Object/NetworkObject.RpcLinks.cs | 34 - .../Object/NetworkObject.RpcLinks.cs.meta | 11 - .../Runtime/Object/NetworkObject.SyncTypes.cs | 25 - .../Object/NetworkObject.SyncTypes.cs.meta | 11 - .../FishNet/Runtime/Object/NetworkObject.cs | 862 ---- .../Runtime/Object/NetworkObject.cs.meta | 11 - .../Runtime/Object/NetworkObjectState.cs | 24 - .../Runtime/Object/NetworkObjectState.cs.meta | 11 - .../Runtime/Object/PredictedSpawningType.cs | 14 - .../Object/PredictedSpawningType.cs.meta | 11 - Assets/FishNet/Runtime/Object/Prediction.meta | 8 - .../Runtime/Object/Prediction/Attributes.cs | 29 - .../Object/Prediction/Attributes.cs.meta | 11 - .../Runtime/Object/Prediction/Delegates.cs | 20 - .../Object/Prediction/Delegates.cs.meta | 11 - .../Runtime/Object/Prediction/Interfaces.cs | 18 - .../Object/Prediction/Interfaces.cs.meta | 11 - Assets/FishNet/Runtime/Object/RpcLinkType.cs | 25 - .../Runtime/Object/RpcLinkType.cs.meta | 11 - .../Runtime/Object/SyncTypeWriteType.cs | 12 - .../Runtime/Object/SyncTypeWriteType.cs.meta | 11 - .../FishNet/Runtime/Object/Synchronizing.meta | 8 - .../Object/Synchronizing/ICustomSync.cs | 19 - .../Object/Synchronizing/ICustomSync.cs.meta | 11 - .../Object/Synchronizing/ISyncObject.cs | 48 - .../Object/Synchronizing/ISyncObject.cs.meta | 11 - .../MissingObjectPacketLength.cs | 11 - .../MissingObjectPacketLength.cs.meta | 11 - .../Object/Synchronizing/ReadPermissions.cs | 21 - .../Synchronizing/ReadPermissions.cs.meta | 11 - .../Object/Synchronizing/SecretMenu.meta | 8 - .../SecretMenu/SyncVarExtensions.cs | 21 - .../SecretMenu/SyncVarExtensions.cs.meta | 11 - .../Runtime/Object/Synchronizing/Settings.cs | 53 - .../Object/Synchronizing/Settings.cs.meta | 11 - .../Runtime/Object/Synchronizing/SyncBase.cs | 265 -- .../Object/Synchronizing/SyncBase.cs.meta | 11 - .../Object/Synchronizing/SyncDictionary.cs | 628 --- .../Synchronizing/SyncDictionary.cs.meta | 11 - .../Synchronizing/SyncDictionaryOperation.cs | 31 - .../SyncDictionaryOperation.cs.meta | 11 - .../Synchronizing/SyncHashSetOperation.cs | 31 - .../SyncHashSetOperation.cs.meta | 11 - .../Object/Synchronizing/SyncHashset.cs | 616 --- .../Object/Synchronizing/SyncHashset.cs.meta | 11 - .../Runtime/Object/Synchronizing/SyncList.cs | 748 ---- .../Object/Synchronizing/SyncList.cs.meta | 11 - .../Object/Synchronizing/SyncListOperation.cs | 35 - .../Synchronizing/SyncListOperation.cs.meta | 11 - .../Runtime/Object/Synchronizing/SyncVar.cs | 290 -- .../Object/Synchronizing/SyncVar.cs.meta | 11 - .../Object/Synchronizing/WritePermissions.cs | 10 - .../Synchronizing/WritePermissions.cs.meta | 11 - .../Runtime/Object/TransformProperties.cs | 20 - .../Object/TransformProperties.cs.meta | 11 - Assets/FishNet/Runtime/Observing.meta | 8 - .../FishNet/Runtime/Observing/Conditions.meta | 8 - .../Observing/Conditions/DistanceCondition.cs | 143 - .../Conditions/DistanceCondition.cs.meta | 11 - .../Observing/Conditions/HostOnlyCondition.cs | 30 - .../Conditions/HostOnlyCondition.cs.meta | 11 - .../Observing/Conditions/MatchCondition.cs | 585 --- .../Conditions/MatchCondition.cs.meta | 11 - .../Conditions/OwnerOnlyCondition.cs | 47 - .../Conditions/OwnerOnlyCondition.cs.meta | 11 - .../Observing/Conditions/SceneCondition.cs | 88 - .../Conditions/SceneCondition.cs.meta | 11 - .../Conditions/ScriptableObjects.meta | 8 - .../ScriptableObjects/DistanceCondition.asset | 18 - .../DistanceCondition.asset.meta | 8 - .../ScriptableObjects/HostOnlyCondition.asset | 15 - .../HostOnlyCondition.asset.meta | 8 - .../ScriptableObjects/MatchCondition.asset | 15 - .../MatchCondition.asset.meta | 8 - .../OwnerOnlyCondition.asset | 15 - .../OwnerOnlyCondition.asset.meta | 8 - .../ScriptableObjects/SceneCondition.asset | 17 - .../SceneCondition.asset.meta | 8 - .../Observing/HostVisibilityUpdateTypes.cs | 17 - .../HostVisibilityUpdateTypes.cs.meta | 11 - .../Runtime/Observing/NetworkObserver.cs | 404 -- .../Runtime/Observing/NetworkObserver.cs.meta | 11 - .../Runtime/Observing/ObserverCondition.cs | 81 - .../Observing/ObserverCondition.cs.meta | 11 - .../Runtime/Observing/ObserverStateChange.cs | 12 - .../Observing/ObserverStateChange.cs.meta | 11 - Assets/FishNet/Runtime/Plugins.meta | 8 - .../Runtime/Plugins/ColliderRollback.meta | 8 - .../Plugins/ColliderRollback/Attributions.txt | 5 - .../ColliderRollback/Attributions.txt.meta | 7 - .../Plugins/ColliderRollback/LICENSE.txt | 1 - .../Plugins/ColliderRollback/LICENSE.txt.meta | 7 - .../Plugins/ColliderRollback/Scripts.meta | 8 - .../Scripts/ColliderRollback.cs | 23 - .../Scripts/ColliderRollback.cs.meta | 11 - .../Scripts/RollbackManager.cs | 51 - .../Scripts/RollbackManager.cs.meta | 11 - Assets/FishNet/Runtime/Plugins/Yak.meta | 8 - .../FishNet/Runtime/Plugins/Yak/CHANGELOG.txt | 2 - .../Runtime/Plugins/Yak/CHANGELOG.txt.meta | 7 - Assets/FishNet/Runtime/Plugins/Yak/Core.meta | 8 - .../Runtime/Plugins/Yak/Core/ClientSocket.cs | 0 .../Plugins/Yak/Core/ClientSocket.cs.meta | 11 - .../Runtime/Plugins/Yak/Core/CommonSocket.cs | 0 .../Plugins/Yak/Core/CommonSocket.cs.meta | 11 - .../Runtime/Plugins/Yak/Core/LocalPacket.cs | 1 - .../Plugins/Yak/Core/LocalPacket.cs.meta | 11 - .../Runtime/Plugins/Yak/Core/ServerSocket.cs | 0 .../Plugins/Yak/Core/ServerSocket.cs.meta | 11 - .../FishNet/Runtime/Plugins/Yak/VERSION.txt | 1 - .../Runtime/Plugins/Yak/VERSION.txt.meta | 7 - Assets/FishNet/Runtime/Plugins/Yak/Yak.cs | 0 .../FishNet/Runtime/Plugins/Yak/Yak.cs.meta | 11 - Assets/FishNet/Runtime/Serializing.meta | 8 - .../Runtime/Serializing/AutoPackType.cs | 21 - .../Runtime/Serializing/AutoPackType.cs.meta | 11 - .../FishNet/Runtime/Serializing/Helping.meta | 8 - .../Runtime/Serializing/Helping/Attributes.cs | 26 - .../Serializing/Helping/Attributes.cs.meta | 11 - .../Runtime/Serializing/Helping/Broadcasts.cs | 38 - .../Serializing/Helping/Broadcasts.cs.meta | 11 - .../Runtime/Serializing/Helping/Comparers.cs | 66 - .../Serializing/Helping/Comparers.cs.meta | 11 - .../Serializing/Helping/Quaternion32.cs | 163 - .../Serializing/Helping/Quaternion32.cs.meta | 11 - .../Serializing/Helping/Quaternion64.cs | 192 - .../Serializing/Helping/Quaternion64.cs.meta | 11 - .../Helping/QuaternionConverter.cs | 126 - .../Helping/QuaternionConverter.cs.meta | 11 - .../Serializing/Helping/ValueConversions.cs | 41 - .../Helping/ValueConversions.cs.meta | 11 - Assets/FishNet/Runtime/Serializing/Reader.cs | 1421 ------ .../Runtime/Serializing/Reader.cs.meta | 11 - .../Runtime/Serializing/ReaderExtensions.cs | 18 - .../Serializing/ReaderExtensions.cs.meta | 11 - .../FishNet/Runtime/Serializing/ReaderPool.cs | 68 - .../Runtime/Serializing/ReaderPool.cs.meta | 11 - .../Runtime/Serializing/ReaderStatics.cs | 47 - .../Runtime/Serializing/ReaderStatics.cs.meta | 11 - .../Runtime/Serializing/SceneComparer.cs | 18 - .../Runtime/Serializing/SceneComparer.cs.meta | 11 - .../Serializing/TransformPackingData.cs | 10 - .../Serializing/TransformPackingData.cs.meta | 11 - Assets/FishNet/Runtime/Serializing/Writer.cs | 1331 ------ .../Runtime/Serializing/Writer.cs.meta | 11 - .../Runtime/Serializing/WriterExtensions.cs | 113 - .../Serializing/WriterExtensions.cs.meta | 11 - .../FishNet/Runtime/Serializing/WriterPool.cs | 159 - .../Runtime/Serializing/WriterPool.cs.meta | 11 - .../Runtime/Serializing/WriterStatics.cs | 61 - .../Runtime/Serializing/WriterStatics.cs.meta | 11 - Assets/FishNet/Runtime/Transporting.meta | 8 - .../FishNet/Runtime/Transporting/Channels.cs | 19 - .../Runtime/Transporting/Channels.cs.meta | 11 - .../Runtime/Transporting/ConnectionStates.cs | 43 - .../Transporting/ConnectionStates.cs.meta | 11 - .../Runtime/Transporting/EventStructures.cs | 152 - .../Transporting/EventStructures.cs.meta | 11 - .../Runtime/Transporting/IPAddressType.cs | 19 - .../Transporting/IPAddressType.cs.meta | 11 - .../Runtime/Transporting/NetworkReaderLoop.cs | 33 - .../Transporting/NetworkReaderLoop.cs.meta | 11 - .../Runtime/Transporting/NetworkWriterLoop.cs | 38 - .../Transporting/NetworkWriterLoop.cs.meta | 11 - .../FishNet/Runtime/Transporting/PacketId.cs | 33 - .../Runtime/Transporting/PacketId.cs.meta | 11 - .../FishNet/Runtime/Transporting/Transport.cs | 243 - .../Runtime/Transporting/Transport.cs.meta | 11 - .../Runtime/Transporting/Transports.meta | 8 - .../Transporting/Transports/Multipass.meta | 8 - .../Transports/Multipass/CHANGELOG.txt | 2 - .../Transports/Multipass/CHANGELOG.txt.meta | 7 - .../Transports/Multipass/Multipass.cs | 946 ---- .../Transports/Multipass/Multipass.cs.meta | 11 - .../Transports/Multipass/VERSION.txt | 1 - .../Transports/Multipass/VERSION.txt.meta | 7 - .../Transporting/Transports/Tugboat.meta | 8 - .../Transporting/Transports/Tugboat/Core.meta | 8 - .../Transports/Tugboat/Core/ClientSocket.cs | 307 -- .../Tugboat/Core/ClientSocket.cs.meta | 11 - .../Transports/Tugboat/Core/CommonSocket.cs | 125 - .../Tugboat/Core/CommonSocket.cs.meta | 11 - .../Transports/Tugboat/Core/ServerSocket.cs | 523 --- .../Tugboat/Core/ServerSocket.cs.meta | 11 - .../Transports/Tugboat/Core/Supporting.cs | 63 - .../Tugboat/Core/Supporting.cs.meta | 11 - .../Transports/Tugboat/LiteNetLib.meta | 8 - .../Tugboat/LiteNetLib/BaseChannel.cs | 46 - .../Tugboat/LiteNetLib/BaseChannel.cs.meta | 11 - .../Tugboat/LiteNetLib/ConnectionRequest.cs | 134 - .../LiteNetLib/ConnectionRequest.cs.meta | 11 - .../Tugboat/LiteNetLib/INetEventListener.cs | 272 -- .../LiteNetLib/INetEventListener.cs.meta | 11 - .../Tugboat/LiteNetLib/InternalPackets.cs | 133 - .../LiteNetLib/InternalPackets.cs.meta | 11 - .../Transports/Tugboat/LiteNetLib/Layers.meta | 8 - .../Tugboat/LiteNetLib/Layers/Crc32cLayer.cs | 41 - .../LiteNetLib/Layers/Crc32cLayer.cs.meta | 11 - .../LiteNetLib/Layers/PacketLayerBase.cs | 17 - .../LiteNetLib/Layers/PacketLayerBase.cs.meta | 11 - .../LiteNetLib/Layers/XorEncryptLayer.cs | 60 - .../LiteNetLib/Layers/XorEncryptLayer.cs.meta | 11 - .../Tugboat/LiteNetLib/NatPunchModule.cs | 259 -- .../Tugboat/LiteNetLib/NatPunchModule.cs.meta | 11 - .../Tugboat/LiteNetLib/NativeSocket.cs | 301 -- .../Tugboat/LiteNetLib/NativeSocket.cs.meta | 11 - .../Tugboat/LiteNetLib/NetConstants.cs | 75 - .../Tugboat/LiteNetLib/NetConstants.cs.meta | 11 - .../Transports/Tugboat/LiteNetLib/NetDebug.cs | 92 - .../Tugboat/LiteNetLib/NetDebug.cs.meta | 11 - .../LiteNetLib/NetManager.PacketPool.cs | 80 - .../LiteNetLib/NetManager.PacketPool.cs.meta | 11 - .../Tugboat/LiteNetLib/NetManager.Socket.cs | 701 --- .../LiteNetLib/NetManager.Socket.cs.meta | 11 - .../Tugboat/LiteNetLib/NetManager.cs | 1789 -------- .../Tugboat/LiteNetLib/NetManager.cs.meta | 11 - .../Tugboat/LiteNetLib/NetPacket.cs | 161 - .../Tugboat/LiteNetLib/NetPacket.cs.meta | 11 - .../Transports/Tugboat/LiteNetLib/NetPeer.cs | 1405 ------ .../Tugboat/LiteNetLib/NetPeer.cs.meta | 11 - .../Tugboat/LiteNetLib/NetStatistics.cs | 81 - .../Tugboat/LiteNetLib/NetStatistics.cs.meta | 11 - .../Transports/Tugboat/LiteNetLib/NetUtils.cs | 194 - .../Tugboat/LiteNetLib/NetUtils.cs.meta | 11 - .../Tugboat/LiteNetLib/PausedSocketFix.cs | 75 - .../LiteNetLib/PausedSocketFix.cs.meta | 11 - .../Tugboat/LiteNetLib/PooledPacket.cs | 32 - .../Tugboat/LiteNetLib/PooledPacket.cs.meta | 11 - .../Tugboat/LiteNetLib/ReliableChannel.cs | 336 -- .../LiteNetLib/ReliableChannel.cs.meta | 11 - .../Tugboat/LiteNetLib/SequencedChannel.cs | 110 - .../LiteNetLib/SequencedChannel.cs.meta | 11 - .../Transports/Tugboat/LiteNetLib/Utils.meta | 8 - .../Tugboat/LiteNetLib/Utils/CRC32C.cs | 150 - .../Tugboat/LiteNetLib/Utils/CRC32C.cs.meta | 11 - .../LiteNetLib/Utils/FastBitConverter.cs | 175 - .../LiteNetLib/Utils/FastBitConverter.cs.meta | 11 - .../LiteNetLib/Utils/INetSerializable.cs | 8 - .../LiteNetLib/Utils/INetSerializable.cs.meta | 11 - .../Tugboat/LiteNetLib/Utils/NetDataReader.cs | 680 --- .../LiteNetLib/Utils/NetDataReader.cs.meta | 11 - .../Tugboat/LiteNetLib/Utils/NetDataWriter.cs | 379 -- .../LiteNetLib/Utils/NetDataWriter.cs.meta | 11 - .../LiteNetLib/Utils/NetPacketProcessor.cs | 296 -- .../Utils/NetPacketProcessor.cs.meta | 11 - .../Tugboat/LiteNetLib/Utils/NetSerializer.cs | 738 ---- .../LiteNetLib/Utils/NetSerializer.cs.meta | 11 - .../Tugboat/LiteNetLib/Utils/NtpPacket.cs | 423 -- .../LiteNetLib/Utils/NtpPacket.cs.meta | 11 - .../Tugboat/LiteNetLib/Utils/NtpRequest.cs | 42 - .../LiteNetLib/Utils/NtpRequest.cs.meta | 11 - .../Transports/Tugboat/Tugboat.cs | 505 --- .../Transports/Tugboat/Tugboat.cs.meta | 11 - Assets/FishNet/Runtime/Utility.meta | 8 - .../Runtime/Utility/ApplicationState.cs | 64 - .../Runtime/Utility/ApplicationState.cs.meta | 11 - Assets/FishNet/Runtime/Utility/Constants.cs | 12 - .../FishNet/Runtime/Utility/Constants.cs.meta | 11 - Assets/FishNet/Runtime/Utility/DDOLFinder.cs | 60 - .../Runtime/Utility/DDOLFinder.cs.meta | 11 - Assets/FishNet/Runtime/Utility/Editor.meta | 8 - .../Runtime/Utility/Editor/SceneDrawer.cs | 51 - .../Utility/Editor/SceneDrawer.cs.meta | 11 - Assets/FishNet/Runtime/Utility/Extension.meta | 8 - .../FishNet/Runtime/Utility/Extension/Bool.cs | 18 - .../Runtime/Utility/Extension/Bool.cs.meta | 11 - .../Runtime/Utility/Extension/Collection.cs | 33 - .../Utility/Extension/Collection.cs.meta | 11 - .../Runtime/Utility/Extension/Dictionary.cs | 35 - .../Utility/Extension/Dictionary.cs.meta | 11 - .../FishNet/Runtime/Utility/Extension/Enum.cs | 31 - .../Runtime/Utility/Extension/Enum.cs.meta | 11 - .../FishNet/Runtime/Utility/Extension/List.cs | 24 - .../Runtime/Utility/Extension/List.cs.meta | 11 - .../FishNet/Runtime/Utility/Extension/Math.cs | 34 - .../Runtime/Utility/Extension/Math.cs.meta | 11 - .../Runtime/Utility/Extension/Object.cs | 27 - .../Runtime/Utility/Extension/Object.cs.meta | 11 - .../Runtime/Utility/Extension/Quaternion.cs | 43 - .../Utility/Extension/Quaternion.cs.meta | 11 - .../Runtime/Utility/Extension/Scene.cs | 76 - .../Runtime/Utility/Extension/Scene.cs.meta | 11 - .../Runtime/Utility/Extension/Transforms.cs | 42 - .../Utility/Extension/Transforms.cs.meta | 11 - .../FishNet/Runtime/Utility/Performance.meta | 8 - .../Utility/Performance/ByteArrayPool.cs | 53 - .../Utility/Performance/ByteArrayPool.cs.meta | 11 - .../Utility/Performance/DefaultObjectPool.cs | 203 - .../Performance/DefaultObjectPool.cs.meta | 11 - .../Runtime/Utility/Performance/ListCache.cs | 341 -- .../Utility/Performance/ListCache.cs.meta | 11 - .../Runtime/Utility/Performance/ObjectPool.cs | 47 - .../Utility/Performance/ObjectPool.cs.meta | 11 - .../Runtime/Utility/Performance/RingBuffer.cs | 339 -- .../Utility/Performance/RingBuffer.cs.meta | 11 - .../Runtime/Utility/Performance/Transforms.cs | 39 - .../Utility/Performance/Transforms.cs.meta | 11 - .../FishNet/Runtime/Utility/SceneAttribute.cs | 12 - .../Runtime/Utility/SceneAttribute.cs.meta | 11 - Assets/FishNet/THIRD PARTY NOTICE.md | 82 - Assets/FishNet/THIRD PARTY NOTICE.md.meta | 7 - Assets/FishNet/Upgrading.meta | 8 - Assets/FishNet/Upgrading/MirrorUpgrade.cs | 428 -- .../FishNet/Upgrading/MirrorUpgrade.cs.meta | 11 - .../Upgrading/UpgradeFromMirrorMenu.cs | 75 - .../Upgrading/UpgradeFromMirrorMenu.cs.meta | 11 - Assets/FishNet/VERSION.txt | 1 - Assets/FishNet/VERSION.txt.meta | 7 - Assets/Packages/Facepunch.meta | 8 - .../Facepunch/Facepunch.Steamworks.Posix.dll | Bin 545280 -> 0 bytes .../Facepunch/Facepunch.Steamworks.Posix.xml | 3571 --------------- .../Facepunch.Steamworks.Posix.xml.meta | 7 - .../Facepunch/Facepunch.Steamworks.Win32.dll | Bin 546816 -> 0 bytes .../Facepunch/Facepunch.Steamworks.Win32.xml | 3571 --------------- .../Facepunch.Steamworks.Win32.xml.meta | 7 - .../Facepunch/Facepunch.Steamworks.Win64.dll | Bin 546816 -> 0 bytes .../Facepunch.Steamworks.Win64.dll.meta | 95 - .../Facepunch/Facepunch.Steamworks.Win64.xml | 3571 --------------- .../Facepunch.Steamworks.Win64.xml.meta | 7 - .../Facepunch/redistributable_bin.meta | 8 - .../redistributable_bin/linux32.meta | 8 - .../linux32/libsteam_api.so | Bin 403896 -> 0 bytes .../linux32/libsteam_api.so.meta | 89 - .../redistributable_bin/linux64.meta | 8 - .../linux64/libsteam_api.so | Bin 398662 -> 0 bytes .../Facepunch/redistributable_bin/osx.meta | 8 - .../osx/libsteam_api.bundle | Bin 446352 -> 0 bytes .../osx/libsteam_api.bundle.meta | 32 - .../redistributable_bin/steam_api.dll | Bin 237856 -> 0 bytes .../redistributable_bin/steam_api.lib | Bin 344672 -> 0 bytes .../redistributable_bin/steam_api.lib.meta | 7 - .../Facepunch/redistributable_bin/win64.meta | 8 - .../redistributable_bin/win64/steam_api64.dll | Bin 262944 -> 0 bytes .../win64/steam_api64.dll.meta | 89 - .../redistributable_bin/win64/steam_api64.lib | Bin 341696 -> 0 bytes .../win64/steam_api64.lib.meta | 7 - Assets/Scenes/StartScreen2.unity | 54 +- Assets/Scripts/MainMenu/MainMenuManager.cs | 16 + Assets/Scripts/Steam.meta | 8 - Assets/Scripts/Steam/FriendObject.cs | 30 - Assets/Scripts/Steam/FriendObject.cs.meta | 11 - Assets/Scripts/Steam/SteamFriendsManager.cs | 74 - .../Scripts/Steam/SteamFriendsManager.cs.meta | 11 - Assets/Scripts/Steam/SteamLobbyManager.cs | 183 - .../Scripts/Steam/SteamLobbyManager.cs.meta | 11 - Assets/Scripts/Steam/SteamLobbyWithPlayer.cs | 164 - .../Steam/SteamLobbyWithPlayer.cs.meta | 11 - Assets/Scripts/Steam/SteamManager.cs | 39 - Assets/Scripts/Steamworks.NET.meta | 5 + Assets/Scripts/Steamworks.NET/SteamManager.cs | 182 + .../SteamManager.cs.meta | 5 +- .../Electronic Highway Sign SDF.asset | 527 +-- ...eta => com.rlabrecque.steamworks.net.meta} | 2 +- .../Editor.meta | 2 +- .../Editor/RedistCopy.cs | 76 + .../Editor/RedistCopy.cs.meta} | 2 +- .../Editor/RedistInstall.cs | 70 + .../Editor/RedistInstall.cs.meta} | 2 +- ...om.rlabrecque.steamworks.net.editor.asmdef | 18 + ...brecque.steamworks.net.editor.asmdef.meta} | 2 +- .../LICENSE.md} | 12 +- .../LICENSE.md.meta} | 2 +- .../Plugins.meta | 2 +- .../Plugins/libsteam_api.so | Bin 0 -> 391056 bytes .../Plugins/libsteam_api.so.meta} | 43 +- .../Plugins/steam_api.bundle.meta} | 34 +- .../Plugins/steam_api.bundle/Contents.meta} | 2 +- .../steam_api.bundle/Contents/Info.plist | 38 + .../Contents/Info.plist.meta} | 2 +- .../steam_api.bundle/Contents/MacOS.meta} | 2 +- .../Contents/MacOS/libsteam_api.dylib | Bin 0 -> 610496 bytes .../Contents/MacOS/libsteam_api.dylib.meta} | 2 +- .../Plugins/steam_api.dll | Bin 0 -> 266600 bytes .../Plugins}/steam_api.dll.meta | 43 +- .../Plugins/steam_api64.dll | Bin 0 -> 298856 bytes .../Plugins/steam_api64.dll.meta} | 47 +- .../com.rlabrecque.steamworks.net/README.md | 15 + .../README.md.meta | 2 +- .../Runtime.meta | 2 +- .../Runtime/CallbackDispatcher.cs | 400 ++ .../Runtime/CallbackDispatcher.cs.meta} | 2 +- .../Runtime/CallbackIdentity.cs | 35 + .../Runtime/CallbackIdentity.cs.meta} | 2 +- .../Runtime/ISteamMatchmakingResponses.cs | 490 +++ .../ISteamMatchmakingResponses.cs.meta | 11 + .../Runtime/InteropHelp.cs | 267 ++ .../Runtime/InteropHelp.cs.meta | 11 + .../Runtime/Packsize.cs | 71 + .../Runtime/Packsize.cs.meta | 11 + .../Runtime/Steam.cs | 568 +++ .../Runtime/Steam.cs.meta | 11 + .../Runtime/Version.cs | 24 + .../Runtime/Version.cs.meta | 11 + .../Runtime/autogen.meta} | 2 +- .../Runtime/autogen/NativeMethods.cs | 3337 ++++++++++++++ .../Runtime/autogen/NativeMethods.cs.meta | 11 + .../Runtime/autogen/SteamCallbacks.cs | 2939 +++++++++++++ .../Runtime/autogen/SteamCallbacks.cs.meta | 11 + .../Runtime/autogen/SteamConstants.cs | 330 ++ .../Runtime/autogen/SteamConstants.cs.meta | 11 + .../Runtime/autogen/SteamEnums.cs | 2787 ++++++++++++ .../Runtime/autogen/SteamEnums.cs.meta | 11 + .../Runtime/autogen/SteamStructs.cs | 452 ++ .../Runtime/autogen/SteamStructs.cs.meta | 11 + .../Runtime/autogen/isteamapplist.cs | 63 + .../Runtime/autogen/isteamapplist.cs.meta | 11 + .../Runtime/autogen/isteamapps.cs | 277 ++ .../Runtime/autogen/isteamapps.cs.meta | 11 + .../Runtime/autogen/isteamclient.cs | 376 ++ .../Runtime/autogen/isteamclient.cs.meta | 11 + .../Runtime/autogen/isteamfriends.cs | 688 +++ .../Runtime/autogen/isteamfriends.cs.meta | 11 + .../Runtime/autogen/isteamgameserver.cs | 450 ++ .../Runtime/autogen/isteamgameserver.cs.meta | 11 + .../Runtime/autogen/isteamgameserverclient.cs | 376 ++ .../autogen/isteamgameserverclient.cs.meta | 11 + .../Runtime/autogen/isteamgameserverhttp.cs | 277 ++ .../autogen/isteamgameserverhttp.cs.meta | 11 + .../autogen/isteamgameserverinventory.cs | 478 ++ .../autogen/isteamgameserverinventory.cs.meta | 11 + .../autogen/isteamgameservernetworking.cs | 270 ++ .../isteamgameservernetworking.cs.meta | 11 + .../isteamgameservernetworkingsockets.cs | 1111 +++++ .../isteamgameservernetworkingsockets.cs.meta | 11 + .../isteamgameservernetworkingutils.cs | 444 ++ .../isteamgameservernetworkingutils.cs.meta | 11 + .../Runtime/autogen/isteamgameserverstats.cs | 110 + .../autogen/isteamgameserverstats.cs.meta | 11 + .../Runtime/autogen/isteamgameserverugc.cs | 709 +++ .../autogen/isteamgameserverugc.cs.meta | 11 + .../Runtime/autogen/isteamgameserverutils.cs | 356 ++ .../autogen/isteamgameserverutils.cs.meta | 11 + .../Runtime/autogen/isteamhtmlsurface.cs | 341 ++ .../Runtime/autogen/isteamhtmlsurface.cs.meta | 11 + .../Runtime/autogen/isteamhttp.cs | 277 ++ .../Runtime/autogen/isteamhttp.cs.meta | 11 + .../Runtime/autogen/isteaminput.cs | 476 ++ .../Runtime/autogen/isteaminput.cs.meta | 11 + .../Runtime/autogen/isteaminventory.cs | 478 ++ .../Runtime/autogen/isteaminventory.cs.meta | 11 + .../Runtime/autogen/isteammatchmaking.cs | 892 ++++ .../Runtime/autogen/isteammatchmaking.cs.meta | 11 + .../Runtime/autogen/isteammusic.cs | 69 + .../Runtime/autogen/isteammusic.cs.meta | 11 + .../Runtime/autogen/isteammusicremote.cs | 212 + .../Runtime/autogen/isteammusicremote.cs.meta | 11 + .../Runtime/autogen/isteamnetworking.cs | 270 ++ .../Runtime/autogen/isteamnetworking.cs.meta | 11 + .../autogen/isteamnetworkingmessages.cs | 139 + .../autogen/isteamnetworkingmessages.cs.meta | 11 + .../autogen/isteamnetworkingsockets.cs | 1111 +++++ .../autogen/isteamnetworkingsockets.cs.meta | 11 + .../Runtime/autogen/isteamnetworkingutils.cs | 444 ++ .../autogen/isteamnetworkingutils.cs.meta | 11 + .../Runtime/autogen/isteamparentalsettings.cs | 51 + .../autogen/isteamparentalsettings.cs.meta | 11 + .../Runtime/autogen/isteamremoteplay.cs | 80 + .../Runtime/autogen/isteamremoteplay.cs.meta | 11 + .../Runtime/autogen/isteamremotestorage.cs | 434 ++ .../autogen/isteamremotestorage.cs.meta | 11 + .../Runtime/autogen/isteamscreenshots.cs | 111 + .../Runtime/autogen/isteamscreenshots.cs.meta | 11 + .../Runtime/autogen/isteamugc.cs | 709 +++ .../Runtime/autogen/isteamugc.cs.meta | 11 + .../Runtime/autogen/isteamuser.cs | 381 ++ .../Runtime/autogen/isteamuser.cs.meta | 11 + .../Runtime/autogen/isteamuserstats.cs | 474 ++ .../Runtime/autogen/isteamuserstats.cs.meta | 11 + .../Runtime/autogen/isteamutils.cs | 356 ++ .../Runtime/autogen/isteamutils.cs.meta | 11 + .../Runtime/autogen/isteamvideo.cs | 54 + .../Runtime/autogen/isteamvideo.cs.meta | 11 + .../com.rlabrecque.steamworks.net.asmdef | 20 + ...com.rlabrecque.steamworks.net.asmdef.meta} | 2 +- .../Runtime/types.meta | 8 + .../Runtime/types/MatchmakingTypes.meta | 8 + .../MatchmakingTypes/gameserveritem_t.cs | 106 + .../MatchmakingTypes/gameserveritem_t.cs.meta | 11 + .../types/MatchmakingTypes/servernetadr_t.cs | 116 + .../MatchmakingTypes/servernetadr_t.cs.meta | 11 + .../Runtime/types/SteamClient.meta | 8 + .../SteamAPIWarningMessageHook_t.cs | 22 + .../SteamAPIWarningMessageHook_t.cs.meta | 11 + .../SteamAPI_CheckCallbackRegistered_t.cs | 22 + ...SteamAPI_CheckCallbackRegistered_t.cs.meta | 11 + .../Runtime/types/SteamClientPublic.meta | 8 + .../types/SteamClientPublic/CGameID.cs | 154 + .../types/SteamClientPublic/CGameID.cs.meta | 11 + .../types/SteamClientPublic/CSteamID.cs | 269 ++ .../types/SteamClientPublic/CSteamID.cs.meta | 11 + .../types/SteamClientPublic/HAuthTicket.cs | 65 + .../SteamClientPublic/HAuthTicket.cs.meta | 11 + .../Runtime/types/SteamDatagramTickets.meta | 8 + .../SteamDatagramHostedAddress.cs | 44 + .../SteamDatagramHostedAddress.cs.meta | 11 + .../SteamDatagramRelayAuthTicket.cs | 144 + .../SteamDatagramRelayAuthTicket.cs.meta | 11 + .../Runtime/types/SteamFriends.meta | 8 + .../types/SteamFriends/FriendsGroupID_t.cs | 65 + .../SteamFriends/FriendsGroupID_t.cs.meta | 11 + .../Runtime/types/SteamHTMLSurface.meta | 8 + .../types/SteamHTMLSurface/HHTMLBrowser.cs | 65 + .../SteamHTMLSurface/HHTMLBrowser.cs.meta | 11 + .../Runtime/types/SteamHTTP.meta | 8 + .../SteamHTTP/HTTPCookieContainerHandle.cs | 65 + .../HTTPCookieContainerHandle.cs.meta | 11 + .../types/SteamHTTP/HTTPRequestHandle.cs | 65 + .../types/SteamHTTP/HTTPRequestHandle.cs.meta | 11 + .../Runtime/types/SteamInput.meta | 8 + .../SteamInput/InputActionSetHandle_t.cs | 64 + .../SteamInput/InputActionSetHandle_t.cs.meta | 11 + .../SteamInput/InputAnalogActionHandle_t.cs | 64 + .../InputAnalogActionHandle_t.cs.meta | 11 + .../SteamInput/InputDigitalActionHandle_t.cs | 64 + .../InputDigitalActionHandle_t.cs.meta | 11 + .../Runtime/types/SteamInput/InputHandle_t.cs | 64 + .../types/SteamInput/InputHandle_t.cs.meta | 11 + .../SteamInputActionEventCallbackPointer.cs | 22 + ...eamInputActionEventCallbackPointer.cs.meta | 11 + .../SteamInput/SteamInputActionEvent_t.cs | 65 + .../SteamInputActionEvent_t.cs.meta | 11 + .../Runtime/types/SteamInventory.meta | 8 + .../SteamInventory/SteamInventoryResult_t.cs | 65 + .../SteamInventoryResult_t.cs.meta | 11 + .../SteamInventoryUpdateHandle_t.cs | 65 + .../SteamInventoryUpdateHandle_t.cs.meta | 11 + .../types/SteamInventory/SteamItemDef_t.cs | 64 + .../SteamInventory/SteamItemDef_t.cs.meta | 11 + .../SteamInventory/SteamItemInstanceID_t.cs | 65 + .../SteamItemInstanceID_t.cs.meta | 11 + .../Runtime/types/SteamMatchmaking.meta | 8 + .../SteamMatchmaking/HServerListRequest.cs | 61 + .../HServerListRequest.cs.meta | 11 + .../types/SteamMatchmaking/HServerQuery.cs | 65 + .../SteamMatchmaking/HServerQuery.cs.meta | 11 + .../Runtime/types/SteamNetworking.meta | 8 + .../SteamNetworking/SNetListenSocket_t.cs | 64 + .../SNetListenSocket_t.cs.meta | 11 + .../types/SteamNetworking/SNetSocket_t.cs | 64 + .../SteamNetworking/SNetSocket_t.cs.meta | 11 + .../Runtime/types/SteamNetworkingSockets.meta | 8 + .../ISteamNetworkingConnectionSignaling.cs | 65 + ...SteamNetworkingConnectionSignaling.cs.meta | 11 + .../ISteamNetworkingSignalingRecvContext.cs | 65 + ...teamNetworkingSignalingRecvContext.cs.meta | 11 + .../Runtime/types/SteamNetworkingTypes.meta | 8 + .../FSteamNetworkingSocketsDebugOutput.cs | 23 + ...FSteamNetworkingSocketsDebugOutput.cs.meta | 11 + .../HSteamListenSocket.cs | 65 + .../HSteamListenSocket.cs.meta | 11 + .../HSteamNetConnection.cs | 65 + .../HSteamNetConnection.cs.meta | 11 + .../HSteamNetPollGroup.cs | 65 + .../HSteamNetPollGroup.cs.meta | 11 + .../SteamNetworkingConfigValue_t.cs | 64 + .../SteamNetworkingConfigValue_t.cs.meta | 11 + .../SteamNetworkingErrMsg.cs | 30 + .../SteamNetworkingErrMsg.cs.meta | 11 + .../SteamNetworkingIPAddr.cs | 114 + .../SteamNetworkingIPAddr.cs.meta | 11 + .../SteamNetworkingIdentity.cs | 212 + .../SteamNetworkingIdentity.cs.meta | 11 + .../SteamNetworkingMessage_t.cs | 124 + .../SteamNetworkingMessage_t.cs.meta | 11 + .../SteamNetworkingMicroseconds.cs | 64 + .../SteamNetworkingMicroseconds.cs.meta | 11 + .../SteamNetworkingPOPID.cs | 64 + .../SteamNetworkingPOPID.cs.meta | 11 + .../Runtime/types/SteamRemotePlay.meta | 8 + .../SteamRemotePlay/RemotePlaySessionID_t.cs | 64 + .../RemotePlaySessionID_t.cs.meta | 11 + .../Runtime/types/SteamRemoteStorage.meta | 8 + .../SteamRemoteStorage/PublishedFileId_t.cs | 65 + .../PublishedFileId_t.cs.meta | 11 + .../PublishedFileUpdateHandle_t.cs | 65 + .../PublishedFileUpdateHandle_t.cs.meta | 11 + .../UGCFileWriteStreamHandle_t.cs | 65 + .../UGCFileWriteStreamHandle_t.cs.meta | 11 + .../types/SteamRemoteStorage/UGCHandle_t.cs | 65 + .../SteamRemoteStorage/UGCHandle_t.cs.meta | 11 + .../Runtime/types/SteamScreenshots.meta | 8 + .../SteamScreenshots/ScreenshotHandle.cs | 65 + .../SteamScreenshots/ScreenshotHandle.cs.meta | 11 + .../Runtime/types/SteamTypes.meta | 8 + .../Runtime/types/SteamTypes/AccountID_t.cs | 64 + .../types/SteamTypes/AccountID_t.cs.meta | 11 + .../Runtime/types/SteamTypes/AppId_t.cs | 65 + .../Runtime/types/SteamTypes/AppId_t.cs.meta | 11 + .../Runtime/types/SteamTypes/DepotId_t.cs | 65 + .../types/SteamTypes/DepotId_t.cs.meta | 11 + .../types/SteamTypes/PartyBeaconID_t.cs | 65 + .../types/SteamTypes/PartyBeaconID_t.cs.meta | 11 + .../Runtime/types/SteamTypes/RTime32.cs | 64 + .../Runtime/types/SteamTypes/RTime32.cs.meta | 11 + .../types/SteamTypes/SteamAPICall_t.cs | 65 + .../types/SteamTypes/SteamAPICall_t.cs.meta | 11 + .../types/SteamTypes/SteamIPAddress_t.cs | 97 + .../types/SteamTypes/SteamIPAddress_t.cs.meta | 11 + .../Runtime/types/SteamUGC.meta | 8 + .../types/SteamUGC/UGCQueryHandle_t.cs | 65 + .../types/SteamUGC/UGCQueryHandle_t.cs.meta | 11 + .../types/SteamUGC/UGCUpdateHandle_t.cs | 65 + .../types/SteamUGC/UGCUpdateHandle_t.cs.meta | 11 + .../Runtime/types/SteamUserStats.meta | 8 + .../SteamLeaderboardEntries_t.cs | 64 + .../SteamLeaderboardEntries_t.cs.meta | 11 + .../SteamUserStats/SteamLeaderboard_t.cs | 64 + .../SteamUserStats/SteamLeaderboard_t.cs.meta | 11 + .../Runtime/types/Steam_api_common.meta | 8 + .../types/Steam_api_common/HSteamPipe.cs | 64 + .../types/Steam_api_common/HSteamPipe.cs.meta | 11 + .../types/Steam_api_common/HSteamUser.cs | 64 + .../types/Steam_api_common/HSteamUser.cs.meta | 11 + .../package.json | 21 + .../package.json.meta} | 4 +- .../BurstAotSettings_StandaloneOSX.json | 16 + ProjectSettings/ProjectSettings.asset | 2 +- steam_appid.txt | 1 + 1614 files changed, 31598 insertions(+), 142081 deletions(-) delete mode 100644 Assets/FishNet/CodeGenerating/Extension/ILProcessorExtensions.cs delete mode 100644 Assets/FishNet/CodeGenerating/Extension/MethodDefinitionExtensions.cs delete mode 100644 Assets/FishNet/CodeGenerating/Extension/TypeDefinitionExtensions.cs delete mode 100644 Assets/FishNet/CodeGenerating/Extension/TypeReferenceExtensions.cs delete mode 100644 Assets/FishNet/CodeGenerating/FN_README.txt delete mode 100644 Assets/FishNet/CodeGenerating/FN_README.txt.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/FieldReferenceExtensions.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/FieldReferenceExtensions.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/MethodDefinitionExtensions.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/MethodDefinitionExtensions.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/ModuleDefinitionExtensions.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/ModuleDefinitionExtensions.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/ParameterDefinitionExtensions.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/ParameterDefinitionExtensions.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/TypeDefinitionExtensions.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/TypeDefinitionExtensions.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/TypeReferenceExtensions.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Extension/TypeReferenceExtensions.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/GeneralHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/GeneralHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/GenericReaderHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/GenericReaderHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/GenericWriterHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/GenericWriterHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/NetworkBehaviourHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/NetworkBehaviourHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionImports.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionImports.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/ObjectHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/ObjectHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/PhysicsHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/PhysicsHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/PredictedObjectHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/PredictedObjectHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/ReaderGenerator.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/ReaderGenerator.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/ReaderHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/ReaderHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/ReaderImports.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/ReaderImports.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/TimeManagerHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/TimeManagerHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/TransportHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/TransportHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed/Comparers.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed/Comparers.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed/CreatedSyncType.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed/CreatedSyncType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed/GeneratorHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed/GeneratorHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed/QOLAttributeType.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed/QOLAttributeType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed/SerializatierType.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed/SerializatierType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed/SyncIndexData.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed/SyncIndexData.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed/SyncType.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/Typed/SyncType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/WriterGenerator.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/WriterGenerator.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/WriterHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/WriterHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/WriterImports.cs delete mode 100644 Assets/FishNet/CodeGenerating/Helpers/WriterImports.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/ILCore.meta delete mode 100644 Assets/FishNet/CodeGenerating/ILCore/FishNetILPP.cs delete mode 100644 Assets/FishNet/CodeGenerating/ILCore/FishNetILPP.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/ILCore/ILCoreHelper.cs delete mode 100644 Assets/FishNet/CodeGenerating/ILCore/ILCoreHelper.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/ILCore/PostProcessorAssemblyResolver.cs delete mode 100644 Assets/FishNet/CodeGenerating/ILCore/PostProcessorAssemblyResolver.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporter.cs delete mode 100644 Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporter.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporterProvider.cs delete mode 100644 Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporterProvider.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/CodegenBase.cs delete mode 100644 Assets/FishNet/CodeGenerating/Processing/CodegenBase.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/CustomSerializerProcessor.cs delete mode 100644 Assets/FishNet/CodeGenerating/Processing/CustomSerializerProcessor.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourProcessor.cs delete mode 100644 Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourProcessor.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourSyncProcessor.cs delete mode 100644 Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourSyncProcessor.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Prediction.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Prediction/PredictionProcessor.cs delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Prediction/PredictionProcessor.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/QOLAttributeProcessor.cs delete mode 100644 Assets/FishNet/CodeGenerating/Processing/QOLAttributeProcessor.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/ReaderProcessor.cs delete mode 100644 Assets/FishNet/CodeGenerating/Processing/ReaderProcessor.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Rpc.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Rpc/AttributeData.cs delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Rpc/AttributeData.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Rpc/Attributes.cs delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Rpc/Attributes.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Rpc/CreatedRpc.cs delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Rpc/CreatedRpc.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Rpc/RpcProcessor.cs delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Rpc/RpcProcessor.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Typed.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Typed/ProcessedSync.cs delete mode 100644 Assets/FishNet/CodeGenerating/Processing/Typed/ProcessedSync.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Processing/WriterProcessor.cs delete mode 100644 Assets/FishNet/CodeGenerating/Processing/WriterProcessor.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/Unity.FishNet.CodeGen.asmdef delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Directory.Build.props delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/LICENSE.txt delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Code.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Code.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeReader.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeReader.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeWriter.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeWriter.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Document.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Document.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ExceptionHandler.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ExceptionHandler.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ILProcessor.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ILProcessor.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Instruction.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Instruction.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/MethodBody.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/MethodBody.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCode.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCode.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCodes.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCodes.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/PortablePdb.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/PortablePdb.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/SequencePoint.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/SequencePoint.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Symbols.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Symbols.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableDefinition.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableDefinition.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableReference.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableReference.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/BlobHeap.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/BlobHeap.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Buffers.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Buffers.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/CodedIndex.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/CodedIndex.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/ElementType.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/ElementType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/GuidHeap.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/GuidHeap.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Heap.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Heap.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/MetadataToken.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/MetadataToken.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/PdbHeap.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/PdbHeap.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Row.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Row.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/StringHeap.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/StringHeap.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TableHeap.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TableHeap.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TokenType.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TokenType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/UserStringHeap.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/UserStringHeap.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Utilities.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Utilities.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamReader.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamReader.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamWriter.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamWriter.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBuffer.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBuffer.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBufferEqualityComparer.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBufferEqualityComparer.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/DataDirectory.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/DataDirectory.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Image.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Image.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageReader.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageReader.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageWriter.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageWriter.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Section.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Section.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/TextMap.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/TextMap.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Tests.props delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nunit delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nunit.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nuspec delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nuspec.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ArrayType.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ArrayType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyDefinition.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyDefinition.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyFlags.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyFlags.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyHashAlgorithm.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyHashAlgorithm.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyInfo.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyInfo.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyLinkedResource.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyLinkedResource.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameDefinition.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameDefinition.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameReference.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameReference.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyReader.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyReader.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyWriter.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyWriter.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/BaseAssemblyResolver.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/BaseAssemblyResolver.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CallSite.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CallSite.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Consts.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Consts.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CustomAttribute.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CustomAttribute.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/DefaultAssemblyResolver.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/DefaultAssemblyResolver.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EmbeddedResource.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EmbeddedResource.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventAttributes.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventAttributes.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventDefinition.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventDefinition.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventReference.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventReference.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ExportedType.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ExportedType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldAttributes.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldAttributes.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldDefinition.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldDefinition.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldReference.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldReference.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FileAttributes.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FileAttributes.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FunctionPointerType.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FunctionPointerType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceMethod.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceMethod.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceType.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameter.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameter.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterAttributes.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterAttributes.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterResolver.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterResolver.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IConstantProvider.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IConstantProvider.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ICustomAttributeProvider.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ICustomAttributeProvider.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericInstance.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericInstance.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericParameterProvider.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericParameterProvider.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMarshalInfoProvider.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMarshalInfoProvider.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMemberDefinition.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMemberDefinition.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataScope.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataScope.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataTokenProvider.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataTokenProvider.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMethodSignature.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMethodSignature.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Import.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Import.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/LinkedResource.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/LinkedResource.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ManifestResourceAttributes.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ManifestResourceAttributes.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MarshalInfo.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MarshalInfo.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberDefinitionCollection.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberDefinitionCollection.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberReference.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberReference.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataResolver.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataResolver.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataSystem.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataSystem.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodAttributes.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodAttributes.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodCallingConvention.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodCallingConvention.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodDefinition.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodDefinition.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodImplAttributes.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodImplAttributes.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReference.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReference.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReferenceComparer.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReferenceComparer.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReturnType.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReturnType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSemanticsAttributes.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSemanticsAttributes.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSpecification.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSpecification.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Modifiers.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Modifiers.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleDefinition.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleDefinition.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleKind.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleKind.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleReference.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleReference.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/NativeType.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/NativeType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeAttributes.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeAttributes.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeInfo.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeInfo.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterAttributes.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterAttributes.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinition.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinition.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinitionCollection.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinitionCollection.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterReference.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterReference.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PinnedType.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PinnedType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PointerType.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PointerType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyAttributes.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyAttributes.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyDefinition.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyDefinition.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyReference.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyReference.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ReferenceType.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ReferenceType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Resource.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Resource.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SecurityDeclaration.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SecurityDeclaration.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SentinelType.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SentinelType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TargetRuntime.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TargetRuntime.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Treatments.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Treatments.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeAttributes.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeAttributes.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeComparisonMode.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeComparisonMode.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinition.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinition.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinitionCollection.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinitionCollection.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeParser.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeParser.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReference.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReference.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReferenceEqualityComparer.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReferenceEqualityComparer.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeResolver.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeResolver.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSpecification.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSpecification.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSystem.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSystem.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/VariantType.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/VariantType.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/WindowsRuntimeProjections.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/WindowsRuntimeProjections.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/Collection.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/Collection.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/ReadOnlyCollection.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/ReadOnlyCollection.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoConvert.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoConvert.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoService.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoService.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Disposable.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Disposable.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Empty.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Empty.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/MergeSort.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/MergeSort.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/MonoFN.Cecil.asmdef delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/ProjectInfo.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/ProjectInfo.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/README.md delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/cecil.snk delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/cecil.snk.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/DocCommentId.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/DocCommentId.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/Functional.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/Functional.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ILParser.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ILParser.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ParameterReferenceRocks.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ParameterReferenceRocks.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs.meta delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs delete mode 100644 Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs.meta delete mode 100644 Assets/FishNet/DOCUMENTATION.txt delete mode 100644 Assets/FishNet/Demos.meta delete mode 100644 Assets/FishNet/Demos/FishNet.Demos.asmdef delete mode 100644 Assets/FishNet/Demos/FishNet.Demos.asmdef.meta delete mode 100644 Assets/FishNet/Demos/Network LOD.meta delete mode 100644 Assets/FishNet/Demos/Network LOD/Network LOD Demo README.txt delete mode 100644 Assets/FishNet/Demos/Network LOD/Network LOD Demo README.txt.meta delete mode 100644 Assets/FishNet/Demos/Network LOD/Prefabs.meta delete mode 100644 Assets/FishNet/Demos/Network LOD/Prefabs/NetworkLOD_Prefab.prefab delete mode 100644 Assets/FishNet/Demos/Network LOD/Prefabs/NetworkLOD_Prefab.prefab.meta delete mode 100644 Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.cs delete mode 100644 Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.cs.meta delete mode 100644 Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.inputactions delete mode 100644 Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.inputactions.meta delete mode 100644 Assets/FishNet/Demos/Network LOD/Prefabs/PlayerInputDriver.cs delete mode 100644 Assets/FishNet/Demos/Network LOD/Prefabs/PlayerInputDriver.cs.meta delete mode 100644 Assets/FishNet/Demos/Network LOD/Prefabs/PowerCore.prefab delete mode 100644 Assets/FishNet/Demos/Network LOD/Prefabs/PowerCore.prefab.meta delete mode 100644 Assets/FishNet/Demos/Network LOD/Prefabs/mydef.asmdef delete mode 100644 Assets/FishNet/Demos/Network LOD/Prefabs/mydef.asmdef.meta delete mode 100644 Assets/FishNet/Demos/Network LOD/Scenes.meta delete mode 100644 Assets/FishNet/Demos/Network LOD/Scenes/NetworkLOD_Demo.unity delete mode 100644 Assets/FishNet/Demos/Network LOD/Scenes/NetworkLOD_Demo.unity.meta delete mode 100644 Assets/FishNet/Demos/Network LOD/Scripts.meta delete mode 100644 Assets/FishNet/Demos/Network LOD/Scripts/MoveRandomly.cs delete mode 100644 Assets/FishNet/Demos/Network LOD/Scripts/MoveRandomly.cs.meta delete mode 100644 Assets/FishNet/Demos/Network LOD/Scripts/NetworkLodTester.cs delete mode 100644 Assets/FishNet/Demos/Network LOD/Scripts/NetworkLodTester.cs.meta delete mode 100644 Assets/FishNet/Example.meta delete mode 100644 Assets/FishNet/Example/All.meta delete mode 100644 Assets/FishNet/Example/All/Authenticator.meta delete mode 100644 Assets/FishNet/Example/All/Authenticator/Authenticator.unity delete mode 100644 Assets/FishNet/Example/All/Authenticator/Authenticator.unity.meta delete mode 100644 Assets/FishNet/Example/All/Authenticator/Scripts.meta delete mode 100644 Assets/FishNet/Example/All/Authenticator/Scripts/Broadcasts.cs delete mode 100644 Assets/FishNet/Example/All/Authenticator/Scripts/Broadcasts.cs.meta delete mode 100644 Assets/FishNet/Example/All/Authenticator/Scripts/HostAuthenticator.cs delete mode 100644 Assets/FishNet/Example/All/Authenticator/Scripts/HostAuthenticator.cs.meta delete mode 100644 Assets/FishNet/Example/All/Authenticator/Scripts/PasswordAuthenticator.cs delete mode 100644 Assets/FishNet/Example/All/Authenticator/Scripts/PasswordAuthenticator.cs.meta delete mode 100644 Assets/FishNet/Example/All/CustomSyncType.meta delete mode 100644 Assets/FishNet/Example/All/CustomSyncType/Component State Sync.meta delete mode 100644 Assets/FishNet/Example/All/CustomSyncType/Component State Sync/AMonoScript.cs delete mode 100644 Assets/FishNet/Example/All/CustomSyncType/Component State Sync/AMonoScript.cs.meta delete mode 100644 Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentStateSync.cs delete mode 100644 Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentStateSync.cs.meta delete mode 100644 Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentSyncStateBehaviour.cs delete mode 100644 Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentSyncStateBehaviour.cs.meta delete mode 100644 Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync.meta delete mode 100644 Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructSyncBehaviour.cs delete mode 100644 Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructSyncBehaviour.cs.meta delete mode 100644 Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructySync.cs delete mode 100644 Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructySync.cs.meta delete mode 100644 Assets/FishNet/Example/All/Prediction.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/CharacterController.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/CharacterController/CharacterControllerPrediction.unity delete mode 100644 Assets/FishNet/Example/All/Prediction/CharacterController/CharacterControllerPrediction.unity.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/CharacterController/Prefabs.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/CharacterController/Prefabs/CharacterControllerPrediction.prefab delete mode 100644 Assets/FishNet/Example/All/Prediction/CharacterController/Prefabs/CharacterControllerPrediction.prefab.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/CharacterController/Scripts.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/CharacterController/Scripts/CharacterControllerPrediction.cs delete mode 100644 Assets/FishNet/Example/All/Prediction/CharacterController/Scripts/CharacterControllerPrediction.cs.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Materials.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Materials/BlueMat.mat delete mode 100644 Assets/FishNet/Example/All/Prediction/Materials/BlueMat.mat.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Materials/GroundMat.mat delete mode 100644 Assets/FishNet/Example/All/Prediction/Materials/GroundMat.mat.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Materials/PurpleMat.mat delete mode 100644 Assets/FishNet/Example/All/Prediction/Materials/PurpleMat.mat.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Materials/YellowishMat.mat delete mode 100644 Assets/FishNet/Example/All/Prediction/Materials/YellowishMat.mat.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/New Physic Material.physicMaterial delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/New Physic Material.physicMaterial.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedBullet.prefab delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedBullet.prefab.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedSphereSorta.prefab delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedSphereSorta.prefab.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/RigidbodyPrediction.prefab delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/RigidbodyPrediction.prefab.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/RigidbodyPrediction.unity delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/RigidbodyPrediction.unity.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/BulletTest.cs delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/BulletTest.cs.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/PredictedBullet.cs delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/PredictedBullet.cs.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/RigidbodyPrediction.cs delete mode 100644 Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/RigidbodyPrediction.cs.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Transform.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Transform/Prefabs.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Transform/Prefabs/TransformPrediction.prefab delete mode 100644 Assets/FishNet/Example/All/Prediction/Transform/Prefabs/TransformPrediction.prefab.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Transform/Scripts.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Transform/Scripts/TransformPrediction.cs delete mode 100644 Assets/FishNet/Example/All/Prediction/Transform/Scripts/TransformPrediction.cs.meta delete mode 100644 Assets/FishNet/Example/All/Prediction/Transform/TransformPrediction.unity delete mode 100644 Assets/FishNet/Example/All/Prediction/Transform/TransformPrediction.unity.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Materials.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Materials/Black.mat delete mode 100644 Assets/FishNet/Example/All/SceneManager/Materials/Black.mat.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Materials/Blue.mat delete mode 100644 Assets/FishNet/Example/All/SceneManager/Materials/Blue.mat.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Materials/Green.mat delete mode 100644 Assets/FishNet/Example/All/SceneManager/Materials/Green.mat.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Materials/Red.mat delete mode 100644 Assets/FishNet/Example/All/SceneManager/Materials/Red.mat.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Prefabs.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Prefabs/Player.prefab delete mode 100644 Assets/FishNet/Example/All/SceneManager/Prefabs/Player.prefab.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/SceneManager Event Diagram.png delete mode 100644 Assets/FishNet/Example/All/SceneManager/SceneManager Event Diagram.png.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes/Additive.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveConnection.unity delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveConnection.unity.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveGlobal.unity delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveGlobal.unity.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveMain.unity delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveMain.unity.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes/Replace.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceConnection.unity delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceConnection.unity.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceGlobal.unity delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceGlobal.unity.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceMain.unity delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceMain.unity.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scripts.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scripts/PlayerController.cs delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scripts/PlayerController.cs.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scripts/SceneLoaderExample.cs delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scripts/SceneLoaderExample.cs.meta delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scripts/SceneUnloaderExample.cs delete mode 100644 Assets/FishNet/Example/All/SceneManager/Scripts/SceneUnloaderExample.cs.meta delete mode 100644 Assets/FishNet/Example/FishNet.Example.asmdef delete mode 100644 Assets/FishNet/Example/FishNet.Example.asmdef.meta delete mode 100644 Assets/FishNet/Example/Prefabs.meta delete mode 100644 Assets/FishNet/Example/Prefabs/NetworkHudCanvas.prefab delete mode 100644 Assets/FishNet/Example/Prefabs/NetworkHudCanvas.prefab.meta delete mode 100644 Assets/FishNet/Example/Prefabs/NetworkManager.prefab delete mode 100644 Assets/FishNet/Example/Prefabs/NetworkManager.prefab.meta delete mode 100644 Assets/FishNet/Example/Scripts.meta delete mode 100644 Assets/FishNet/Example/Scripts/NetworkHudCanvases.cs delete mode 100644 Assets/FishNet/Example/Scripts/NetworkHudCanvases.cs.meta delete mode 100644 Assets/FishNet/LICENSE.txt delete mode 100644 Assets/FishNet/LICENSE.txt.meta delete mode 100644 Assets/FishNet/Plugins/CodeAnalysis.meta delete mode 100644 Assets/FishNet/Plugins/CodeAnalysis/FishNet.CodeAnalysis.Analyzers.dll delete mode 100644 Assets/FishNet/Plugins/CodeAnalysis/FishNet.CodeAnalysis.Analyzers.dll.meta delete mode 100644 Assets/FishNet/Plugins/CodeAnalysis/FishNet.CodeAnalysis.dll delete mode 100644 Assets/FishNet/Plugins/CodeAnalysis/FishNet.CodeAnalysis.dll.meta delete mode 100644 Assets/FishNet/Plugins/CodeAnalysis/LICENSE.txt.meta delete mode 100644 Assets/FishNet/Plugins/CodeAnalysis/README.txt delete mode 100644 Assets/FishNet/Plugins/CodeAnalysis/README.txt.meta delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch.meta delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/CHANGELOG.txt delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/CHANGELOG.txt.meta delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core.meta delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/BidirectionalDictionary.cs delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/BidirectionalDictionary.cs.meta delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/ClientHostSocket.cs delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/ClientHostSocket.cs.meta delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/ClientSocket.cs delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/ClientSocket.cs.meta delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/CommonSocket.cs delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/CommonSocket.cs.meta delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/FishyConnectionManager.cs delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/FishyConnectionManager.cs.meta delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/FishySocketManager.cs delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/FishySocketManager.cs.meta delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/LocalPacket.cs delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/LocalPacket.cs.meta delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/ServerSocket.cs delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/Core/ServerSocket.cs.meta delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/FishyFacepunch.cs delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/FishyFacepunch.cs.meta delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/VERSION.txt delete mode 100644 Assets/FishNet/Plugins/FishyFacepunch/VERSION.txt.meta delete mode 100644 Assets/FishNet/Runtime/Authenticating.meta delete mode 100644 Assets/FishNet/Runtime/Authenticating/Authenticator.cs delete mode 100644 Assets/FishNet/Runtime/Authenticating/Authenticator.cs.meta delete mode 100644 Assets/FishNet/Runtime/Broadcast.meta delete mode 100644 Assets/FishNet/Runtime/Broadcast/Helping.meta delete mode 100644 Assets/FishNet/Runtime/Broadcast/Helping/BroadcastHelper.cs delete mode 100644 Assets/FishNet/Runtime/Broadcast/Helping/BroadcastHelper.cs.meta delete mode 100644 Assets/FishNet/Runtime/Broadcast/IBroadcast.cs delete mode 100644 Assets/FishNet/Runtime/Broadcast/IBroadcast.cs.meta delete mode 100644 Assets/FishNet/Runtime/Config.json delete mode 100644 Assets/FishNet/Runtime/Config.json.meta delete mode 100644 Assets/FishNet/Runtime/Connection.meta delete mode 100644 Assets/FishNet/Runtime/Connection/Buffer.cs delete mode 100644 Assets/FishNet/Runtime/Connection/Buffer.cs.meta delete mode 100644 Assets/FishNet/Runtime/Connection/NetworkConnection.Buffer.cs delete mode 100644 Assets/FishNet/Runtime/Connection/NetworkConnection.Buffer.cs.meta delete mode 100644 Assets/FishNet/Runtime/Connection/NetworkConnection.LOD.cs delete mode 100644 Assets/FishNet/Runtime/Connection/NetworkConnection.LOD.cs.meta delete mode 100644 Assets/FishNet/Runtime/Connection/NetworkConnection.PingPong.cs delete mode 100644 Assets/FishNet/Runtime/Connection/NetworkConnection.PingPong.cs.meta delete mode 100644 Assets/FishNet/Runtime/Connection/NetworkConnection.QOL.cs delete mode 100644 Assets/FishNet/Runtime/Connection/NetworkConnection.QOL.cs.meta delete mode 100644 Assets/FishNet/Runtime/Connection/NetworkConnection.cs delete mode 100644 Assets/FishNet/Runtime/Connection/NetworkConnection.cs.meta delete mode 100644 Assets/FishNet/Runtime/Documenting.meta delete mode 100644 Assets/FishNet/Runtime/Documenting/Attributes.cs delete mode 100644 Assets/FishNet/Runtime/Documenting/Attributes.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/CodeStripping.cs delete mode 100644 Assets/FishNet/Runtime/Editor/CodeStripping.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Configuring.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Configuring/ConfigurationData.cs delete mode 100644 Assets/FishNet/Runtime/Editor/Configuring/ConfigurationData.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Configuring/ConfigurationEditor.cs delete mode 100644 Assets/FishNet/Runtime/Editor/Configuring/ConfigurationEditor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Configuring/Configuring.cs delete mode 100644 Assets/FishNet/Runtime/Editor/Configuring/Configuring.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Configuring/FIshNetGettingStartedEditor.cs delete mode 100644 Assets/FishNet/Runtime/Editor/Configuring/FIshNetGettingStartedEditor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Configuring/ReviewReminderEditor.cs delete mode 100644 Assets/FishNet/Runtime/Editor/Configuring/ReviewReminderEditor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Configuring/SettingsProvider.cs delete mode 100644 Assets/FishNet/Runtime/Editor/Configuring/SettingsProvider.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Constants.cs delete mode 100644 Assets/FishNet/Runtime/Editor/Constants.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/DefaultPrefabsFinder.cs delete mode 100644 Assets/FishNet/Runtime/Editor/DefaultPrefabsFinder.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Finding.cs delete mode 100644 Assets/FishNet/Runtime/Editor/Finding.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/PlayModeTracker.cs delete mode 100644 Assets/FishNet/Runtime/Editor/PlayModeTracker.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator.meta delete mode 100644 Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Generator.cs delete mode 100644 Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Generator.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Settings.cs delete mode 100644 Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Settings.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/SettingsProvider.cs delete mode 100644 Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/SettingsProvider.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/PrefabProcessor.cs delete mode 100644 Assets/FishNet/Runtime/Editor/PrefabProcessor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/ScriptingDefines.cs delete mode 100644 Assets/FishNet/Runtime/Editor/ScriptingDefines.cs.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Textures.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Textures/Icon.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Textures/Icon/fishnet_light.png delete mode 100644 Assets/FishNet/Runtime/Editor/Textures/Icon/fishnet_light.png.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Textures/UI.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Client_Background.png delete mode 100644 Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Client_Background.png.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Indicator.png delete mode 100644 Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Indicator.png.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Server_Background.png delete mode 100644 Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Server_Background.png.meta delete mode 100644 Assets/FishNet/Runtime/Editor/Textures/UI/Logo_With_Text.png delete mode 100644 Assets/FishNet/Runtime/Editor/Textures/UI/Logo_With_Text.png.meta delete mode 100644 Assets/FishNet/Runtime/FishNet.Runtime.asmdef delete mode 100644 Assets/FishNet/Runtime/FishNet.Runtime.asmdef.meta delete mode 100644 Assets/FishNet/Runtime/Generated.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/NetworkAnimator.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/Editor.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/Editor/NetworkAnimatorEditor.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/Editor/NetworkAnimatorEditor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/NetworkAnimator.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/NetworkAnimator.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/NetworkTransform.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/NetworkTransform/Editor.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/NetworkTransform/Editor/NetworkTransformEditor.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/NetworkTransform/Editor/NetworkTransformEditor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/NetworkTransform/NetworkTransform.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/NetworkTransform/NetworkTransform.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/NetworkTransform/SynchronizedProperty.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/NetworkTransform/SynchronizedProperty.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/Editor.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/Editor/PredictedObjectEditor.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/Editor/PredictedObjectEditor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/OfflineRigidbody.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/OfflineRigidbody.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.Rigidbodies.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.Rigidbodies.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectOwnerSmoother.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectOwnerSmoother.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectSpectatorSmoother.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectSpectatorSmoother.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyPauser.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyPauser.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyState.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyState.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyType.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyType.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Spawning.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Spawning/PlayerSpawner.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Spawning/PlayerSpawner.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/TakeOwnership.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedOwner.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedOwner.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedSpawn.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedSpawn.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Utility.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Utility/BandwidthDisplay.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Utility/BandwidthDisplay.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Utility/DefaultScene.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Utility/DefaultScene.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Utility/PingDisplay.cs delete mode 100644 Assets/FishNet/Runtime/Generated/Component/Utility/PingDisplay.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/SyncTypes.meta delete mode 100644 Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatch.cs delete mode 100644 Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatch.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatchOperation.cs delete mode 100644 Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatchOperation.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimer.cs delete mode 100644 Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimer.cs.meta delete mode 100644 Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimerOperation.cs delete mode 100644 Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimerOperation.cs.meta delete mode 100644 Assets/FishNet/Runtime/InstanceFinder.cs delete mode 100644 Assets/FishNet/Runtime/InstanceFinder.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Client.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Client/ClientManager.Broadcast.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Client/ClientManager.Broadcast.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Client/ClientManager.LOD.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Client/ClientManager.LOD.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Client/ClientManager.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Client/ClientManager.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Client/Editor.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Client/Editor/ClientManagerEditor.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Client/Editor/ClientManagerEditor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Client/Object.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.RpcLinks.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.RpcLinks.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Client/Object/ObjectCaching.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Client/Object/ObjectCaching.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Debugging.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Debugging/DebugManager.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Debugging/DebugManager.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Debugging/ParseLogger.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Debugging/ParseLogger.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Editor.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Editor/NetworkManagerEditor.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Editor/NetworkManagerEditor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Logging.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Logging/LevelLoggingConfiguration.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Logging/LevelLoggingConfiguration.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Logging/LoggingConfiguration.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Logging/LoggingConfiguration.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Logging/LoggingType.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Logging/LoggingType.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/NetworkManager.Logging.cs delete mode 100644 Assets/FishNet/Runtime/Managing/NetworkManager.Logging.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/NetworkManager.Pro.cs delete mode 100644 Assets/FishNet/Runtime/Managing/NetworkManager.Pro.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/NetworkManager.QOL.cs delete mode 100644 Assets/FishNet/Runtime/Managing/NetworkManager.QOL.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/NetworkManager.cs delete mode 100644 Assets/FishNet/Runtime/Managing/NetworkManager.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Object.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Object/DespawnWriter.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Object/DespawnWriter.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Object/DualPrefab.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Object/DualPrefab.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Object/ManagedObjects.Spawning.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Object/ManagedObjects.Spawning.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Object/ManagedObjects.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Object/ManagedObjects.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Object/ObjectSpawnType.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Object/ObjectSpawnType.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Object/PrefabObjects.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DefaultPrefabObjects.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DefaultPrefabObjects.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DualPrefabObjects.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DualPrefabObjects.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Object/PrefabObjects/PrefabObjects.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Object/PrefabObjects/PrefabObjects.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Object/PrefabObjects/SinglePrefabObjects.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Object/PrefabObjects/SinglePrefabObjects.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Object/SpawnParentType.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Object/SpawnParentType.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Object/SpawnWriter.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Object/SpawnWriter.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Observing.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Observing/Editor.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Observing/Editor/ObserverManagerEditor.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Observing/Editor/ObserverManagerEditor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Observing/ObserverManager.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Observing/ObserverManager.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Prediction.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Prediction/Editor.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Prediction/Editor/PredictionManagerEditor.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Prediction/Editor/PredictionManagerEditor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Prediction/PredictionManager.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Prediction/PredictionManager.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/Broadcast.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/Broadcast/SceneBroadcasts.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/Broadcast/SceneBroadcasts.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/DefaultSceneProcessor.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/DefaultSceneProcessor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/Events.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/Events/ClientPresenceChangeEventArgs.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/Events/ClientPresenceChangeEventArgs.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/Events/LoadSceneEventArgs.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/Events/LoadSceneEventArgs.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/Events/UnloadSceneEventArgs.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/Events/UnloadSceneEventArgs.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadOptions.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadOptions.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadParams.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadParams.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadQueueData.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadQueueData.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/ReplaceOption.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/ReplaceOption.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneLoadData.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneLoadData.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneScopeTypes.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneScopeTypes.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneUnloadData.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneUnloadData.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadOptions.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadOptions.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadParams.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadParams.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadQueueData.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadQueueData.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/SceneProcessorBase.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/SceneProcessorBase.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/SceneSpawner.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/SceneSpawner.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Server.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Server/ClientConnectionBroadcast.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Server/ClientConnectionBroadcast.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Server/Editor.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Server/Editor/ServerManagerEditor.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Server/Editor/ServerManagerEditor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Server/KickReasons.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Server/KickReasons.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Server/Object.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Observers.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Observers.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Parsing.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Parsing.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Server/ServerManager.Broadcast.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Server/ServerManager.Broadcast.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Server/ServerManager.LOD.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Server/ServerManager.LOD.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Server/ServerManager.QOL.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Server/ServerManager.QOL.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Server/ServerManager.RpcLinks.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Server/ServerManager.RpcLinks.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Server/ServerManager.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Server/ServerManager.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Statistic.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficArgs.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficArgs.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficStatistics.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficStatistics.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Statistic/StatisticsManager.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Statistic/StatisticsManager.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Timing.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/Editor.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/Editor/TimeManagerEditor.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/Editor/TimeManagerEditor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/MovingAverage.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/MovingAverage.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/PhysicsMode.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/PhysicsMode.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/PreciseTick.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/PreciseTick.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/TickRounding.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/TickRounding.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/TickType.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/TickType.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Transporting.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Transporting/IntermediateLayer.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Transporting/IntermediateLayer.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Transporting/LatencySimulator.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Transporting/LatencySimulator.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Transporting/SplitReader.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Transporting/SplitReader.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Transporting/TransportManager.QOL.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Transporting/TransportManager.QOL.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Transporting/TransportManager.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Transporting/TransportManager.cs.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Utility.meta delete mode 100644 Assets/FishNet/Runtime/Managing/Utility/Utility.cs delete mode 100644 Assets/FishNet/Runtime/Managing/Utility/Utility.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object.meta delete mode 100644 Assets/FishNet/Runtime/Object/Attributes.cs delete mode 100644 Assets/FishNet/Runtime/Object/Attributes.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/ChangedTransformProperties.cs delete mode 100644 Assets/FishNet/Runtime/Object/ChangedTransformProperties.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Delegates.cs delete mode 100644 Assets/FishNet/Runtime/Object/Delegates.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/DespawnType.cs delete mode 100644 Assets/FishNet/Runtime/Object/DespawnType.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/EmptyNetworkBehaviour.cs delete mode 100644 Assets/FishNet/Runtime/Object/EmptyNetworkBehaviour.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Helping.meta delete mode 100644 Assets/FishNet/Runtime/Object/Helping/Hashing.cs delete mode 100644 Assets/FishNet/Runtime/Object/Helping/Hashing.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Helping/RpcLink.cs delete mode 100644 Assets/FishNet/Runtime/Object/Helping/RpcLink.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Helping/RpcType.cs delete mode 100644 Assets/FishNet/Runtime/Object/Helping/RpcType.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Helping/StaticShortcuts.cs delete mode 100644 Assets/FishNet/Runtime/Object/Helping/StaticShortcuts.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.Callbacks.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.Callbacks.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.Logging.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.Logging.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.Prediction.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.Prediction.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.QOL.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.QOL.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCLinks.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCLinks.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCs.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCs.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.SyncTypes.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.SyncTypes.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkBehaviour.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.Broadcast.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.Broadcast.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.Callbacks.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.Callbacks.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.Observers.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.Observers.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.QOL.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.QOL.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.ReferenceIds.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.ReferenceIds.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.RpcLinks.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.RpcLinks.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.SyncTypes.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.SyncTypes.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObject.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObjectState.cs delete mode 100644 Assets/FishNet/Runtime/Object/NetworkObjectState.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/PredictedSpawningType.cs delete mode 100644 Assets/FishNet/Runtime/Object/PredictedSpawningType.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Prediction.meta delete mode 100644 Assets/FishNet/Runtime/Object/Prediction/Attributes.cs delete mode 100644 Assets/FishNet/Runtime/Object/Prediction/Attributes.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Prediction/Delegates.cs delete mode 100644 Assets/FishNet/Runtime/Object/Prediction/Delegates.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Prediction/Interfaces.cs delete mode 100644 Assets/FishNet/Runtime/Object/Prediction/Interfaces.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/RpcLinkType.cs delete mode 100644 Assets/FishNet/Runtime/Object/RpcLinkType.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/SyncTypeWriteType.cs delete mode 100644 Assets/FishNet/Runtime/Object/SyncTypeWriteType.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/ICustomSync.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/ICustomSync.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/ISyncObject.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/ISyncObject.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/MissingObjectPacketLength.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/MissingObjectPacketLength.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/ReadPermissions.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/ReadPermissions.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SecretMenu.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SecretMenu/SyncVarExtensions.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SecretMenu/SyncVarExtensions.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/Settings.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/Settings.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncBase.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncBase.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionary.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionary.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionaryOperation.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionaryOperation.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncHashSetOperation.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncHashSetOperation.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncHashset.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncHashset.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncList.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncList.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncListOperation.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncListOperation.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncVar.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/SyncVar.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/WritePermissions.cs delete mode 100644 Assets/FishNet/Runtime/Object/Synchronizing/WritePermissions.cs.meta delete mode 100644 Assets/FishNet/Runtime/Object/TransformProperties.cs delete mode 100644 Assets/FishNet/Runtime/Object/TransformProperties.cs.meta delete mode 100644 Assets/FishNet/Runtime/Observing.meta delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions.meta delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/DistanceCondition.cs delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/DistanceCondition.cs.meta delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/HostOnlyCondition.cs delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/HostOnlyCondition.cs.meta delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/MatchCondition.cs delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/MatchCondition.cs.meta delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/OwnerOnlyCondition.cs delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/OwnerOnlyCondition.cs.meta delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/SceneCondition.cs delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/SceneCondition.cs.meta delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects.meta delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/DistanceCondition.asset delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/DistanceCondition.asset.meta delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/HostOnlyCondition.asset delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/HostOnlyCondition.asset.meta delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/MatchCondition.asset delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/MatchCondition.asset.meta delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/OwnerOnlyCondition.asset delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/OwnerOnlyCondition.asset.meta delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/SceneCondition.asset delete mode 100644 Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/SceneCondition.asset.meta delete mode 100644 Assets/FishNet/Runtime/Observing/HostVisibilityUpdateTypes.cs delete mode 100644 Assets/FishNet/Runtime/Observing/HostVisibilityUpdateTypes.cs.meta delete mode 100644 Assets/FishNet/Runtime/Observing/NetworkObserver.cs delete mode 100644 Assets/FishNet/Runtime/Observing/NetworkObserver.cs.meta delete mode 100644 Assets/FishNet/Runtime/Observing/ObserverCondition.cs delete mode 100644 Assets/FishNet/Runtime/Observing/ObserverCondition.cs.meta delete mode 100644 Assets/FishNet/Runtime/Observing/ObserverStateChange.cs delete mode 100644 Assets/FishNet/Runtime/Observing/ObserverStateChange.cs.meta delete mode 100644 Assets/FishNet/Runtime/Plugins.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/ColliderRollback.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/ColliderRollback/Attributions.txt delete mode 100644 Assets/FishNet/Runtime/Plugins/ColliderRollback/Attributions.txt.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/ColliderRollback/LICENSE.txt delete mode 100644 Assets/FishNet/Runtime/Plugins/ColliderRollback/LICENSE.txt.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/ColliderRollback.cs delete mode 100644 Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/ColliderRollback.cs.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/RollbackManager.cs delete mode 100644 Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/RollbackManager.cs.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/CHANGELOG.txt delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/CHANGELOG.txt.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/Core.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/Core/ClientSocket.cs delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/Core/ClientSocket.cs.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/Core/CommonSocket.cs delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/Core/CommonSocket.cs.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/Core/LocalPacket.cs delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/Core/LocalPacket.cs.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/Core/ServerSocket.cs delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/Core/ServerSocket.cs.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/VERSION.txt delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/VERSION.txt.meta delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/Yak.cs delete mode 100644 Assets/FishNet/Runtime/Plugins/Yak/Yak.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/AutoPackType.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/AutoPackType.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping/Attributes.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping/Attributes.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping/Broadcasts.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping/Broadcasts.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping/Quaternion32.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping/Quaternion32.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping/Quaternion64.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping/Quaternion64.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping/QuaternionConverter.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping/QuaternionConverter.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping/ValueConversions.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/Helping/ValueConversions.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/Reader.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/Reader.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/ReaderExtensions.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/ReaderExtensions.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/ReaderPool.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/ReaderPool.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/ReaderStatics.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/ReaderStatics.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/SceneComparer.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/SceneComparer.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/TransformPackingData.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/TransformPackingData.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/Writer.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/Writer.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/WriterExtensions.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/WriterExtensions.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/WriterPool.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/WriterPool.cs.meta delete mode 100644 Assets/FishNet/Runtime/Serializing/WriterStatics.cs delete mode 100644 Assets/FishNet/Runtime/Serializing/WriterStatics.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Channels.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Channels.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/ConnectionStates.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/ConnectionStates.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/EventStructures.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/EventStructures.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/IPAddressType.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/IPAddressType.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/NetworkReaderLoop.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/NetworkReaderLoop.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/NetworkWriterLoop.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/NetworkWriterLoop.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/PacketId.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/PacketId.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transport.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transport.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Multipass.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Multipass/CHANGELOG.txt delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Multipass/CHANGELOG.txt.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Multipass/Multipass.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Multipass/Multipass.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Multipass/VERSION.txt delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Multipass/VERSION.txt.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ClientSocket.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ClientSocket.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/CommonSocket.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/CommonSocket.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ServerSocket.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ServerSocket.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/Supporting.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/Supporting.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/BaseChannel.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/BaseChannel.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ConnectionRequest.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ConnectionRequest.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/INetEventListener.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/INetEventListener.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/InternalPackets.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/InternalPackets.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/Crc32cLayer.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/Crc32cLayer.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/PacketLayerBase.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/PacketLayerBase.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/XorEncryptLayer.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/XorEncryptLayer.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NatPunchModule.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NatPunchModule.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NativeSocket.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NativeSocket.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetConstants.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetConstants.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetDebug.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetDebug.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.PacketPool.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.PacketPool.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.Socket.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.Socket.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPacket.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPacket.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPeer.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPeer.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetStatistics.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetStatistics.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetUtils.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetUtils.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PausedSocketFix.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PausedSocketFix.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PooledPacket.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PooledPacket.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ReliableChannel.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ReliableChannel.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/SequencedChannel.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/SequencedChannel.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/CRC32C.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/CRC32C.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/FastBitConverter.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/FastBitConverter.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/INetSerializable.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/INetSerializable.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataReader.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataReader.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataWriter.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataWriter.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetPacketProcessor.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetPacketProcessor.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetSerializer.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetSerializer.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpPacket.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpPacket.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpRequest.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpRequest.cs.meta delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Tugboat.cs delete mode 100644 Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Tugboat.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility.meta delete mode 100644 Assets/FishNet/Runtime/Utility/ApplicationState.cs delete mode 100644 Assets/FishNet/Runtime/Utility/ApplicationState.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Constants.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Constants.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/DDOLFinder.cs delete mode 100644 Assets/FishNet/Runtime/Utility/DDOLFinder.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Editor.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Editor/SceneDrawer.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Editor/SceneDrawer.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Extension.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Bool.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Bool.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Collection.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Collection.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Dictionary.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Dictionary.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Enum.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Enum.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/List.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/List.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Math.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Math.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Object.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Object.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Quaternion.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Quaternion.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Scene.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Scene.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Transforms.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Extension/Transforms.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Performance.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Performance/ByteArrayPool.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Performance/ByteArrayPool.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Performance/DefaultObjectPool.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Performance/DefaultObjectPool.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Performance/ListCache.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Performance/ListCache.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Performance/ObjectPool.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Performance/ObjectPool.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Performance/RingBuffer.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Performance/RingBuffer.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/Performance/Transforms.cs delete mode 100644 Assets/FishNet/Runtime/Utility/Performance/Transforms.cs.meta delete mode 100644 Assets/FishNet/Runtime/Utility/SceneAttribute.cs delete mode 100644 Assets/FishNet/Runtime/Utility/SceneAttribute.cs.meta delete mode 100644 Assets/FishNet/THIRD PARTY NOTICE.md delete mode 100644 Assets/FishNet/THIRD PARTY NOTICE.md.meta delete mode 100644 Assets/FishNet/Upgrading.meta delete mode 100644 Assets/FishNet/Upgrading/MirrorUpgrade.cs delete mode 100644 Assets/FishNet/Upgrading/MirrorUpgrade.cs.meta delete mode 100644 Assets/FishNet/Upgrading/UpgradeFromMirrorMenu.cs delete mode 100644 Assets/FishNet/Upgrading/UpgradeFromMirrorMenu.cs.meta delete mode 100644 Assets/FishNet/VERSION.txt delete mode 100644 Assets/FishNet/VERSION.txt.meta delete mode 100644 Assets/Packages/Facepunch.meta delete mode 100644 Assets/Packages/Facepunch/Facepunch.Steamworks.Posix.dll delete mode 100644 Assets/Packages/Facepunch/Facepunch.Steamworks.Posix.xml delete mode 100644 Assets/Packages/Facepunch/Facepunch.Steamworks.Posix.xml.meta delete mode 100644 Assets/Packages/Facepunch/Facepunch.Steamworks.Win32.dll delete mode 100644 Assets/Packages/Facepunch/Facepunch.Steamworks.Win32.xml delete mode 100644 Assets/Packages/Facepunch/Facepunch.Steamworks.Win32.xml.meta delete mode 100644 Assets/Packages/Facepunch/Facepunch.Steamworks.Win64.dll delete mode 100644 Assets/Packages/Facepunch/Facepunch.Steamworks.Win64.dll.meta delete mode 100644 Assets/Packages/Facepunch/Facepunch.Steamworks.Win64.xml delete mode 100644 Assets/Packages/Facepunch/Facepunch.Steamworks.Win64.xml.meta delete mode 100644 Assets/Packages/Facepunch/redistributable_bin.meta delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/linux32.meta delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/linux32/libsteam_api.so delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/linux32/libsteam_api.so.meta delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/linux64.meta delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/linux64/libsteam_api.so delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/osx.meta delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/osx/libsteam_api.bundle delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/osx/libsteam_api.bundle.meta delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/steam_api.dll delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/steam_api.lib delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/steam_api.lib.meta delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/win64.meta delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/win64/steam_api64.dll delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/win64/steam_api64.dll.meta delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/win64/steam_api64.lib delete mode 100644 Assets/Packages/Facepunch/redistributable_bin/win64/steam_api64.lib.meta delete mode 100644 Assets/Scripts/Steam.meta delete mode 100644 Assets/Scripts/Steam/FriendObject.cs delete mode 100644 Assets/Scripts/Steam/FriendObject.cs.meta delete mode 100644 Assets/Scripts/Steam/SteamFriendsManager.cs delete mode 100644 Assets/Scripts/Steam/SteamFriendsManager.cs.meta delete mode 100644 Assets/Scripts/Steam/SteamLobbyManager.cs delete mode 100644 Assets/Scripts/Steam/SteamLobbyManager.cs.meta delete mode 100644 Assets/Scripts/Steam/SteamLobbyWithPlayer.cs delete mode 100644 Assets/Scripts/Steam/SteamLobbyWithPlayer.cs.meta delete mode 100644 Assets/Scripts/Steam/SteamManager.cs create mode 100644 Assets/Scripts/Steamworks.NET.meta create mode 100644 Assets/Scripts/Steamworks.NET/SteamManager.cs rename Assets/Scripts/{Steam => Steamworks.NET}/SteamManager.cs.meta (57%) rename Assets/{FishNet.meta => com.rlabrecque.steamworks.net.meta} (77%) rename Assets/{FishNet/Runtime => com.rlabrecque.steamworks.net}/Editor.meta (77%) create mode 100644 Assets/com.rlabrecque.steamworks.net/Editor/RedistCopy.cs rename Assets/{FishNet/CodeGenerating/Extension/MethodDefinitionExtensions.cs.meta => com.rlabrecque.steamworks.net/Editor/RedistCopy.cs.meta} (83%) create mode 100644 Assets/com.rlabrecque.steamworks.net/Editor/RedistInstall.cs rename Assets/{FishNet/CodeGenerating/Extension/TypeDefinitionExtensions.cs.meta => com.rlabrecque.steamworks.net/Editor/RedistInstall.cs.meta} (83%) create mode 100644 Assets/com.rlabrecque.steamworks.net/Editor/com.rlabrecque.steamworks.net.editor.asmdef rename Assets/{FishNet/CodeGenerating/Unity.FishNet.CodeGen.asmdef.meta => com.rlabrecque.steamworks.net/Editor/com.rlabrecque.steamworks.net.editor.asmdef.meta} (76%) rename Assets/{FishNet/Plugins/CodeAnalysis/LICENSE.txt => com.rlabrecque.steamworks.net/LICENSE.md} (86%) rename Assets/{FishNet/DOCUMENTATION.txt.meta => com.rlabrecque.steamworks.net/LICENSE.md.meta} (75%) rename Assets/{FishNet => com.rlabrecque.steamworks.net}/Plugins.meta (77%) create mode 100644 Assets/com.rlabrecque.steamworks.net/Plugins/libsteam_api.so rename Assets/{Packages/Facepunch/Facepunch.Steamworks.Win32.dll.meta => com.rlabrecque.steamworks.net/Plugins/libsteam_api.so.meta} (66%) rename Assets/{Packages/Facepunch/Facepunch.Steamworks.Posix.dll.meta => com.rlabrecque.steamworks.net/Plugins/steam_api.bundle.meta} (70%) rename Assets/{FishNet/CodeGenerating.meta => com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents.meta} (77%) create mode 100644 Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/Info.plist rename Assets/{FishNet/CodeGenerating/cecil-0.11.4/Directory.Build.props.meta => com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/Info.plist.meta} (74%) rename Assets/{FishNet/CodeGenerating/Extension.meta => com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/MacOS.meta} (77%) create mode 100644 Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/MacOS/libsteam_api.dylib rename Assets/{FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Tests.props.meta => com.rlabrecque.steamworks.net/Plugins/steam_api.bundle/Contents/MacOS/libsteam_api.dylib.meta} (74%) create mode 100644 Assets/com.rlabrecque.steamworks.net/Plugins/steam_api.dll rename Assets/{Packages/Facepunch/redistributable_bin => com.rlabrecque.steamworks.net/Plugins}/steam_api.dll.meta (65%) create mode 100644 Assets/com.rlabrecque.steamworks.net/Plugins/steam_api64.dll rename Assets/{Packages/Facepunch/redistributable_bin/linux64/libsteam_api.so.meta => com.rlabrecque.steamworks.net/Plugins/steam_api64.dll.meta} (64%) create mode 100644 Assets/com.rlabrecque.steamworks.net/README.md rename Assets/{FishNet/CodeGenerating/cecil-0.11.4 => com.rlabrecque.steamworks.net}/README.md.meta (75%) rename Assets/{FishNet => com.rlabrecque.steamworks.net}/Runtime.meta (77%) create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/CallbackDispatcher.cs rename Assets/{FishNet/CodeGenerating/Extension/TypeReferenceExtensions.cs.meta => com.rlabrecque.steamworks.net/Runtime/CallbackDispatcher.cs.meta} (83%) create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/CallbackIdentity.cs rename Assets/{FishNet/CodeGenerating/Extension/ILProcessorExtensions.cs.meta => com.rlabrecque.steamworks.net/Runtime/CallbackIdentity.cs.meta} (83%) create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/ISteamMatchmakingResponses.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/ISteamMatchmakingResponses.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/InteropHelp.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/InteropHelp.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/Packsize.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/Packsize.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/Steam.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/Steam.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/Version.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/Version.cs.meta rename Assets/{FishNet/CodeGenerating/Helpers.meta => com.rlabrecque.steamworks.net/Runtime/autogen.meta} (77%) create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/NativeMethods.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/NativeMethods.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamCallbacks.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamCallbacks.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamConstants.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamConstants.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamEnums.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamEnums.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamStructs.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/SteamStructs.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapplist.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapplist.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapps.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamapps.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamclient.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamclient.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamfriends.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamfriends.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserver.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserver.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverclient.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverclient.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverhttp.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverhttp.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverinventory.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverinventory.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworking.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworking.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingsockets.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingsockets.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingutils.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameservernetworkingutils.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverstats.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverstats.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverugc.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverugc.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverutils.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamgameserverutils.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhtmlsurface.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhtmlsurface.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhttp.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamhttp.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminput.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminput.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminventory.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteaminventory.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammatchmaking.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammatchmaking.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusic.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusic.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusicremote.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteammusicremote.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworking.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworking.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingmessages.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingmessages.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingsockets.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingsockets.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingutils.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamnetworkingutils.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamparentalsettings.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamparentalsettings.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremoteplay.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremoteplay.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremotestorage.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamremotestorage.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamscreenshots.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamscreenshots.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamugc.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamugc.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuser.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuser.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuserstats.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamuserstats.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamutils.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamutils.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamvideo.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/autogen/isteamvideo.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/com.rlabrecque.steamworks.net.asmdef rename Assets/{FishNet/CodeGenerating/cecil-0.11.4/MonoFN.Cecil.asmdef.meta => com.rlabrecque.steamworks.net/Runtime/com.rlabrecque.steamworks.net.asmdef.meta} (76%) create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/gameserveritem_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/gameserveritem_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/servernetadr_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/MatchmakingTypes/servernetadr_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPIWarningMessageHook_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPIWarningMessageHook_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPI_CheckCallbackRegistered_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClient/SteamAPI_CheckCallbackRegistered_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CGameID.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CGameID.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CSteamID.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/CSteamID.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/HAuthTicket.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamClientPublic/HAuthTicket.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramHostedAddress.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramHostedAddress.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramRelayAuthTicket.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamDatagramTickets/SteamDatagramRelayAuthTicket.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamFriends.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamFriends/FriendsGroupID_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamFriends/FriendsGroupID_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTMLSurface.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTMLSurface/HHTMLBrowser.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTMLSurface/HHTMLBrowser.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPCookieContainerHandle.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPCookieContainerHandle.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPRequestHandle.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamHTTP/HTTPRequestHandle.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputActionSetHandle_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputActionSetHandle_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputAnalogActionHandle_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputAnalogActionHandle_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputDigitalActionHandle_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputDigitalActionHandle_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputHandle_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/InputHandle_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEventCallbackPointer.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEventCallbackPointer.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEvent_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInput/SteamInputActionEvent_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryResult_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryResult_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryUpdateHandle_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamInventoryUpdateHandle_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemDef_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemDef_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemInstanceID_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamInventory/SteamItemInstanceID_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerListRequest.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerListRequest.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerQuery.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamMatchmaking/HServerQuery.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetListenSocket_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetListenSocket_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetSocket_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworking/SNetSocket_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingConnectionSignaling.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingConnectionSignaling.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingSignalingRecvContext.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingSockets/ISteamNetworkingSignalingRecvContext.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/FSteamNetworkingSocketsDebugOutput.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/FSteamNetworkingSocketsDebugOutput.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamListenSocket.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamListenSocket.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetConnection.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetConnection.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetPollGroup.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/HSteamNetPollGroup.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingConfigValue_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingConfigValue_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingErrMsg.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingErrMsg.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIPAddr.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIPAddr.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIdentity.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingIdentity.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMessage_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMessage_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMicroseconds.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingMicroseconds.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingPOPID.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamNetworkingTypes/SteamNetworkingPOPID.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemotePlay.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemotePlay/RemotePlaySessionID_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemotePlay/RemotePlaySessionID_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileId_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileId_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileUpdateHandle_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/PublishedFileUpdateHandle_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCFileWriteStreamHandle_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCFileWriteStreamHandle_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCHandle_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamRemoteStorage/UGCHandle_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamScreenshots.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamScreenshots/ScreenshotHandle.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamScreenshots/ScreenshotHandle.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AccountID_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AccountID_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AppId_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/AppId_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/DepotId_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/DepotId_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/PartyBeaconID_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/PartyBeaconID_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/RTime32.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/RTime32.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamAPICall_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamAPICall_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamIPAddress_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamTypes/SteamIPAddress_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCQueryHandle_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCQueryHandle_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCUpdateHandle_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUGC/UGCUpdateHandle_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboardEntries_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboardEntries_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboard_t.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/SteamUserStats/SteamLeaderboard_t.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamPipe.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamPipe.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamUser.cs create mode 100644 Assets/com.rlabrecque.steamworks.net/Runtime/types/Steam_api_common/HSteamUser.cs.meta create mode 100644 Assets/com.rlabrecque.steamworks.net/package.json rename Assets/{FishNet/CodeGenerating/cecil-0.11.4/LICENSE.txt.meta => com.rlabrecque.steamworks.net/package.json.meta} (60%) create mode 100644 ProjectSettings/BurstAotSettings_StandaloneOSX.json create mode 100644 steam_appid.txt diff --git a/Assets/Animations/PlayerAnimations/Running/PlayerRunning.fbx.meta b/Assets/Animations/PlayerAnimations/Running/PlayerRunning.fbx.meta index 72a8525..786051a 100644 --- a/Assets/Animations/PlayerAnimations/Running/PlayerRunning.fbx.meta +++ b/Assets/Animations/PlayerAnimations/Running/PlayerRunning.fbx.meta @@ -31,7 +31,36 @@ ModelImporter: animationWrapMode: 0 extraExposedTransformPaths: [] extraUserProperties: [] - clipAnimations: [] + clipAnimations: + - serializedVersion: 16 + name: mixamo.com + takeName: mixamo.com + internalID: -203655887218126122 + firstFrame: 0 + lastFrame: 21 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 1 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 isReadable: 0 meshes: lODScreenPercentages: [] diff --git a/Assets/Animations/PlayerAnimations/Running/X Bot@Pistol Run Down.fbx.meta b/Assets/Animations/PlayerAnimations/Running/X Bot@Pistol Run Down.fbx.meta index b328077..c05723a 100644 --- a/Assets/Animations/PlayerAnimations/Running/X Bot@Pistol Run Down.fbx.meta +++ b/Assets/Animations/PlayerAnimations/Running/X Bot@Pistol Run Down.fbx.meta @@ -31,7 +31,36 @@ ModelImporter: animationWrapMode: 0 extraExposedTransformPaths: [] extraUserProperties: [] - clipAnimations: [] + clipAnimations: + - serializedVersion: 16 + name: Pistol Run Down + takeName: Armature|Armature|mixamo.com|Layer0 + internalID: -4791504522942941401 + firstFrame: 0 + lastFrame: 1 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 1 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 isReadable: 0 meshes: lODScreenPercentages: [] diff --git a/Assets/Animations/PlayerAnimations/Running/X Bot@Pistol Run Up.fbx.meta b/Assets/Animations/PlayerAnimations/Running/X Bot@Pistol Run Up.fbx.meta index 0ba1ea4..693cc50 100644 --- a/Assets/Animations/PlayerAnimations/Running/X Bot@Pistol Run Up.fbx.meta +++ b/Assets/Animations/PlayerAnimations/Running/X Bot@Pistol Run Up.fbx.meta @@ -31,7 +31,36 @@ ModelImporter: animationWrapMode: 0 extraExposedTransformPaths: [] extraUserProperties: [] - clipAnimations: [] + clipAnimations: + - serializedVersion: 16 + name: Pistol Run Up + takeName: Armature|Armature|mixamo.com|Layer0 + internalID: -4791504522942941401 + firstFrame: 0 + lastFrame: 1 + wrapMode: 0 + orientationOffsetY: 0 + level: 0 + cycleOffset: 0 + loop: 0 + hasAdditiveReferencePose: 0 + loopTime: 1 + loopBlend: 0 + loopBlendOrientation: 0 + loopBlendPositionY: 0 + loopBlendPositionXZ: 0 + keepOriginalOrientation: 0 + keepOriginalPositionY: 1 + keepOriginalPositionXZ: 0 + heightFromFeet: 0 + mirror: 0 + bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + curves: [] + events: [] + transformMask: [] + maskType: 3 + maskSource: {instanceID: 0} + additiveReferencePoseFrame: 0 isReadable: 0 meshes: lODScreenPercentages: [] diff --git a/Assets/FishNet/CodeGenerating/Extension/ILProcessorExtensions.cs b/Assets/FishNet/CodeGenerating/Extension/ILProcessorExtensions.cs deleted file mode 100644 index 7e1c18a..0000000 --- a/Assets/FishNet/CodeGenerating/Extension/ILProcessorExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using FishNet.CodeGenerating.Helping.Extension; -using MonoFN.Cecil.Cil; - -namespace FishNet.CodeGenerating.Extension -{ - - - internal static class ILProcessorExtensions - { - /// - /// Creates a variable type within the body and returns it's VariableDef. - /// - internal static VariableDefinition CreateVariable(this ILProcessor processor, CodegenSession session, System.Type variableType) - { - return processor.Body.Method.CreateVariable(session, variableType); - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Extension/MethodDefinitionExtensions.cs b/Assets/FishNet/CodeGenerating/Extension/MethodDefinitionExtensions.cs deleted file mode 100644 index 1d42d6d..0000000 --- a/Assets/FishNet/CodeGenerating/Extension/MethodDefinitionExtensions.cs +++ /dev/null @@ -1,131 +0,0 @@ -using FishNet.CodeGenerating.Helping.Extension; -using MonoFN.Cecil; -using MonoFN.Cecil.Rocks; -using MonoFN.Collections.Generic; -using System.Collections.Generic; - -namespace FishNet.CodeGenerating.Extension -{ - - - internal static class MethodDefinitionExtensions - { - /// - /// Returns the proper OpCode to use for call methods. - /// - public static MonoFN.Cecil.Cil.OpCode GetCallOpCode(this MethodDefinition md) - { - if (md.Attributes.HasFlag(MethodAttributes.Virtual)) - return MonoFN.Cecil.Cil.OpCodes.Callvirt; - else - return MonoFN.Cecil.Cil.OpCodes.Call; - } - /// - /// Returns the proper OpCode to use for call methods. - /// - public static MonoFN.Cecil.Cil.OpCode GetCallOpCode(this MethodReference mr, CodegenSession session) - { - return mr.CachedResolve(session).GetCallOpCode(); - } - - /// - /// Adds otherMd parameters to thisMR and returns added parameters. - /// - public static List CreateParameters(this MethodReference thisMr, CodegenSession session, MethodDefinition otherMd) - { - return thisMr.CachedResolve(session).CreateParameters(session, otherMd); - } - /// - /// Adds otherMr parameters to thisMR and returns added parameters. - /// - public static List CreateParameters(this MethodReference thisMr, CodegenSession session, MethodReference otherMr) - { - return thisMr.CachedResolve(session).CreateParameters(session, otherMr.CachedResolve(session)); - } - - /// - /// Adds otherMd parameters to thisMd and returns added parameters. - /// - public static List CreateParameters(this MethodDefinition thisMd, CodegenSession session, MethodDefinition otherMd) - { - List results = new List(); - - foreach (ParameterDefinition pd in otherMd.Parameters) - { - session.ImportReference(pd.ParameterType); - int currentCount = thisMd.Parameters.Count; - string name = (pd.Name + currentCount); - ParameterDefinition parameterDef = new ParameterDefinition(name, pd.Attributes, pd.ParameterType); - //Set any default values. - parameterDef.Constant = pd.Constant; - parameterDef.IsReturnValue = pd.IsReturnValue; - parameterDef.IsOut = pd.IsOut; - foreach (CustomAttribute item in pd.CustomAttributes) - parameterDef.CustomAttributes.Add(item); - parameterDef.HasConstant = pd.HasConstant; - parameterDef.HasDefault = pd.HasDefault; - - thisMd.Parameters.Add(parameterDef); - - results.Add(parameterDef); - } - - return results; - } - - /// - /// Returns a method reference while considering if declaring type is generic. - /// - public static MethodReference GetMethodReference(this MethodDefinition md, CodegenSession session) - { - MethodReference methodRef = session.ImportReference(md); - - //Is generic. - if (md.DeclaringType.HasGenericParameters) - { - GenericInstanceType git = methodRef.DeclaringType.MakeGenericInstanceType(); - MethodReference result = new MethodReference(md.Name, md.ReturnType) - { - HasThis = md.HasThis, - ExplicitThis = md.ExplicitThis, - DeclaringType = git, - CallingConvention = md.CallingConvention, - }; - foreach (ParameterDefinition pd in md.Parameters) - { - session.ImportReference(pd.ParameterType); - result.Parameters.Add(pd); - } - return result; - } - else - { - return methodRef; - } - } - - - /// - /// Returns a method reference for a generic method. - /// - public static MethodReference GetMethodReference(this MethodDefinition md, CodegenSession session, TypeReference typeReference) - { - MethodReference methodRef = session.ImportReference(md); - return methodRef.GetMethodReference(session, typeReference); - } - - - /// - /// Returns a method reference for a generic method. - /// - public static MethodReference GetMethodReference(this MethodDefinition md, CodegenSession session, TypeReference[] typeReferences) - { - MethodReference methodRef = session.ImportReference(md); - return methodRef.GetMethodReference(session, typeReferences); - } - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Extension/TypeDefinitionExtensions.cs b/Assets/FishNet/CodeGenerating/Extension/TypeDefinitionExtensions.cs deleted file mode 100644 index 6c11c26..0000000 --- a/Assets/FishNet/CodeGenerating/Extension/TypeDefinitionExtensions.cs +++ /dev/null @@ -1,254 +0,0 @@ -using FishNet.CodeGenerating.Helping.Extension; -using MonoFN.Cecil; - -namespace FishNet.CodeGenerating.Extension -{ - - - internal static class TypeDefinitionExtensions - { - - - /// - /// Returns if a TypeDefinition is nullable. - /// - public static bool IsNullable(this TypeDefinition td) - { - return (td.Name == typeof(System.Nullable<>).Name); - } - - - public static MethodReference GetMethodReferenceInBase(this TypeDefinition td, CodegenSession session, string methodName) - { - MethodDefinition baseMd = td.GetMethodDefinitionInBase(session, methodName); - if (baseMd == null) - return null; - - - MethodReference baseMr; - TypeReference baseTr = td.BaseType; - if (baseTr.CachedResolve(session).HasGenericParameters) - { - GenericInstanceType git = (GenericInstanceType)baseTr; - baseMr = new MethodReference(baseMd.Name, baseMd.ReturnType, git) - { - HasThis = baseMd.HasThis, - CallingConvention = baseMd.CallingConvention, - ExplicitThis = baseMd.ExplicitThis, - }; - foreach (ParameterDefinition pd in baseMd.Parameters) - { - session.ImportReference(pd.ParameterType); - baseMr.Parameters.Add(pd); - } - } - else - { - baseMr = session.ImportReference(baseMd); - } - - return baseMr; - } - /// - /// Returns a method in the next base class. - /// - public static MethodDefinition GetMethodDefinitionInBase(this TypeDefinition td, CodegenSession session, string methodName) - { - if (td.BaseType == null) - { - session.LogError($"BaseType for {td.FullName} is null."); - return null; - } - - TypeDefinition baseTd = td.BaseType.CachedResolve(session); - return baseTd.GetMethod(methodName); - } - - - /// - /// Returns a method in the next base class. - /// - public static MethodReference GetMethodReference(this TypeDefinition td, CodegenSession session, string methodName) - { - MethodDefinition md = td.GetMethod(methodName); - //Not found. - if (md == null) - return null; - - return md.GetMethodReference(session); - } - - /// - /// Gets a MethodReference or creates one if missing. - /// - public static MethodReference GetOrCreateMethodReference(this TypeDefinition td, CodegenSession session, string methodName, MethodAttributes attributes, TypeReference returnType, out bool created) - { - MethodDefinition md = td.GetMethod(methodName); - //Not found. - if (md == null) - { - md = new MethodDefinition(methodName, attributes, returnType); - td.Methods.Add(md); - created = true; - } - else - { - created = false; - } - - return md.GetMethodReference(session); - } - - - /// - /// Gets a MethodDefinition or creates one if missing. - /// - public static MethodDefinition GetOrCreateMethodDefinition(this TypeDefinition td, CodegenSession session, string methodName, MethodAttributes attributes, TypeReference returnType, out bool created) - { - MethodDefinition md = td.GetMethod(methodName); - //Not found. - if (md == null) - { - md = new MethodDefinition(methodName, attributes, returnType); - td.Methods.Add(md); - created = true; - } - else - { - created = false; - } - - return md; - } - - /// - /// Gets a MethodDefinition or creates one if missing. - /// - public static MethodDefinition GetOrCreateMethodDefinition(this TypeDefinition td, CodegenSession session, string methodName, MethodDefinition methodTemplate, bool copyParameters, out bool created) - { - MethodDefinition md = td.GetMethod(methodName); - //Not found. - if (md == null) - { - TypeReference returnType = session.ImportReference(methodTemplate.ReturnType); - md = new MethodDefinition(methodName, methodTemplate.Attributes, returnType) - { - ExplicitThis = methodTemplate.ExplicitThis, - AggressiveInlining = methodTemplate.AggressiveInlining, - Attributes = methodTemplate.Attributes, - CallingConvention = methodTemplate.CallingConvention, - HasThis = methodTemplate.HasThis, - }; - md.Body.InitLocals = methodTemplate.Body.InitLocals; - - if (copyParameters) - { - foreach (ParameterDefinition pd in methodTemplate.Parameters) - md.Parameters.Add(pd); - } - - td.Methods.Add(md); - created = true; - } - else - { - created = false; - } - - return md; - } - - - - /// - /// Returns a method in any inherited classes. The first found method is returned. - /// - public static MethodDefinition GetMethodDefinitionInAnyBase(this TypeDefinition td, CodegenSession session, string methodName) - { - while (td != null) - { - foreach (MethodDefinition md in td.Methods) - { - if (md.Name == methodName) - return md; - } - - try - { - td = td.GetNextBaseTypeDefinition(session); - } - catch - { - return null; - } - } - - return null; - } - - /// - /// Returns the next base type. - /// - public static TypeDefinition GetNextBaseTypeDefinition(this TypeDefinition typeDef, CodegenSession session) - { - return (typeDef.BaseType == null) ? null : typeDef.BaseType.CachedResolve(session); - } - - /// - /// Creates a FieldReference. - /// - public static FieldReference CreateFieldReference(this FieldDefinition fd, CodegenSession session) - { - FieldReference fr; - TypeDefinition declaringType = fd.DeclaringType; - //Is generic. - if (declaringType.HasGenericParameters) - { - GenericInstanceType git = new GenericInstanceType(declaringType); - foreach (GenericParameter item in declaringType.GenericParameters) - git.GenericArguments.Add(item); - fr = new FieldReference(fd.Name, fd.FieldType, git); - return fr; - } - //Not generic. - else - { - return session.ImportReference(fd); - } - } - - /// - /// Gets a FieldReference or creates it if missing. - /// - public static FieldReference GetOrCreateFieldReference(this TypeDefinition td, CodegenSession session, string fieldName, FieldAttributes attributes, TypeReference fieldTypeRef, out bool created) - { - FieldReference fr = td.GetFieldReference(fieldName, session); - if (fr == null) - { - fr = td.CreateFieldDefinition(session, fieldName, attributes, fieldTypeRef); - created = true; - } - else - { - created = false; - } - - return fr; - } - - /// - /// Creates a FieldReference. - /// - public static FieldReference CreateFieldDefinition(this TypeDefinition td, CodegenSession session, string fieldName, FieldAttributes attributes, TypeReference fieldTypeRef) - { - FieldDefinition fd = new FieldDefinition(fieldName, attributes, fieldTypeRef); - td.Fields.Add(fd); - return fd.CreateFieldReference(session); - } - - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Extension/TypeReferenceExtensions.cs b/Assets/FishNet/CodeGenerating/Extension/TypeReferenceExtensions.cs deleted file mode 100644 index 35ab37f..0000000 --- a/Assets/FishNet/CodeGenerating/Extension/TypeReferenceExtensions.cs +++ /dev/null @@ -1,59 +0,0 @@ - -using FishNet.CodeGenerating.Helping; -using FishNet.CodeGenerating.Helping.Extension; -using MonoFN.Cecil; -using UnityEngine; - -namespace FishNet.CodeGenerating.Extension -{ - - - internal static class TypeReferenceExtensions - { - - /// - /// Returns if a TypeReference is nullable. - /// - public static bool IsNullable(this TypeReference tr, CodegenSession session) - { - TypeDefinition td = tr.CachedResolve(session); - return td.IsNullable(); - } - - /// - /// Returns the fullname of a TypeReference without <>. - /// - /// - /// - public static string GetFullnameWithoutBrackets(this TypeReference tr) - { - string str = tr.FullName; - str = str.Replace("<", ""); - str = str.Replace(">", ""); - return str; - } - - /// - /// Returns a method in the next base class. - /// - public static MethodReference GetMethodInBase(this TypeReference tr, CodegenSession session, string methodName) - { - return tr.CachedResolve(session).GetMethodInBase(session, methodName); - } - - /// - /// Makes a GenericInstanceType. - /// - public static GenericInstanceType MakeGenericInstanceType(this TypeReference self) - { - GenericInstanceType instance = new GenericInstanceType(self); - foreach (GenericParameter argument in self.GenericParameters) - instance.GenericArguments.Add(argument); - - return instance; - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/FN_README.txt b/Assets/FishNet/CodeGenerating/FN_README.txt deleted file mode 100644 index 3efe3cf..0000000 --- a/Assets/FishNet/CodeGenerating/FN_README.txt +++ /dev/null @@ -1,9 +0,0 @@ -After updating a custom Cecil to fix conflict with Unity.Burst in 2021 perform the following: - -- Open cecil in it's own project; eg: do not place directly in FN. -- Rename namespace.Mono to namespace.MonoFN. -- Current project rename strings, "Mono to "MonoFN -- Replace current project #if INSIDE_ROCKS to #if UNITY_EDITOR -- Comment out `[assembly: AssemblyTitle ("MonoFN.Cecil.Rocks")]` within rocks\Mono.Cecil.Rocks\AssemblyInfo.cs. -- Delete obj/bin/tests folders. -- Copy into FN project. diff --git a/Assets/FishNet/CodeGenerating/FN_README.txt.meta b/Assets/FishNet/CodeGenerating/FN_README.txt.meta deleted file mode 100644 index 04e8428..0000000 --- a/Assets/FishNet/CodeGenerating/FN_README.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 9133eb285bd7f3c4f89f4d7a2a079c6b -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs deleted file mode 100644 index 15b6c4f..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs +++ /dev/null @@ -1,94 +0,0 @@ -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.Object; -using FishNet.Object.Helping; -using FishNet.Object.Prediction; -using FishNet.Object.Synchronizing; -using MonoFN.Cecil; - - -namespace FishNet.CodeGenerating.Helping -{ - internal class AttributeHelper : CodegenBase - { - #region Reflection references. - internal string ReplicateAttribute_FullName; - internal string ReconcileAttribute_FullName; - private string ServerAttribute_FullName; - private string ClientAttribute_FullName; - private string ServerRpcAttribute_FullName; - private string ObserversRpcAttribute_FullName; - private string TargetRpcAttribute_FullName; - private string SyncVarAttribute_FullName; - private string SyncObjectAttribute_FullName; - #endregion - - public override bool ImportReferences() - { - ServerAttribute_FullName = typeof(ServerAttribute).FullName; - ClientAttribute_FullName = typeof(ClientAttribute).FullName; - ServerRpcAttribute_FullName = typeof(ServerRpcAttribute).FullName; - ObserversRpcAttribute_FullName = typeof(ObserversRpcAttribute).FullName; - TargetRpcAttribute_FullName = typeof(TargetRpcAttribute).FullName; - SyncVarAttribute_FullName = typeof(SyncVarAttribute).FullName; - SyncObjectAttribute_FullName = typeof(SyncObjectAttribute).FullName; - ReplicateAttribute_FullName = typeof(ReplicateAttribute).FullName; - ReconcileAttribute_FullName = typeof(ReconcileAttribute).FullName; - - return true; - } - - /// - /// Returns type of Rpc attributeFullName is for. - /// - /// - /// - public RpcType GetRpcAttributeType(CustomAttribute ca) - { - if (ca.Is(ServerRpcAttribute_FullName)) - return RpcType.Server; - else if (ca.Is(ObserversRpcAttribute_FullName)) - return RpcType.Observers; - else if (ca.Is(TargetRpcAttribute_FullName)) - return RpcType.Target; - else - return RpcType.None; - } - - - /// - /// Returns type of Rpc attributeFullName is for. - /// - /// - /// - internal QolAttributeType GetQolAttributeType(string attributeFullName) - { - if (attributeFullName == ServerAttribute_FullName) - return QolAttributeType.Server; - else if (attributeFullName == ClientAttribute_FullName) - return QolAttributeType.Client; - else - return QolAttributeType.None; - } - - - /// - /// Returns if attribute if a SyncVarAttribute. - /// - /// - /// - public bool IsSyncVarAttribute(string attributeFullName) - { - return (attributeFullName == SyncVarAttribute_FullName); - } - /// - /// Returns if attribute if a SyncObjectAttribute. - /// - /// - /// - public bool IsSyncObjectAttribute(string attributeFullName) - { - return (attributeFullName == SyncObjectAttribute_FullName); - } - } - -} diff --git a/Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs.meta deleted file mode 100644 index d84b8e4..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/AttributeHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d32f3dc23b55598429c5cfe6156e6243 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs b/Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs deleted file mode 100644 index 6448c24..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs +++ /dev/null @@ -1,194 +0,0 @@ -using FishNet.CodeGenerating.Helping; -using FishNet.CodeGenerating.ILCore; -using FishNet.CodeGenerating.Processing; -using FishNet.CodeGenerating.Processing.Rpc; -using MonoFN.Cecil; -using System.Collections.Generic; -using System.Linq; -using Unity.CompilationPipeline.Common.Diagnostics; -#if !UNITY_2020_1_OR_NEWER -using UnityEngine; -#endif -using SR = System.Reflection; - - -namespace FishNet.CodeGenerating -{ - - internal class CodegenSession - { - /// - /// Current module for this session. - /// - internal ModuleDefinition Module; - /// - /// Outputs errors when codegen fails. - /// - internal List Diagnostics; - /// - /// SyncVars that are being accessed from an assembly other than the currently being processed one. - /// - internal List DifferentAssemblySyncVars = new List(); - - - /// - /// CodegenBase classes for processing a module. - /// - private List _bases; - /// - /// Quick lookup of base classes. - /// - private Dictionary _basesCache = new Dictionary(); - - /// - /// Returns class of type if found within CodegenBase classes. - /// - /// - /// - internal T GetClass() where T : CodegenBase - { - string tName = typeof(T).Name; - return (T)_basesCache[tName]; - } - /// - /// Resets all helpers while importing any information needed by them. - /// - /// - /// - internal bool Initialize(ModuleDefinition module) - { - Module = module; - Diagnostics = new List(); - - _bases = new List() - { - new ReaderImports(), new ReaderProcessor() - ,new WriterImports(), new WriterProcessor() - , new PhysicsHelper(), new TimeManagerHelper(), new AttributeHelper(), new GeneralHelper() - , new ObjectHelper(), new NetworkBehaviourHelper() - , new CreatedSyncVarGenerator(), new TransportHelper() - , new NetworkConnectionImports(), new PredictedObjectHelper(), new GeneratorHelper() - , new CustomSerializerProcessor() - , new NetworkBehaviourProcessor() - , new QolAttributeProcessor() - , new RpcProcessor() - , new NetworkBehaviourSyncProcessor() - , new PredictionProcessor() - }; - - //Add all to dictionary first, then import. - foreach (CodegenBase item in _bases) - { - string tName = item.GetType().Name; - _basesCache.Add(tName, item); - } - - //Initialize. - foreach (CodegenBase item in _bases) - { - item.Initialize(this); - if (!item.ImportReferences()) - return false; - } - - return true; - } - - - - - #region Logging. - /// - /// Logs a warning. - /// - /// - internal void LogWarning(string msg) - { -#if UNITY_2020_1_OR_NEWER - Diagnostics.AddWarning(msg); -#else - Debug.LogWarning(msg); -#endif - } - /// - /// Logs an error. - /// - /// - internal void LogError(string msg) - { -#if UNITY_2020_1_OR_NEWER - Diagnostics.AddError(msg); -#else - Debug.LogError(msg); -#endif - } - #endregion - - #region ImportReference. - - public MethodReference ImportReference(SR.MethodBase method) - { - return Module.ImportReference(method); - } - - public MethodReference ImportReference(SR.MethodBase method, IGenericParameterProvider context) - { - return Module.ImportReference(method, context); - } - - public TypeReference ImportReference(TypeReference type) - { - return Module.ImportReference(type); - } - - public TypeReference ImportReference(TypeReference type, IGenericParameterProvider context) - { - return Module.ImportReference(type, context); - } - - public FieldReference ImportReference(FieldReference field) - { - return Module.ImportReference(field); - } - - public FieldReference ImportReference(FieldReference field, IGenericParameterProvider context) - { - return Module.ImportReference(field, context); - } - public MethodReference ImportReference(MethodReference method) - { - return Module.ImportReference(method); - } - - public MethodReference ImportReference(MethodReference method, IGenericParameterProvider context) - { - return Module.ImportReference(method, context); - } - public TypeReference ImportReference(System.Type type) - { - return ImportReference(type, null); - } - - - public TypeReference ImportReference(System.Type type, IGenericParameterProvider context) - { - return Module.ImportReference(type, context); - } - - - public FieldReference ImportReference(SR.FieldInfo field) - { - return Module.ImportReference(field); - } - - public FieldReference ImportReference(SR.FieldInfo field, IGenericParameterProvider context) - { - return Module.ImportReference(field, context); - } - - #endregion - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs.meta deleted file mode 100644 index 3373edc..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/CodegenSession.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3e8416eee3308f54fa942003de975420 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs b/Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs deleted file mode 100644 index 89b1cc7..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs +++ /dev/null @@ -1,121 +0,0 @@ -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.CodeGenerating.Processing; -using FishNet.Object.Synchronizing; -using FishNet.Object.Synchronizing.Internal; -using MonoFN.Cecil; -using MonoFN.Cecil.Rocks; -using System; -using System.Collections.Generic; - -namespace FishNet.CodeGenerating.Helping -{ - internal class CreatedSyncVarGenerator : CodegenBase - { - private readonly Dictionary _createdSyncVars = new Dictionary(); - - #region Relfection references. - private TypeReference _syncBase_TypeRef; - internal TypeReference SyncVar_TypeRef; - private MethodReference _syncVar_Constructor_MethodRef; - #endregion - - #region Const. - private const string GETVALUE_NAME = "GetValue"; - private const string SETVALUE_NAME = "SetValue"; - #endregion - - /* //feature add and test the dirty boolean changes - * eg... instead of base.Dirty() - * do if (!base.Dirty()) return false; - * See synclist for more info. */ - - /// - /// Imports references needed by this helper. - /// - /// - /// - public override bool ImportReferences() - { - SyncVar_TypeRef = base.ImportReference(typeof(SyncVar<>)); - MethodDefinition svConstructor = SyncVar_TypeRef.GetFirstConstructor(base.Session, true); - _syncVar_Constructor_MethodRef = base.ImportReference(svConstructor); - - Type syncBaseType = typeof(SyncBase); - _syncBase_TypeRef = base.ImportReference(syncBaseType); - - return true; - } - - /// - /// Gets and optionally creates data for SyncVar - /// - /// - /// - internal CreatedSyncVar GetCreatedSyncVar(FieldDefinition originalFd, bool createMissing) - { - TypeReference dataTr = originalFd.FieldType; - TypeDefinition dataTd = dataTr.CachedResolve(base.Session); - - string typeHash = dataTr.FullName + dataTr.IsArray.ToString(); - - if (_createdSyncVars.TryGetValue(typeHash, out CreatedSyncVar createdSyncVar)) - { - return createdSyncVar; - } - else - { - if (!createMissing) - return null; - - base.ImportReference(dataTd); - - GenericInstanceType syncVarGit = SyncVar_TypeRef.MakeGenericInstanceType(new TypeReference[] { dataTr }); - TypeReference genericDataTr = syncVarGit.GenericArguments[0]; - - //Make sure can serialize. - bool canSerialize = base.GetClass().HasSerializerAndDeserializer(genericDataTr, true); - if (!canSerialize) - { - base.LogError($"SyncVar {originalFd.Name} data type {genericDataTr.FullName} does not support serialization. Use a supported type or create a custom serializer."); - return null; - } - - //Set needed methods from syncbase. - MethodReference setSyncIndexMr; - MethodReference genericSyncVarCtor = _syncVar_Constructor_MethodRef.MakeHostInstanceGeneric(base.Session, syncVarGit); - - if (!base.GetClass().SetSyncBaseMethods(_syncBase_TypeRef.CachedResolve(base.Session), out setSyncIndexMr, out _)) - return null; - - MethodReference setValueMr = null; - MethodReference getValueMr = null; - foreach (MethodDefinition md in SyncVar_TypeRef.CachedResolve(base.Session).Methods) - { - //GetValue. - if (md.Name == GETVALUE_NAME) - { - MethodReference mr = base.ImportReference(md); - getValueMr = mr.MakeHostInstanceGeneric(base.Session, syncVarGit); - } - //SetValue. - else if (md.Name == SETVALUE_NAME) - { - MethodReference mr = base.ImportReference(md); - setValueMr = mr.MakeHostInstanceGeneric(base.Session, syncVarGit); - } - } - - if (setValueMr == null || getValueMr == null) - return null; - - CreatedSyncVar csv = new CreatedSyncVar(syncVarGit, dataTd, getValueMr, setValueMr, setSyncIndexMr, null, genericSyncVarCtor); - _createdSyncVars.Add(typeHash, csv); - return csv; - } - } - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs.meta deleted file mode 100644 index 086dc59..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/CreatedSyncVarGenerator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 935ec97b96b35b94f8c6880c6908304c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension.meta deleted file mode 100644 index a4c0b09..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: df90983b61081f84b990ac494ac8bdb6 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs deleted file mode 100644 index b11e91c..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs +++ /dev/null @@ -1,54 +0,0 @@ -using MonoFN.Cecil; -using System.Linq; - -namespace FishNet.CodeGenerating.Helping.Extension -{ - - internal static class CustomAttributeExtensions - { - /// - /// Finds a field within an attribute. - /// - /// - /// - /// - /// - /// - internal static T GetField(this CustomAttribute customAttr, string field, T defaultValue) - { - foreach (CustomAttributeNamedArgument customField in customAttr.Fields) - { - if (customField.Name == field) - { - return (T)customField.Argument.Value; - } - } - - return defaultValue; - } - - /// - /// Returns if any of the attributes match IAtrribute. - /// - /// - /// - /// - internal static bool HasCustomAttribute(this ICustomAttributeProvider attributeProvider) - { - return attributeProvider.CustomAttributes.Any(attr => attr.AttributeType.Is()); - } - - /// - /// Returns if ca is of type target. - /// - /// - /// - /// - internal static bool Is(this CustomAttribute ca, string targetFullName) - { - return ca.AttributeType.FullName == targetFullName; - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs.meta deleted file mode 100644 index 87b14e3..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/CustomAttributeExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a66d771ab331fae408142a5c04abd74e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs deleted file mode 100644 index 5fda8fe..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs +++ /dev/null @@ -1,41 +0,0 @@ -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Unity.CompilationPipeline.Common.Diagnostics; - -namespace FishNet.CodeGenerating.Helping -{ - internal static class Diagnostics - { - internal static void AddError(this List diagnostics, string message) - { - diagnostics.AddMessage(DiagnosticType.Error, (SequencePoint)null, message); - } - - internal static void AddWarning(this List diagnostics, string message) - { - diagnostics.AddMessage(DiagnosticType.Warning, (SequencePoint)null, message); - } - - internal static void AddError(this List diagnostics, MethodDefinition methodDef, string message) - { - diagnostics.AddMessage(DiagnosticType.Error, methodDef.DebugInformation.SequencePoints.FirstOrDefault(), message); - } - - internal static void AddMessage(this List diagnostics, DiagnosticType diagnosticType, SequencePoint sequencePoint, string message) - { - diagnostics.Add(new DiagnosticMessage - { - DiagnosticType = diagnosticType, - File = sequencePoint?.Document.Url.Replace($"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}", ""), - Line = sequencePoint?.StartLine ?? 0, - Column = sequencePoint?.StartColumn ?? 0, - MessageData = $" - {message}" - }); - } - - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs.meta deleted file mode 100644 index a70954f..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/Diagnostics.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fb7b65b572b01444cbe3c9d830cd3587 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/FieldReferenceExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/FieldReferenceExtensions.cs deleted file mode 100644 index 803d4de..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/FieldReferenceExtensions.cs +++ /dev/null @@ -1,38 +0,0 @@ -using FishNet.CodeGenerating.Extension; -using MonoFN.Cecil; - -namespace FishNet.CodeGenerating.Helping.Extension -{ - - internal static class FieldReferenceExtensions - { - - /// - /// Gets a Resolve favoring cached results first. - /// - internal static FieldDefinition CachedResolve(this FieldReference fieldRef, CodegenSession session) - { - return session.GetClass().GetFieldReferenceResolve(fieldRef); - } - - - public static FieldReference MakeHostGenericIfNeeded(this FieldDefinition fd, CodegenSession session) - { - TypeReference declaringTr = fd.DeclaringType; - - if (declaringTr.HasGenericParameters) - { - GenericInstanceType git = declaringTr.MakeGenericInstanceType(); - FieldReference result = new FieldReference(fd.Name, fd.FieldType, git); - return result; - } - else - { - return session.ImportReference(fd); - } - } - - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/FieldReferenceExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/FieldReferenceExtensions.cs.meta deleted file mode 100644 index c868340..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/FieldReferenceExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6d983ebd0c9e1b745902030c2f7a8e99 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs deleted file mode 100644 index 2d38cdd..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs +++ /dev/null @@ -1,191 +0,0 @@ -using FishNet.CodeGenerating.Helping.Extension; -using MonoFN.Cecil; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.CodeGenerating.Helping -{ - internal static class Constructors - { - - /// - /// Gets the first constructor that optionally has, or doesn't have parameters. - /// - /// - /// - public static MethodDefinition GetFirstConstructor(this TypeReference typeRef, CodegenSession session, bool requireParameters) - { - return typeRef.CachedResolve(session).GetFirstConstructor(requireParameters); - } - /// - /// Gets the first constructor that optionally has, or doesn't have parameters. - /// - /// - /// - public static MethodDefinition GetFirstConstructor(this TypeDefinition typeDef, bool requireParameters) - { - - foreach (MethodDefinition methodDef in typeDef.Methods) - { - if (methodDef.IsConstructor && methodDef.IsPublic) - { - if (requireParameters && methodDef.Parameters.Count > 0) - return methodDef; - else if (!requireParameters && methodDef.Parameters.Count == 0) - return methodDef; - } - - } - - return null; - } - - /// - /// Gets the first public constructor with no parameters. - /// - /// - public static MethodDefinition GetConstructor(this TypeReference typeRef, CodegenSession session) - { - return typeRef.CachedResolve(session).GetConstructor(); - } - /// - /// Gets the first public constructor with no parameters. - /// - /// - public static MethodDefinition GetConstructor(this TypeDefinition typeDef) - { - foreach (MethodDefinition methodDef in typeDef.Methods) - { - if (methodDef.IsConstructor && methodDef.IsPublic && methodDef.Parameters.Count == 0) - return methodDef; - } - - return null; - } - - /// - /// Gets all constructors on typeDef. - /// - /// - public static List GetConstructors(this TypeDefinition typeDef) - { - List lst = new List(); - foreach (MethodDefinition methodDef in typeDef.Methods) - { - if (methodDef.IsConstructor) - lst.Add(methodDef); - } - - return lst; - } - - - /// - /// Gets constructor which has arguments. - /// - /// - /// - public static MethodDefinition GetConstructor(this TypeReference typeRef, CodegenSession session, Type[] arguments) - { - return typeRef.CachedResolve(session).GetConstructor(arguments); - } - - /// - /// Gets constructor which has arguments. - /// - /// - /// - public static MethodDefinition GetConstructor(this TypeDefinition typeDef, Type[] arguments) - { - Type[] argsCopy = (arguments == null) ? new Type[0] : arguments; - foreach (MethodDefinition methodDef in typeDef.Methods) - { - if (methodDef.IsConstructor && methodDef.IsPublic && methodDef.Parameters.Count == argsCopy.Length) - { - bool match = true; - for (int i = 0; i < argsCopy.Length; i++) - { - if (methodDef.Parameters[0].ParameterType.FullName != argsCopy[i].FullName) - { - match = false; - break; - } - } - - if (match) - return methodDef; - } - } - return null; - } - - - /// - /// Gets constructor which has arguments. - /// - /// - /// - public static MethodDefinition GetConstructor(this TypeReference typeRef, CodegenSession session, TypeReference[] arguments) - { - return typeRef.CachedResolve(session).GetConstructor(arguments); - } - - /// - /// Gets constructor which has arguments. - /// - /// - /// - public static MethodDefinition GetConstructor(this TypeDefinition typeDef, TypeReference[] arguments) - { - TypeReference[] argsCopy = (arguments == null) ? new TypeReference[0] : arguments; - foreach (MethodDefinition methodDef in typeDef.Methods) - { - if (methodDef.IsConstructor && methodDef.IsPublic && methodDef.Parameters.Count == argsCopy.Length) - { - bool match = true; - for (int i = 0; i < argsCopy.Length; i++) - { - if (methodDef.Parameters[0].ParameterType.FullName != argsCopy[i].FullName) - { - match = false; - break; - } - } - - if (match) - return methodDef; - } - } - return null; - } - - /// - /// Resolves the constructor with parameterCount for typeRef. - /// - /// - /// - public static MethodDefinition GetConstructor(this TypeReference typeRef, CodegenSession session, int parameterCount) - { - return typeRef.CachedResolve(session).GetConstructor(parameterCount); - } - - - /// - /// Resolves the constructor with parameterCount for typeRef. - /// - /// - /// - public static MethodDefinition GetConstructor(this TypeDefinition typeDef, int parameterCount) - { - foreach (MethodDefinition methodDef in typeDef.Methods) - { - if (methodDef.IsConstructor && methodDef.IsPublic && methodDef.Parameters.Count == parameterCount) - return methodDef; - } - return null; - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs.meta deleted file mode 100644 index c66fc8f..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/GetConstructor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1a7e03137ca78704e999f3a3dc68b953 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs deleted file mode 100644 index 2ff3d20..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs +++ /dev/null @@ -1,169 +0,0 @@ -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using System.Collections.Generic; - -namespace FishNet.CodeGenerating.Helping.Extension -{ - - internal static class ILProcessorExtensions - { - - /// - /// Creates a debug log for text without any conditions. - /// - public static void DebugLog(this ILProcessor processor, CodegenSession session, string txt) - { - processor.Emit(OpCodes.Ldstr, txt); - processor.Emit(OpCodes.Call, session.GetClass().Debug_LogCommon_MethodRef); - } - /// - /// Creates a debug log for vd without any conditions. - /// - public static void DebugLog(this ILProcessor processor, CodegenSession session, VariableDefinition vd) - { - processor.Emit(OpCodes.Ldloc, vd); - processor.Emit(OpCodes.Box, vd.VariableType); - processor.Emit(OpCodes.Call, session.GetClass().Debug_LogCommon_MethodRef); - } - /// - /// Creates a debug log for vd without any conditions. - /// - public static void DebugLog(this ILProcessor processor, CodegenSession session, FieldDefinition fd, bool loadArg0) - { - if (loadArg0) - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldfld, fd); - processor.Emit(OpCodes.Box, fd.FieldType); - processor.Emit(OpCodes.Call, session.GetClass().Debug_LogCommon_MethodRef); - } - /// - /// Creates a debug log for pd without any conditions. - /// - public static void DebugLog(this ILProcessor processor, CodegenSession session, ParameterDefinition pd) - { - processor.Emit(OpCodes.Ldloc, pd); - processor.Emit(OpCodes.Box, pd.ParameterType); - processor.Emit(OpCodes.Call, session.GetClass().Debug_LogCommon_MethodRef); - } - - ///// - ///// Creates a debug log for mr without any conditions. - ///// - //public static void DebugLog(this ILProcessor processor, MethodReference mr) - //{ - // processor.Emit(OpCodes.Call, mr); - // processor.Emit(OpCodes.Box, mr.ReturnType); - // processor.Emit(OpCodes.Call, base.GetClass().Debug_LogCommon_MethodRef); - //} - - - /// - /// Inserts instructions at the beginning. - /// - /// - /// - public static void InsertAt(this ILProcessor processor, int target, List instructions) - { - for (int i = 0; i < instructions.Count; i++) - processor.Body.Instructions.Insert(i + target, instructions[i]); - } - - - /// - /// Inserts instructions at the beginning. - /// - /// - /// - public static void InsertFirst(this ILProcessor processor, List instructions) - { - for (int i = 0; i < instructions.Count; i++) - processor.Body.Instructions.Insert(i, instructions[i]); - } - - /// - /// Inserts instructions at the end while also moving Ret down. - /// - /// - /// - public static void InsertLast(this ILProcessor processor, List instructions) - { - bool retRemoved = false; - int startingCount = processor.Body.Instructions.Count; - //Remove ret if it exist and add it back in later. - if (startingCount > 0) - { - if (processor.Body.Instructions[startingCount - 1].OpCode == OpCodes.Ret) - { - processor.Body.Instructions.RemoveAt(startingCount - 1); - retRemoved = true; - } - } - - foreach (Instruction inst in instructions) - processor.Append(inst); - - //Add ret back if it was removed. - if (retRemoved) - processor.Emit(OpCodes.Ret); - } - - /// - /// Inserts instructions before target. - /// - /// - /// - public static void InsertBefore(this ILProcessor processor, Instruction target, List instructions) - { - int index = processor.Body.Instructions.IndexOf(target); - for (int i = 0; i < instructions.Count; i++) - processor.Body.Instructions.Insert(index + i, instructions[i]); - } - - /// - /// Adds instructions to the end of processor. - /// - /// - /// - public static void Add(this ILProcessor processor, List instructions) - { - for (int i = 0; i < instructions.Count; i++) - processor.Body.Instructions.Add(instructions[i]); - } - - /// - /// Inserts instructions before returns. Only works on void types. - /// - /// - /// - public static void InsertBeforeReturns(this ILProcessor processor, CodegenSession session, List instructions) - { - if (processor.Body.Method.ReturnType.FullName != session.Module.TypeSystem.Void.FullName) - { - session.LogError($"Cannot insert instructions before returns on {processor.Body.Method.FullName} because it does not return void."); - return; - } - - /* Insert at the end of the method - * and get the first instruction that was inserted. - * Any returns or breaks which would exit the method - * will jump to this instruction instead. */ - processor.InsertLast(instructions); - Instruction startInst = processor.Body.Instructions[processor.Body.Instructions.Count - instructions.Count]; - - //Look for anything that jumps to rets. - for (int i = 0; i < processor.Body.Instructions.Count; i++) - { - Instruction inst = processor.Body.Instructions[i]; - if (inst.Operand is Instruction operInst) - { - if (operInst.OpCode == OpCodes.Ret) - inst.Operand = startInst; - } - } - } - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs.meta deleted file mode 100644 index dfed3f0..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/ILProcessorExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 820cf8401d4d71c4196dda444559ef8a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs deleted file mode 100644 index aefd42c..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs +++ /dev/null @@ -1,12 +0,0 @@ -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using System; -using System.Collections.Generic; - -namespace FishNet.CodeGenerating.Helping -{ - public static class Instructions - { - } - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs.meta deleted file mode 100644 index ba87cbb..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/InstructionExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 360667149f16b6c4aba61fd05427cbfb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodDefinitionExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodDefinitionExtensions.cs deleted file mode 100644 index 373321a..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodDefinitionExtensions.cs +++ /dev/null @@ -1,55 +0,0 @@ -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; - -namespace FishNet.CodeGenerating.Helping.Extension -{ - - internal static class MethodDefinitionExtensions - { - /// - /// Clears the method content and returns ret. - /// - internal static void ClearMethodWithRet(this MethodDefinition md, CodegenSession session, ModuleDefinition importReturnModule = null) - { - md.Body.Instructions.Clear(); - ILProcessor processor = md.Body.GetILProcessor(); - processor.Add(session.GetClass().CreateRetDefault(md, importReturnModule)); - } - - /// - /// Returns the ParameterDefinition index from end of parameters. - /// - /// - /// - /// - internal static ParameterDefinition GetEndParameter(this MethodDefinition md, int index) - { - //Not enough parameters. - if (md.Parameters.Count < (index + 1)) - return null; - - return md.Parameters[md.Parameters.Count - (index + 1)]; - } - - - /// - /// Creates a variable type within the body and returns it's VariableDef. - /// - internal static VariableDefinition CreateVariable(this MethodDefinition methodDef, TypeReference variableTypeRef) - { - VariableDefinition variableDef = new VariableDefinition(variableTypeRef); - methodDef.Body.Variables.Add(variableDef); - return variableDef; - } - - /// - /// Creates a variable type within the body and returns it's VariableDef. - /// - internal static VariableDefinition CreateVariable(this MethodDefinition methodDef, CodegenSession session, System.Type variableType) - { - return CreateVariable(methodDef, session.GetClass().GetTypeReference(variableType)); - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodDefinitionExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodDefinitionExtensions.cs.meta deleted file mode 100644 index a64ef0a..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodDefinitionExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 999d4ae4862274f4ba50569c221976dd -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs deleted file mode 100644 index c55390c..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs +++ /dev/null @@ -1,155 +0,0 @@ -using MonoFN.Cecil; -using MonoFN.Cecil.Rocks; -using System; - -namespace FishNet.CodeGenerating.Helping.Extension -{ - - internal static class MethodReferenceExtensions - { - /// - /// Makes a generic method with specified arguments. - /// - /// - /// - /// - public static GenericInstanceMethod MakeGenericMethod(this MethodReference method, params TypeReference[] genericArguments) - { - GenericInstanceMethod result = new GenericInstanceMethod(method); - foreach (TypeReference argument in genericArguments) - result.GenericArguments.Add(argument); - return result; - } - - /// - /// Makes a generic method with the same arguments as the original. - /// - /// - /// - public static GenericInstanceMethod MakeGenericMethod(this MethodReference method) - { - GenericInstanceMethod result = new GenericInstanceMethod(method); - foreach (ParameterDefinition pd in method.Parameters) - result.GenericArguments.Add(pd.ParameterType); - - return result; - } - - /// - /// Returns a method reference for a generic method. - /// - public static MethodReference GetMethodReference(this MethodReference mr, CodegenSession session, TypeReference typeReference) - { - return mr.GetMethodReference(session, new TypeReference[] { typeReference }); - } - - /// - /// Returns a method reference for a generic method. - /// - public static MethodReference GetMethodReference(this MethodReference mr, CodegenSession session, TypeReference[] typeReferences) - { - if (mr.HasGenericParameters) - { - if (typeReferences == null || typeReferences.Length == 0) - { - session.LogError($"Method {mr.Name} has generic parameters but TypeReferences are null or 0 length."); - return null; - } - else - { - GenericInstanceMethod gim = mr.MakeGenericMethod(typeReferences); - return gim; - } - } - else - { - return mr; - } - } - - - /// - /// Gets a Resolve favoring cached results first. - /// - internal static MethodDefinition CachedResolve(this MethodReference methodRef, CodegenSession session) - { - return session.GetClass().GetMethodReferenceResolve(methodRef); - } - - /// - /// Given a method of a generic class such as ArraySegment`T.get_Count, - /// and a generic instance such as ArraySegment`int - /// Creates a reference to the specialized method ArraySegment`int`.get_Count - /// Note that calling ArraySegment`T.get_Count directly gives an invalid IL error - /// - /// - /// - /// - public static MethodReference MakeHostInstanceGeneric(this MethodReference self, CodegenSession session, GenericInstanceType instanceType) - { - MethodReference reference = new MethodReference(self.Name, self.ReturnType, instanceType) - { - CallingConvention = self.CallingConvention, - HasThis = self.HasThis, - ExplicitThis = self.ExplicitThis - }; - - foreach (ParameterDefinition parameter in self.Parameters) - reference.Parameters.Add(new ParameterDefinition(parameter.ParameterType)); - - foreach (GenericParameter generic_parameter in self.GenericParameters) - reference.GenericParameters.Add(new GenericParameter(generic_parameter.Name, reference)); - - return session.ImportReference(reference); - } - /// - /// Given a method of a generic class such as ArraySegment`T.get_Count, - /// and a generic instance such as ArraySegment`int - /// Creates a reference to the specialized method ArraySegment`int`.get_Count - /// Note that calling ArraySegment`T.get_Count directly gives an invalid IL error - /// - /// - /// - /// - public static MethodReference MakeHostInstanceGeneric(this MethodReference self, TypeReference typeRef, params TypeReference[] args) - { - GenericInstanceType git = typeRef.MakeGenericInstanceType(args); - MethodReference reference = new MethodReference(self.Name, self.ReturnType, git) - { - CallingConvention = self.CallingConvention, - HasThis = self.HasThis, - ExplicitThis = self.ExplicitThis - }; - - foreach (ParameterDefinition parameter in self.Parameters) - reference.Parameters.Add(new ParameterDefinition(parameter.ParameterType)); - - foreach (GenericParameter generic_parameter in self.GenericParameters) - reference.GenericParameters.Add(new GenericParameter(generic_parameter.Name, reference)); - - return reference; - } - public static bool Is(this MethodReference method, string name) - { - return method.DeclaringType.Is() && method.Name == name; - } - public static bool Is(this TypeReference td) - { - return Is(td, typeof(T)); - } - - public static bool Is(this TypeReference td, Type t) - { - if (t.IsGenericType) - { - return td.GetElementType().FullName == t.FullName; - } - return td.FullName == t.FullName; - } - - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs.meta deleted file mode 100644 index 1a5c3a8..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/MethodReferenceExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ee1c15a06ab386e439ec5aa41e3496f7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/ModuleDefinitionExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/ModuleDefinitionExtensions.cs deleted file mode 100644 index e52e04b..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/ModuleDefinitionExtensions.cs +++ /dev/null @@ -1,63 +0,0 @@ -using FishNet.CodeGenerating.ILCore; -using MonoFN.Cecil; -using System; -using System.Linq.Expressions; -using System.Reflection; - -namespace FishNet.CodeGenerating.Helping.Extension -{ - - public static class ModuleDefinitionExtensions - { - /// - /// Gets a class within a module. - /// - /// - /// - public static TypeDefinition GetClass(this ModuleDefinition moduleDef, string className, string namespaceName = "") - { - if (namespaceName.Length == 0) - namespaceName = FishNetILPP.RUNTIME_ASSEMBLY_NAME; - - return moduleDef.GetType(namespaceName, className); - } - - public static MethodReference ImportReference(this ModuleDefinition moduleDef, Expression expression) - { - return ImportReference(moduleDef, (LambdaExpression)expression); - } - public static MethodReference ImportReference(this ModuleDefinition module, Expression> expression) - { - return ImportReference(module, (LambdaExpression)expression); - } - - public static MethodReference ImportReference(this ModuleDefinition module, LambdaExpression expression) - { - if (expression.Body is MethodCallExpression outermostExpression) - { - MethodInfo methodInfo = outermostExpression.Method; - return module.ImportReference(methodInfo); - } - - if (expression.Body is NewExpression newExpression) - { - ConstructorInfo methodInfo = newExpression.Constructor; - // constructor is null when creating an ArraySegment - methodInfo = methodInfo ?? newExpression.Type.GetConstructors()[0]; - return module.ImportReference(methodInfo); - } - - if (expression.Body is MemberExpression memberExpression) - { - var property = memberExpression.Member as PropertyInfo; - return module.ImportReference(property.GetMethod); - } - - throw new ArgumentException($"Invalid Expression {expression.Body.GetType()}"); - } - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/ModuleDefinitionExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/ModuleDefinitionExtensions.cs.meta deleted file mode 100644 index a712e78..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/ModuleDefinitionExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 42648785493390646898f5fa13e1dfd6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/ParameterDefinitionExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/ParameterDefinitionExtensions.cs deleted file mode 100644 index 542524a..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/ParameterDefinitionExtensions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using MonoFN.Cecil; -using System; - -namespace FishNet.CodeGenerating.Helping.Extension -{ - - internal static class ParameterDefinitionExtensions - { - /// - /// Returns if parameterDef is Type. - /// - /// - /// - /// - public static bool Is(this ParameterDefinition parameterDef, Type type) - { - return parameterDef.ParameterType.FullName == type.FullName; - } - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/ParameterDefinitionExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/ParameterDefinitionExtensions.cs.meta deleted file mode 100644 index bcb2358..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/ParameterDefinitionExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 31071055a2e388141b8f11e1ba4e147e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/TypeDefinitionExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/TypeDefinitionExtensions.cs deleted file mode 100644 index f5ea4ff..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/TypeDefinitionExtensions.cs +++ /dev/null @@ -1,521 +0,0 @@ -using FishNet.CodeGenerating.Extension; -using MonoFN.Cecil; -using MonoFN.Collections.Generic; -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace FishNet.CodeGenerating.Helping.Extension -{ - - - internal static class TypeDefinitionExtensionsOld - { - - /// - /// Creates a GenericInstanceType and adds parameters. - /// - internal static GenericInstanceType CreateGenericInstanceType(this TypeDefinition type, Collection parameters) - { - GenericInstanceType git = new GenericInstanceType(type); - foreach (GenericParameter gp in parameters) - git.GenericArguments.Add(gp); - - return git; - } - - /// - /// Finds public fields in type and base type - /// - /// - /// - public static IEnumerable FindAllPublicFields(this TypeDefinition typeDef, CodegenSession session - , System.Type[] excludedBaseTypes = null, string[] excludedAssemblyPrefixes = null) - { - - GeneralHelper gh = session.GetClass(); - while (typeDef != null) - { - if (IsExcluded(typeDef, excludedBaseTypes, excludedAssemblyPrefixes)) - break; - - foreach (FieldDefinition fd in typeDef.Fields) - { - if (fd.IsStatic) - continue; - if (fd.IsNotSerialized) - continue; - if (gh.CodegenExclude(fd)) - continue; - if (fd.IsPrivate) - continue; - - yield return fd; - } - - try { typeDef = typeDef.BaseType?.CachedResolve(session); } - catch { break; } - } - } - - /// - /// Finds public properties on typeDef and all base types which have a public get/set accessor. - /// - /// - /// - public static IEnumerable FindAllPublicProperties(this TypeDefinition typeDef, CodegenSession session - , System.Type[] excludedBaseTypes = null, string[] excludedAssemblyPrefixes = null) - { - GeneralHelper gh = session.GetClass(); - while (typeDef != null) - { - if (IsExcluded(typeDef, excludedBaseTypes, excludedAssemblyPrefixes)) - break; - - foreach (PropertyDefinition pd in typeDef.Properties) - { - //Missing get or set method. - if (pd.GetMethod == null || pd.SetMethod == null) - continue; - if (gh.CodegenExclude(pd)) - continue; - if (pd.GetMethod.IsPrivate) - continue; - if (pd.SetMethod.IsPrivate) - continue; - if (pd.GetMethod.ReturnType.IsGenericParameter) - continue; - - yield return pd; - } - - try { typeDef = typeDef.BaseType?.CachedResolve(session); } - catch { break; } - } - } - - /// - /// Returns if typeDef is excluded. - /// - private static bool IsExcluded(TypeDefinition typeDef, System.Type[] excludedBaseTypes = null, string[] excludedAssemblyPrefixes = null) - { - if (excludedBaseTypes != null) - { - foreach (System.Type t in excludedBaseTypes) - { - if (typeDef.FullName == t.FullName) - return true; - } - } - if (excludedAssemblyPrefixes != null) - { - foreach (string s in excludedAssemblyPrefixes) - { - int len = s.Length; - string tdAsmName = typeDef.Module.Assembly.FullName; - if (tdAsmName.Length >= len && tdAsmName.Substring(0, len).ToLower() == s.ToLower()) - return true; - } - } - - //Fall through, not excluded. - return false; - } - - - /// - /// Returns if typeDef is excluded. - /// - public static bool IsExcluded(this TypeDefinition typeDef, string excludedAssemblyPrefix) - { - - int len = excludedAssemblyPrefix.Length; - string tdAsmName = typeDef.Module.Assembly.FullName; - if (tdAsmName.Length >= len && tdAsmName.Substring(0, len).ToLower() == excludedAssemblyPrefix.ToLower()) - return true; - - //Fall through, not excluded. - return false; - } - - /// - /// Returns if typeDef or any of it's parents inherit from NetworkBehaviour. - /// - /// - /// - internal static bool InheritsNetworkBehaviour(this TypeDefinition typeDef, CodegenSession session) - { - string nbFullName = session.GetClass().FullName; - - TypeDefinition copyTd = typeDef; - while (copyTd != null) - { - if (copyTd.FullName == nbFullName) - return true; - - copyTd = copyTd.GetNextBaseTypeDefinition(session); - } - - //Fall through, network behaviour not found. - return false; - } - - /// - /// Returns a nested TypeDefinition of name. - /// - internal static TypeDefinition GetNestedType(this TypeDefinition typeDef, string name) - { - foreach (TypeDefinition nestedTd in typeDef.NestedTypes) - { - if (nestedTd.Name == name) - return nestedTd; - } - - return null; - } - - /// - /// Returns if the BaseType for TypeDef exist and is not NetworkBehaviour, - /// - /// - /// - internal static bool CanProcessBaseType(this TypeDefinition typeDef, CodegenSession session) - { - return (typeDef != null && typeDef.BaseType != null && typeDef.BaseType.FullName != session.GetClass().FullName); - } - /// - /// Returns if the BaseType for TypeDef exist and is not NetworkBehaviour, - /// - /// - /// - internal static TypeDefinition GetNextBaseClassToProcess(this TypeDefinition typeDef, CodegenSession session) - { - if (typeDef.BaseType != null && typeDef.BaseType.FullName != session.GetClass().FullName) - return typeDef.BaseType.CachedResolve(session); - else - return null; - } - - internal static TypeDefinition GetLastBaseClass(this TypeDefinition typeDef, CodegenSession session) - { - TypeDefinition copyTd = typeDef; - while (copyTd.BaseType != null) - copyTd = copyTd.BaseType.CachedResolve(session); - - return copyTd; - } - - /// - /// Searches for a type in current and inherited types. - /// - internal static TypeDefinition GetClassInInheritance(this TypeDefinition typeDef, CodegenSession session, string typeFullName) - { - TypeDefinition copyTd = typeDef; - do - { - if (copyTd.FullName == typeFullName) - return copyTd; - - if (copyTd.BaseType != null) - copyTd = copyTd.BaseType.CachedResolve(session); - else - copyTd = null; - - } while (copyTd != null); - - //Not found. - return null; - } - - /// - /// Searches for a type in current and inherited types. - /// - internal static TypeDefinition GetClassInInheritance(this TypeDefinition typeDef, CodegenSession session, TypeDefinition targetTypeDef) - { - if (typeDef == null) - return null; - - TypeDefinition copyTd = typeDef; - do - { - if (copyTd == targetTypeDef) - return copyTd; - - if (copyTd.BaseType != null) - copyTd = copyTd.BaseType.CachedResolve(session); - else - copyTd = null; - - } while (copyTd != null); - - //Not found. - return null; - } - - - - /// - /// Returns if typeDef is static (abstract, sealed). - /// - internal static bool IsStatic(this TypeDefinition typeDef) - { - //Combining flags in a single check some reason doesn't work right with HasFlag. - return (typeDef.Attributes.HasFlag(TypeAttributes.Abstract) && typeDef.Attributes.HasFlag(TypeAttributes.Sealed)); - } - - /// - /// Gets an enum underlying type for typeDef. - /// - /// - /// - internal static TypeReference GetEnumUnderlyingTypeReference(this TypeDefinition typeDef) - { - foreach (FieldDefinition field in typeDef.Fields) - { - if (!field.IsStatic) - return field.FieldType; - } - throw new ArgumentException($"Invalid enum {typeDef.FullName}"); - } - - /// - /// Returns if typeDef is derived from type. - /// - /// - /// - /// - internal static bool InheritsFrom(this TypeDefinition typeDef, CodegenSession session) - { - return typeDef.InheritsFrom(session, typeof(T)); - } - - /// - /// Returns if typeDef is derived from type. - /// - /// - /// - /// - internal static bool InheritsFrom(this TypeDefinition typeDef, CodegenSession session, Type type) - { - if (!typeDef.IsClass) - return false; - - TypeDefinition copyTd = typeDef; - while (copyTd.BaseType != null) - { - if (copyTd.BaseType.IsType(type)) - return true; - - copyTd = copyTd.GetNextBaseTypeDefinition(session); - } - - //Fall through. - return false; - } - - /// - /// Adds a method to typeDef. - /// - /// - /// - /// - /// - internal static MethodDefinition AddMethod(this TypeDefinition typDef, string methodName, MethodAttributes attributes) - { - return AddMethod(typDef, methodName, attributes, typDef.Module.ImportReference(typeof(void))); - } - /// - /// Adds a method to typeDef. - /// - /// - /// - /// - /// - /// - internal static MethodDefinition AddMethod(this TypeDefinition typeDef, string methodName, MethodAttributes attributes, TypeReference typeReference) - { - var method = new MethodDefinition(methodName, attributes, typeReference); - typeDef.Methods.Add(method); - return method; - } - - - /// - /// Finds the first method by a given name. - /// - /// - /// - /// - internal static MethodDefinition GetMethod(this TypeDefinition typeDef, string methodName) - { - return typeDef.Methods.FirstOrDefault(method => method.Name == methodName); - } - - /// - /// Finds the first method by a given name. - /// - /// - /// - /// - internal static MethodDefinition GetMethod(this TypeDefinition typeDef, string methodName, Type[] types) - { - throw new NotImplementedException(); - } - - /// - /// Returns if a type is a subclass of another. - /// - /// - /// - /// - internal static bool IsSubclassOf(this TypeDefinition typeDef,CodegenSession session, string ClassTypeFullName) - { - if (!typeDef.IsClass) return false; - - TypeReference baseTypeRef = typeDef.BaseType; - while (baseTypeRef != null) - { - if (baseTypeRef.FullName == ClassTypeFullName) - { - return true; - } - - try - { - baseTypeRef = baseTypeRef.CachedResolve(session).BaseType; - } - catch - { - return false; - } - } - - return false; - } - - /// - /// Gets a field reference by name. - /// - /// - /// - /// - public static FieldReference GetFieldReference(this TypeDefinition typeDef, string fieldName, CodegenSession session) - { - if (typeDef.HasFields) - { - for (int i = 0; i < typeDef.Fields.Count; i++) - { - if (typeDef.Fields[i].Name == fieldName) - return session.ImportReference(typeDef.Fields[i]); - } - } - - return null; - } - - - /// - /// Returns if the TypeDefinition implements TInterface. - /// - /// - /// - /// - public static bool ImplementsInterface(this TypeDefinition typeDef) - { - for (int i = 0; i < typeDef.Interfaces.Count; i++) - { - if (typeDef.Interfaces[i].InterfaceType.Is()) - return true; - } - - return false; - } - - /// - /// Returns if the TypeDefinition implements TInterface. - /// - /// - /// - /// - public static bool ImplementsInterface(this TypeDefinition typeDef, string interfaceName) - { - for (int i = 0; i < typeDef.Interfaces.Count; i++) - { - if (typeDef.Interfaces[i].InterfaceType.FullName == interfaceName) - return true; - } - - return false; - } - - - - - /// - /// Returns if the TypeDefinition implements TInterface. - /// - /// - /// - /// - public static bool ImplementsInterfaceRecursive(this TypeDefinition typeDef, CodegenSession session) - { - TypeDefinition climbTypeDef = typeDef; - - while (climbTypeDef != null) - { - if (climbTypeDef.Interfaces.Any(i => i.InterfaceType.Is())) - return true; - - try - { - if (climbTypeDef.BaseType != null) - climbTypeDef = climbTypeDef.BaseType.CachedResolve(session); - else - climbTypeDef = null; - } - //Could not resolve assembly; can happen for assemblies being checked outside FishNet/csharp. - catch (AssemblyResolutionException) - { - break; - } - } - - return false; - } - - /// - /// Returns if the TypeDefinition implements TInterface. - /// - /// - /// - /// - public static bool ImplementsInterfaceRecursive(this TypeDefinition typeDef, CodegenSession session, string interfaceName) - { - TypeDefinition climbTypeDef = typeDef; - - while (climbTypeDef != null) - { - if (climbTypeDef.Interfaces.Any(i => i.InterfaceType.FullName == interfaceName)) - return true; - - try - { - if (climbTypeDef.BaseType != null) - climbTypeDef = climbTypeDef.BaseType.CachedResolve(session); - else - climbTypeDef = null; - } - //Could not resolve assembly; can happen for assemblies being checked outside FishNet/csharp. - catch (AssemblyResolutionException) - { - break; - } - } - - return false; - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/TypeDefinitionExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/TypeDefinitionExtensions.cs.meta deleted file mode 100644 index da8687a..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/TypeDefinitionExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 645e49fe7eeff3a4e9eb65d77fc6e2ca -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/TypeReferenceExtensions.cs b/Assets/FishNet/CodeGenerating/Helpers/Extension/TypeReferenceExtensions.cs deleted file mode 100644 index 6b4112e..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/TypeReferenceExtensions.cs +++ /dev/null @@ -1,138 +0,0 @@ -using MonoFN.Cecil; -using MonoFN.Cecil.Rocks; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.CodeGenerating.Helping.Extension -{ - - internal static class TypeReferenceExtensionsOld - { - - /// - /// Gets a Resolve favoring cached results first. - /// - internal static TypeDefinition CachedResolve(this TypeReference typeRef, CodegenSession session) - { - return session.GetClass().GetTypeReferenceResolve(typeRef); - } - - /// - /// Returns if typeRef is a class or struct. - /// - internal static bool IsClassOrStruct(this TypeReference typeRef, CodegenSession session) - { - TypeDefinition typeDef = typeRef.CachedResolve(session); - return (!typeDef.IsPrimitive && !typeDef.IsEnum && (typeDef.IsClass || typeDef.IsValueType)); - } - - /// - /// Returns all properties on typeRef and all base types which have a public get/set accessor. - /// - /// - /// - public static IEnumerable FindAllSerializableProperties(this TypeReference typeRef, CodegenSession session, System.Type[] excludedBaseTypes = null, string[] excludedAssemblyPrefixes = null) - { - return typeRef.CachedResolve(session).FindAllPublicProperties(session, excludedBaseTypes, excludedAssemblyPrefixes); - } - - - /// - /// Gets all public fields in typeRef and base type. - /// - /// - /// - public static IEnumerable FindAllSerializableFields(this TypeReference typeRef, CodegenSession session, - System.Type[] excludedBaseTypes = null, string[] excludedAssemblyPrefixes = null) - { - return typeRef.Resolve().FindAllPublicFields(session, excludedBaseTypes, excludedAssemblyPrefixes); - } - - - /// - /// Returns if a typeRef is type. - /// - /// - /// - /// - public static bool IsType(this TypeReference typeRef, Type type) - { - if (type.IsGenericType) - return typeRef.GetElementType().FullName == type.FullName; - else - return typeRef.FullName == type.FullName; - } - - - - /// - /// Returns if typeRef is a multidimensional array. - /// - /// - /// - public static bool IsMultidimensionalArray(this TypeReference typeRef) - { - return typeRef is ArrayType arrayType && arrayType.Rank > 1; - } - - - /// - /// Returns if typeRef can be resolved. - /// - /// - /// - public static bool CanBeResolved(this TypeReference typeRef, CodegenSession session) - { - while (typeRef != null) - { - if (typeRef.Scope.Name == "Windows") - { - return false; - } - - if (typeRef.Scope.Name == "mscorlib") - { - TypeDefinition resolved = typeRef.CachedResolve(session); - return resolved != null; - } - - try - { - typeRef = typeRef.CachedResolve(session).BaseType; - } - catch - { - return false; - } - } - return true; - } - - /// - /// Creates a generic type out of another type, if needed. - /// - /// - /// - public static TypeReference ConvertToGenericIfNeeded(this TypeDefinition type) - { - if (type.HasGenericParameters) - { - // get all the generic parameters and make a generic instance out of it - TypeReference[] genericTypes = new TypeReference[type.GenericParameters.Count]; - for (int i = 0; i < type.GenericParameters.Count; i++) - { - genericTypes[i] = type.GenericParameters[i].GetElementType(); - } - - return type.MakeGenericInstanceType(genericTypes); - } - else - { - return type; - } - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Extension/TypeReferenceExtensions.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Extension/TypeReferenceExtensions.cs.meta deleted file mode 100644 index 5edaeb9..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Extension/TypeReferenceExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2344f5ab0fda07b498c03fbe0e082c14 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/GeneralHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/GeneralHelper.cs deleted file mode 100644 index 6e18a9e..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/GeneralHelper.cs +++ /dev/null @@ -1,1412 +0,0 @@ -using FishNet.CodeGenerating.Extension; -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.CodeGenerating.ILCore; -using FishNet.Managing; -using FishNet.Managing.Logging; -using FishNet.Object; -using FishNet.Object.Helping; -using FishNet.Serializing; -using FishNet.Serializing.Helping; -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using MonoFN.Cecil.Rocks; -using System; -using System.Collections.Generic; -using UnityEngine; -using SR = System.Reflection; - -namespace FishNet.CodeGenerating.Helping -{ - internal class GeneralHelper : CodegenBase - { - #region Reflection references. - public string CodegenExcludeAttribute_FullName; - public string CodegenIncludeAttribute_FullName; - public MethodReference Extension_Attribute_Ctor_MethodRef; - public MethodReference Queue_Enqueue_MethodRef; - public MethodReference Queue_get_Count_MethodRef; - public MethodReference Queue_Dequeue_MethodRef; - public MethodReference Queue_Clear_MethodRef; - public TypeReference List_TypeRef; - public MethodReference List_Clear_MethodRef; - public MethodReference List_get_Item_MethodRef; - public MethodReference List_get_Count_MethodRef; - public MethodReference List_Add_MethodRef; - public MethodReference List_RemoveRange_MethodRef; - public MethodReference InstanceFinder_NetworkManager_MethodRef; - public MethodReference NetworkBehaviour_CanLog_MethodRef; - public MethodReference NetworkBehaviour_NetworkManager_MethodRef; - public MethodReference NetworkManager_LogCommon_MethodRef; - public MethodReference NetworkManager_LogWarning_MethodRef; - public MethodReference NetworkManager_LogError_MethodRef; - public MethodReference Debug_LogCommon_MethodRef; - public MethodReference Debug_LogWarning_MethodRef; - public MethodReference Debug_LogError_MethodRef; - public MethodReference IsServer_MethodRef; - public MethodReference IsClient_MethodRef; - public MethodReference NetworkObject_Deinitializing_MethodRef; - public MethodReference Application_IsPlaying_MethodRef; - public string NonSerialized_Attribute_FullName; - public string Single_FullName; - public TypeReference FunctionT2TypeRef; - public TypeReference FunctionT3TypeRef; - public MethodReference FunctionT2ConstructorMethodRef; - public MethodReference FunctionT3ConstructorMethodRef; - //GeneratedComparer - public MethodReference GeneratedComparer_Compare_Set_MethodRef; - public MethodReference GeneratedComparer_IsDefault_Set_MethodRef; - public TypeReference GeneratedComparer_TypeRef; - public TypeDefinition GeneratedComparer_ClassTypeDef; - public MethodDefinition GeneratedComparer_OnLoadMethodDef; - public TypeReference IEquatable_TypeRef; - //Actions. - public TypeReference ActionT2_TypeRef; - public TypeReference ActionT3_TypeRef; - public MethodReference ActionT2Constructor_MethodRef; - public MethodReference ActionT3Constructor_MethodRef; - - private Dictionary _importedTypeReferences = new Dictionary(); - private Dictionary _importedFieldReferences = new Dictionary(); - private Dictionary _methodReferenceResolves = new Dictionary(); - private Dictionary _typeReferenceResolves = new Dictionary(); - private Dictionary _fieldReferenceResolves = new Dictionary(); - private Dictionary _comparerDelegates = new Dictionary(); - #endregion - - #region Const. - public const string UNITYENGINE_ASSEMBLY_PREFIX = "UnityEngine."; - #endregion - - public override bool ImportReferences() - { - Type tmpType; - TypeReference tmpTr; - SR.MethodInfo tmpMi; - SR.PropertyInfo tmpPi; - - NonSerialized_Attribute_FullName = typeof(NonSerializedAttribute).FullName; - Single_FullName = typeof(float).FullName; - - ActionT2_TypeRef = base.ImportReference(typeof(Action<,>)); - ActionT3_TypeRef = base.ImportReference(typeof(Action<,,>)); - ActionT2Constructor_MethodRef = base.ImportReference(typeof(Action<,>).GetConstructors()[0]); - ActionT3Constructor_MethodRef = base.ImportReference(typeof(Action<,,>).GetConstructors()[0]); - - CodegenExcludeAttribute_FullName = typeof(CodegenExcludeAttribute).FullName; - CodegenIncludeAttribute_FullName = typeof(CodegenIncludeAttribute).FullName; - - tmpType = typeof(Queue<>); - base.ImportReference(tmpType); - tmpMi = tmpType.GetMethod("get_Count"); - Queue_get_Count_MethodRef = base.ImportReference(tmpMi); - foreach (SR.MethodInfo mi in tmpType.GetMethods()) - { - if (mi.Name == nameof(Queue.Enqueue)) - Queue_Enqueue_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(Queue.Dequeue)) - Queue_Dequeue_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(Queue.Clear)) - Queue_Clear_MethodRef = base.ImportReference(mi); - } - - /* MISC */ - // - tmpType = typeof(UnityEngine.Application); - tmpPi = tmpType.GetProperty(nameof(UnityEngine.Application.isPlaying)); - if (tmpPi != null) - Application_IsPlaying_MethodRef = base.ImportReference(tmpPi.GetMethod); - // - tmpType = typeof(System.Runtime.CompilerServices.ExtensionAttribute); - tmpTr = base.ImportReference(tmpType); - Extension_Attribute_Ctor_MethodRef = base.ImportReference(tmpTr.GetConstructor(base.Session)); - - //Networkbehaviour. - Type networkBehaviourType = typeof(NetworkBehaviour); - foreach (SR.MethodInfo methodInfo in networkBehaviourType.GetMethods()) - { - if (methodInfo.Name == nameof(NetworkBehaviour.CanLog)) - NetworkBehaviour_CanLog_MethodRef = base.ImportReference(methodInfo); - } - foreach (SR.PropertyInfo propertyInfo in networkBehaviourType.GetProperties()) - { - if (propertyInfo.Name == nameof(NetworkBehaviour.NetworkManager)) - NetworkBehaviour_NetworkManager_MethodRef = base.ImportReference(propertyInfo.GetMethod); - } - - //Instancefinder. - Type instanceFinderType = typeof(InstanceFinder); - SR.PropertyInfo getNetworkManagerPropertyInfo = instanceFinderType.GetProperty(nameof(InstanceFinder.NetworkManager)); - InstanceFinder_NetworkManager_MethodRef = base.ImportReference(getNetworkManagerPropertyInfo.GetMethod); - - //NetworkManager debug logs. - Type networkManagerType = typeof(NetworkManager); - foreach (SR.MethodInfo methodInfo in networkManagerType.GetMethods()) - { - if (methodInfo.Name == nameof(NetworkManager.Log) && methodInfo.GetParameters().Length == 1) - NetworkManager_LogCommon_MethodRef = base.ImportReference(methodInfo); - else if (methodInfo.Name == nameof(NetworkManager.LogWarning)) - NetworkManager_LogWarning_MethodRef = base.ImportReference(methodInfo); - else if (methodInfo.Name == nameof(NetworkManager.LogError)) - NetworkManager_LogError_MethodRef = base.ImportReference(methodInfo); - } - - //Lists. - tmpType = typeof(List<>); - List_TypeRef = base.ImportReference(tmpType); - SR.MethodInfo lstMi; - lstMi = tmpType.GetMethod("Add"); - List_Add_MethodRef = base.ImportReference(lstMi); - lstMi = tmpType.GetMethod("RemoveRange"); - List_RemoveRange_MethodRef = base.ImportReference(lstMi); - lstMi = tmpType.GetMethod("get_Count"); - List_get_Count_MethodRef = base.ImportReference(lstMi); - lstMi = tmpType.GetMethod("get_Item"); - List_get_Item_MethodRef = base.ImportReference(lstMi); - lstMi = tmpType.GetMethod("Clear"); - List_Clear_MethodRef = base.ImportReference(lstMi); - - //Unity debug logs. - Type debugType = typeof(UnityEngine.Debug); - foreach (SR.MethodInfo methodInfo in debugType.GetMethods()) - { - if (methodInfo.Name == nameof(Debug.LogWarning) && methodInfo.GetParameters().Length == 1) - Debug_LogWarning_MethodRef = base.ImportReference(methodInfo); - else if (methodInfo.Name == nameof(Debug.LogError) && methodInfo.GetParameters().Length == 1) - Debug_LogError_MethodRef = base.ImportReference(methodInfo); - else if (methodInfo.Name == nameof(Debug.Log) && methodInfo.GetParameters().Length == 1) - Debug_LogCommon_MethodRef = base.ImportReference(methodInfo); - } - - Type codegenHelper = typeof(CodegenHelper); - foreach (SR.MethodInfo methodInfo in codegenHelper.GetMethods()) - { - if (methodInfo.Name == nameof(CodegenHelper.NetworkObject_Deinitializing)) - NetworkObject_Deinitializing_MethodRef = base.ImportReference(methodInfo); - else if (methodInfo.Name == nameof(CodegenHelper.IsClient)) - IsClient_MethodRef = base.ImportReference(methodInfo); - else if (methodInfo.Name == nameof(CodegenHelper.IsServer)) - IsServer_MethodRef = base.ImportReference(methodInfo); - } - - //Generic functions. - FunctionT2TypeRef = base.ImportReference(typeof(Func<,>)); - FunctionT3TypeRef = base.ImportReference(typeof(Func<,,>)); - FunctionT2ConstructorMethodRef = base.ImportReference(typeof(Func<,>).GetConstructors()[0]); - FunctionT3ConstructorMethodRef = base.ImportReference(typeof(Func<,,>).GetConstructors()[0]); - - GeneratedComparers(); - - //Sets up for generated comparers. - void GeneratedComparers() - { - GeneralHelper gh = base.GetClass(); - GeneratedComparer_ClassTypeDef = gh.GetOrCreateClass(out _, WriterProcessor.GENERATED_TYPE_ATTRIBUTES, "GeneratedComparers___Internal", null, WriterProcessor.GENERATED_WRITER_NAMESPACE); - bool created; - GeneratedComparer_OnLoadMethodDef = gh.GetOrCreateMethod(GeneratedComparer_ClassTypeDef, out created, WriterProcessor.INITIALIZEONCE_METHOD_ATTRIBUTES, WriterProcessor.INITIALIZEONCE_METHOD_NAME, base.Module.TypeSystem.Void); - if (created) - { - gh.CreateRuntimeInitializeOnLoadMethodAttribute(GeneratedComparer_OnLoadMethodDef); - GeneratedComparer_OnLoadMethodDef.Body.GetILProcessor().Emit(OpCodes.Ret); - } - - System.Type repComparerType = typeof(GeneratedComparer<>); - GeneratedComparer_TypeRef = base.ImportReference(repComparerType); - System.Reflection.PropertyInfo pi; - pi = repComparerType.GetProperty(nameof(GeneratedComparer.Compare)); - GeneratedComparer_Compare_Set_MethodRef = base.ImportReference(pi.GetSetMethod()); - pi = repComparerType.GetProperty(nameof(GeneratedComparer.IsDefault)); - GeneratedComparer_IsDefault_Set_MethodRef = base.ImportReference(pi.GetSetMethod()); - - System.Type iEquatableType = typeof(IEquatable<>); - IEquatable_TypeRef = base.ImportReference(iEquatableType); - } - - return true; - } - - - - #region Resolves. - /// - /// Adds a typeRef to TypeReferenceResolves. - /// - public void AddTypeReferenceResolve(TypeReference typeRef, TypeDefinition typeDef) - { - _typeReferenceResolves[typeRef] = typeDef; - } - - /// - /// Gets a TypeDefinition for typeRef. - /// - public TypeDefinition GetTypeReferenceResolve(TypeReference typeRef) - { - TypeDefinition result; - if (_typeReferenceResolves.TryGetValue(typeRef, out result)) - { - return result; - } - else - { - result = typeRef.Resolve(); - AddTypeReferenceResolve(typeRef, result); - } - - return result; - } - - /// - /// Adds a methodRef to MethodReferenceResolves. - /// - public void AddMethodReferenceResolve(MethodReference methodRef, MethodDefinition methodDef) - { - _methodReferenceResolves[methodRef] = methodDef; - } - - /// - /// Gets a TypeDefinition for typeRef. - /// - public MethodDefinition GetMethodReferenceResolve(MethodReference methodRef) - { - MethodDefinition result; - if (_methodReferenceResolves.TryGetValue(methodRef, out result)) - { - return result; - } - else - { - result = methodRef.Resolve(); - AddMethodReferenceResolve(methodRef, result); - } - - return result; - } - - - /// - /// Adds a fieldRef to FieldReferenceResolves. - /// - public void AddFieldReferenceResolve(FieldReference fieldRef, FieldDefinition fieldDef) - { - _fieldReferenceResolves[fieldRef] = fieldDef; - } - - /// - /// Gets a FieldDefinition for fieldRef. - /// - public FieldDefinition GetFieldReferenceResolve(FieldReference fieldRef) - { - FieldDefinition result; - if (_fieldReferenceResolves.TryGetValue(fieldRef, out result)) - { - return result; - } - else - { - result = fieldRef.Resolve(); - AddFieldReferenceResolve(fieldRef, result); - } - - return result; - } - #endregion - - - /// - /// Makes a method an extension method. - /// - public void MakeExtensionMethod(MethodDefinition md) - { - if (md.Parameters.Count == 0) - { - base.LogError($"Method {md.FullName} cannot be made an extension method because it has no parameters."); - return; - } - - md.Attributes |= (MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig); - CustomAttribute ca = new CustomAttribute(Extension_Attribute_Ctor_MethodRef); - md.CustomAttributes.Add(ca); - } - - /// - /// Returns if typeDef should be ignored. - /// - /// - /// - public bool IgnoreTypeDefinition(TypeDefinition typeDef) - { - foreach (CustomAttribute item in typeDef.CustomAttributes) - { - if (item.AttributeType.FullName == typeof(CodegenExcludeAttribute).FullName) - return true; - } - - return false; - } - - /// - /// Returns if type uses CodegenExcludeAttribute. - /// - public bool CodegenExclude(SR.MethodInfo methodInfo) - { - foreach (SR.CustomAttributeData item in methodInfo.CustomAttributes) - { - if (item.AttributeType == typeof(CodegenExcludeAttribute)) - return true; - } - - return false; - } - - /// - /// Returns if type uses CodegenExcludeAttribute. - /// - public bool CodegenExclude(MethodDefinition methodDef) - { - foreach (CustomAttribute item in methodDef.CustomAttributes) - { - if (item.AttributeType.FullName == CodegenExcludeAttribute_FullName) - return true; - } - - return false; - } - - /// - /// Returns if type uses CodegenExcludeAttribute. - /// - public bool CodegenExclude(FieldDefinition fieldDef) - { - foreach (CustomAttribute item in fieldDef.CustomAttributes) - { - if (item.AttributeType.FullName == CodegenExcludeAttribute_FullName) - return true; - } - - return false; - } - - /// - /// Returns if type uses CodegenIncludeAttribute. - /// - public bool CodegenInclude(FieldDefinition fieldDef) - { - foreach (CustomAttribute item in fieldDef.CustomAttributes) - { - if (item.AttributeType.FullName == CodegenIncludeAttribute_FullName) - return true; - } - - return false; - } - - /// - /// Returns if type uses CodegenExcludeAttribute. - /// - public bool CodegenExclude(PropertyDefinition propDef) - { - foreach (CustomAttribute item in propDef.CustomAttributes) - { - if (item.AttributeType.FullName == CodegenExcludeAttribute_FullName) - return true; - } - - return false; - } - - - /// - /// Returns if type uses CodegenExcludeAttribute. - /// - public bool CodegenInclude(PropertyDefinition propDef) - { - foreach (CustomAttribute item in propDef.CustomAttributes) - { - if (item.AttributeType.FullName == CodegenIncludeAttribute_FullName) - return true; - } - - return false; - } - - - - - /// - /// Calls copiedMd with the assumption md shares the same parameters. - /// - public void CallCopiedMethod(MethodDefinition md, MethodDefinition copiedMd) - { - ILProcessor processor = md.Body.GetILProcessor(); - processor.Emit(OpCodes.Ldarg_0); - foreach (var item in copiedMd.Parameters) - processor.Emit(OpCodes.Ldarg, item); - - MethodReference mr = copiedMd.GetMethodReference(base.Session); - processor.Emit(OpCodes.Call, mr); - - } - - /// - /// Removes countVd from list of dataFd starting at index 0. - /// - public List ListRemoveRange(MethodDefinition methodDef, FieldDefinition dataFd, TypeReference dataTr, VariableDefinition countVd) - { - /* Remove entries which exceed maximum buffer. */ - //Method references for uint/data list: - //get_count, RemoveRange. */ - GenericInstanceType dataListGit; - GetGenericLists(dataTr, out dataListGit); - MethodReference lstDataRemoveRangeMr = base.GetClass().List_RemoveRange_MethodRef.MakeHostInstanceGeneric(base.Session, dataListGit); - - List insts = new List(); - ILProcessor processor = methodDef.Body.GetILProcessor(); - - //Index 1 is the uint, 0 is the data. - insts.Add(processor.Create(OpCodes.Ldarg_0));//this. - insts.Add(processor.Create(OpCodes.Ldfld, dataFd)); - insts.Add(processor.Create(OpCodes.Ldc_I4_0)); - insts.Add(processor.Create(OpCodes.Ldloc, countVd)); - insts.Add(processor.Create(lstDataRemoveRangeMr.GetCallOpCode(base.Session), lstDataRemoveRangeMr)); - - return insts; - } - /// - /// Outputs generic lists for dataTr and uint. - /// - public void GetGenericLists(TypeReference dataTr, out GenericInstanceType lstData) - { - TypeReference listDataTr = base.ImportReference(typeof(List<>)); - lstData = listDataTr.MakeGenericInstanceType(new TypeReference[] { dataTr }); - } - /// - /// Outputs generic lists for dataTr and uint. - /// - public void GetGenericQueues(TypeReference dataTr, out GenericInstanceType queueData) - { - TypeReference queueDataTr = base.ImportReference(typeof(Queue<>)); - queueData = queueDataTr.MakeGenericInstanceType(new TypeReference[] { dataTr }); - } - - /// - /// Copies one method to another while transferring diagnostic paths. - /// - public MethodDefinition CopyIntoNewMethod(MethodDefinition originalMd, string toMethodName, out bool alreadyCreated) - { - TypeDefinition typeDef = originalMd.DeclaringType; - - MethodDefinition md = typeDef.GetOrCreateMethodDefinition(base.Session, toMethodName, originalMd, true, out bool created); - alreadyCreated = !created; - if (alreadyCreated) - return md; - - (md.Body, originalMd.Body) = (originalMd.Body, md.Body); - //Move over all the debugging information - foreach (SequencePoint sequencePoint in originalMd.DebugInformation.SequencePoints) - md.DebugInformation.SequencePoints.Add(sequencePoint); - originalMd.DebugInformation.SequencePoints.Clear(); - - foreach (CustomDebugInformation customInfo in originalMd.CustomDebugInformations) - md.CustomDebugInformations.Add(customInfo); - originalMd.CustomDebugInformations.Clear(); - //Swap debuginformation scope. - (originalMd.DebugInformation.Scope, md.DebugInformation.Scope) = (md.DebugInformation.Scope, originalMd.DebugInformation.Scope); - - return md; - } - - /// - /// Creates the RuntimeInitializeOnLoadMethod attribute for a method. - /// - public void CreateRuntimeInitializeOnLoadMethodAttribute(MethodDefinition methodDef, string loadType = "") - { - TypeReference attTypeRef = GetTypeReference(typeof(RuntimeInitializeOnLoadMethodAttribute)); - foreach (CustomAttribute item in methodDef.CustomAttributes) - { - //Already exist. - if (item.AttributeType.FullName == attTypeRef.FullName) - return; - } - - int parameterRequirement = (loadType.Length == 0) ? 0 : 1; - MethodDefinition constructorMethodDef = attTypeRef.GetConstructor(base.Session, parameterRequirement); - MethodReference constructorMethodRef = base.ImportReference(constructorMethodDef); - CustomAttribute ca = new CustomAttribute(constructorMethodRef); - /* If load type isn't null then it - * has to be passed in as the first argument. */ - if (loadType.Length > 0) - { - Type t = typeof(RuntimeInitializeLoadType); - foreach (UnityEngine.RuntimeInitializeLoadType value in t.GetEnumValues()) - { - if (loadType == value.ToString()) - { - TypeReference tr = base.ImportReference(t); - CustomAttributeArgument arg = new CustomAttributeArgument(tr, value); - ca.ConstructorArguments.Add(arg); - } - } - } - - methodDef.CustomAttributes.Add(ca); - } - - /// - /// Gets the default AutoPackType to use for typeRef. - /// - /// - /// - public AutoPackType GetDefaultAutoPackType(TypeReference typeRef) - { - //Singles are defauled to unpacked. - if (typeRef.FullName == Single_FullName) - return AutoPackType.Unpacked; - else - return AutoPackType.Packed; - } - - /// - /// Gets the InitializeOnce method in typeDef or creates the method should it not exist. - /// - /// - /// - public MethodDefinition GetOrCreateMethod(TypeDefinition typeDef, out bool created, MethodAttributes methodAttr, string methodName, TypeReference returnType) - { - MethodDefinition result = typeDef.GetMethod(methodName); - if (result == null) - { - created = true; - result = new MethodDefinition(methodName, methodAttr, returnType); - typeDef.Methods.Add(result); - } - else - { - created = false; - } - - return result; - } - - - /// - /// Gets a class within moduleDef or creates and returns the class if it does not already exist. - /// - /// - /// - public TypeDefinition GetOrCreateClass(out bool created, TypeAttributes typeAttr, string className, TypeReference baseTypeRef, string namespaceName = WriterProcessor.GENERATED_WRITER_NAMESPACE) - { - if (namespaceName.Length == 0) - namespaceName = FishNetILPP.RUNTIME_ASSEMBLY_NAME; - - TypeDefinition type = base.Module.GetClass(className, namespaceName); - if (type != null) - { - created = false; - return type; - } - else - { - created = true; - type = new TypeDefinition(namespaceName, className, - typeAttr, base.ImportReference(typeof(object))); - //Add base class if specified. - if (baseTypeRef != null) - type.BaseType = base.ImportReference(baseTypeRef); - - base.Module.Types.Add(type); - return type; - } - } - - #region HasNonSerializableAttribute - /// - /// Returns if fieldDef has a NonSerialized attribute. - /// - /// - /// - public bool HasNonSerializableAttribute(FieldDefinition fieldDef) - { - foreach (CustomAttribute customAttribute in fieldDef.CustomAttributes) - { - if (customAttribute.AttributeType.FullName == NonSerialized_Attribute_FullName) - return true; - } - - //Fall through, no matches. - return false; - } - /// - /// Returns if typeDef has a NonSerialized attribute. - /// - /// - /// - public bool HasNonSerializableAttribute(TypeDefinition typeDef) - { - foreach (CustomAttribute customAttribute in typeDef.CustomAttributes) - { - if (customAttribute.AttributeType.FullName == NonSerialized_Attribute_FullName) - return true; - } - - //Fall through, no matches. - return false; - } - #endregion - - /// - /// Gets a TypeReference for a type. - /// - /// - public TypeReference GetTypeReference(Type type) - { - TypeReference result; - if (!_importedTypeReferences.TryGetValue(type, out result)) - { - result = base.ImportReference(type); - _importedTypeReferences.Add(type, result); - } - - return result; - } - - /// - /// Gets a FieldReference for a type. - /// - /// - public FieldReference GetFieldReference(FieldDefinition fieldDef) - { - FieldReference result; - if (!_importedFieldReferences.TryGetValue(fieldDef, out result)) - { - result = base.ImportReference(fieldDef); - _importedFieldReferences.Add(fieldDef, result); - } - - return result; - } - - /// - /// Gets the current constructor for typeDef, or makes a new one if constructor doesn't exist. - /// - /// - /// - public MethodDefinition GetOrCreateConstructor(TypeDefinition typeDef, out bool created, bool makeStatic) - { - // find constructor - MethodDefinition constructorMethodDef = typeDef.GetMethod(".cctor"); - if (constructorMethodDef == null) - constructorMethodDef = typeDef.GetMethod(".ctor"); - - //Constructor already exist. - if (constructorMethodDef != null) - { - if (!makeStatic) - constructorMethodDef.Attributes &= ~MethodAttributes.Static; - - created = false; - } - //Static constructor does not exist yet. - else - { - created = true; - MethodAttributes methodAttr = (MonoFN.Cecil.MethodAttributes.HideBySig | - MonoFN.Cecil.MethodAttributes.SpecialName | - MonoFN.Cecil.MethodAttributes.RTSpecialName); - if (makeStatic) - methodAttr |= MonoFN.Cecil.MethodAttributes.Static; - - //Create a constructor. - constructorMethodDef = new MethodDefinition(".ctor", methodAttr, - typeDef.Module.TypeSystem.Void - ); - - typeDef.Methods.Add(constructorMethodDef); - - //Add ret. - ILProcessor processor = constructorMethodDef.Body.GetILProcessor(); - processor.Emit(OpCodes.Ret); - } - - return constructorMethodDef; - } - - /// - /// Creates a return of boolean type. - /// - /// - /// - public void CreateRetBoolean(ILProcessor processor, bool result) - { - OpCode code = (result) ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0; - processor.Emit(code); - processor.Emit(OpCodes.Ret); - } - - #region Debug logging. - /// - /// Creates instructions to log using a NetworkManager or Unity logging. - /// - /// NetworkManager will be used to log first. If the NetworkManager is unavailable Unity logging will be used. - public List LogMessage(MethodDefinition md, string message, LoggingType loggingType) - { - ILProcessor processor = md.Body.GetILProcessor(); - List instructions = new List(); - if (loggingType == LoggingType.Off) - { - base.LogError($"LogMessage called with LoggingType.Off."); - return instructions; - } - - /* Try to store NetworkManager from base to a variable. - * If the base does not exist, such as not inheriting from NetworkBehaviour, - * or if null because the object is not initialized, then use InstanceFinder to - * retrieve the NetworkManager. Then if NetworkManager was found, perform the log. */ - VariableDefinition networkManagerVd = CreateVariable(processor.Body.Method, typeof(NetworkManager)); - - bool useStatic = (md.IsStatic || !md.DeclaringType.InheritsFrom(base.Session)); - //If does not inherit NB then use InstanceFinder. - if (useStatic) - { - SetNetworkManagerFromInstanceFinder(); - } - //Inherits NB, load from base.NetworkManager. - else - { - instructions.Add(processor.Create(OpCodes.Ldarg_0)); - instructions.Add(processor.Create(OpCodes.Call, NetworkBehaviour_NetworkManager_MethodRef)); - instructions.Add(processor.Create(OpCodes.Stloc, networkManagerVd)); - - //If null from NB then use instancefinder. - Instruction skipSetFromInstanceFinderInst = processor.Create(OpCodes.Nop); - //if (nmVd == null) nmVd = InstanceFinder.NetworkManager. - instructions.Add(processor.Create(OpCodes.Ldloc, networkManagerVd)); - instructions.Add(processor.Create(OpCodes.Brtrue_S, skipSetFromInstanceFinderInst)); - SetNetworkManagerFromInstanceFinder(); - instructions.Add(skipSetFromInstanceFinderInst); - } - - //Sets NetworkManager variable from instancefinder. - void SetNetworkManagerFromInstanceFinder() - { - instructions.Add(processor.Create(OpCodes.Call, InstanceFinder_NetworkManager_MethodRef)); - instructions.Add(processor.Create(OpCodes.Stloc, networkManagerVd)); - } - - VariableDefinition networkManagerIsNullVd = CreateVariable(md, typeof(bool)); - //bool networkManagerIsNull = (networkManager == null); - instructions.Add(processor.Create(OpCodes.Ldloc, networkManagerVd)); - instructions.Add(processor.Create(OpCodes.Ldnull)); - instructions.Add(processor.Create(OpCodes.Ceq)); - instructions.Add(processor.Create(OpCodes.Stloc, networkManagerIsNullVd)); - - /* If (networkManagerIsNull) - * networkManager.Log... - * else - * UnityEngine.Debug.Log... */ - Instruction afterNetworkManagerLogInst = processor.Create(OpCodes.Nop); - Instruction afterUnityLogInst = processor.Create(OpCodes.Nop); - instructions.Add(processor.Create(OpCodes.Ldloc, networkManagerIsNullVd)); - instructions.Add(processor.Create(OpCodes.Brtrue, afterNetworkManagerLogInst)); - instructions.AddRange(LogNetworkManagerMessage(md, networkManagerVd, message, loggingType)); - instructions.Add(processor.Create(OpCodes.Br, afterUnityLogInst)); - instructions.Add(afterNetworkManagerLogInst); - instructions.AddRange(LogUnityDebugMessage(md, message, loggingType)); - instructions.Add(afterUnityLogInst); - - return instructions; - } - - /// - /// Creates instructions to log using NetworkManager without error checking. - /// - public List LogNetworkManagerMessage(MethodDefinition md, VariableDefinition networkManagerVd, string message, LoggingType loggingType) - { - List instructions = new List(); - if (!CanUseLogging(loggingType)) - return instructions; - - ILProcessor processor = md.Body.GetILProcessor(); - - MethodReference methodRef; - if (loggingType == LoggingType.Common) - methodRef = NetworkManager_LogCommon_MethodRef; - else if (loggingType == LoggingType.Warning) - methodRef = NetworkManager_LogWarning_MethodRef; - else - methodRef = NetworkManager_LogError_MethodRef; - - instructions.Add(processor.Create(OpCodes.Ldloc, networkManagerVd)); - instructions.Add(processor.Create(OpCodes.Ldstr, message)); - instructions.Add(processor.Create(OpCodes.Call, methodRef)); - - return instructions; - } - - /// - /// Creates instructions to log using Unity logging. - /// - public List LogUnityDebugMessage(MethodDefinition md, string message, LoggingType loggingType) - { - List instructions = new List(); - if (!CanUseLogging(loggingType)) - return instructions; - - ILProcessor processor = md.Body.GetILProcessor(); - - MethodReference methodRef; - if (loggingType == LoggingType.Common) - methodRef = Debug_LogCommon_MethodRef; - else if (loggingType == LoggingType.Warning) - methodRef = Debug_LogWarning_MethodRef; - else - methodRef = Debug_LogError_MethodRef; - - instructions.Add(processor.Create(OpCodes.Ldstr, message)); - instructions.Add(processor.Create(OpCodes.Call, methodRef)); - return instructions; - } - - /// - /// Returns if logging can be done using a LoggingType. - /// - public bool CanUseLogging(LoggingType lt) - { - if (lt == LoggingType.Off) - { - base.LogError($"Log attempt called with LoggingType.Off."); - return false; - } - - return true; - } - #endregion - - #region CreateVariable / CreateParameter. - /// - /// Creates a parameter within methodDef and returns it's ParameterDefinition. - /// - /// - /// - /// - public ParameterDefinition CreateParameter(MethodDefinition methodDef, TypeDefinition parameterTypeDef, string name = "", ParameterAttributes attributes = ParameterAttributes.None, int index = -1) - { - TypeReference typeRef = methodDef.Module.ImportReference(parameterTypeDef); - return CreateParameter(methodDef, typeRef, name, attributes, index); - } - - /// - /// Creates a parameter within methodDef as the next index, with the same data as passed in parameter definition. - /// - public ParameterDefinition CreateParameter(MethodDefinition methodDef, ParameterDefinition parameterTypeDef) - { - base.ImportReference(parameterTypeDef.ParameterType); - - int currentCount = methodDef.Parameters.Count; - string name = (parameterTypeDef.Name + currentCount); - ParameterDefinition parameterDef = new ParameterDefinition(name, parameterTypeDef.Attributes, parameterTypeDef.ParameterType); - methodDef.Parameters.Add(parameterDef); - - return parameterDef; - } - - /// - /// Creates a parameter within methodDef and returns it's ParameterDefinition. - /// - /// - /// - /// - public ParameterDefinition CreateParameter(MethodDefinition methodDef, TypeReference parameterTypeRef, string name = "", ParameterAttributes attributes = ParameterAttributes.None, int index = -1) - { - int currentCount = methodDef.Parameters.Count; - if (string.IsNullOrEmpty(name)) - name = (parameterTypeRef.Name + currentCount); - ParameterDefinition parameterDef = new ParameterDefinition(name, attributes, parameterTypeRef); - if (index == -1) - methodDef.Parameters.Add(parameterDef); - else - methodDef.Parameters.Insert(index, parameterDef); - return parameterDef; - } - /// - /// Creates a parameter within methodDef and returns it's ParameterDefinition. - /// - /// - /// - /// - public ParameterDefinition CreateParameter(MethodDefinition methodDef, Type parameterType, string name = "", ParameterAttributes attributes = ParameterAttributes.None, int index = -1) - { - return CreateParameter(methodDef, GetTypeReference(parameterType), name, attributes, index); - } - /// - /// Creates a variable type within the body and returns it's VariableDef. - /// - /// - /// - /// - public VariableDefinition CreateVariable(MethodDefinition methodDef, TypeReference variableTypeRef) - { - VariableDefinition variableDef = new VariableDefinition(variableTypeRef); - methodDef.Body.Variables.Add(variableDef); - return variableDef; - } - /// Creates a variable type within the body and returns it's VariableDef. - /// - /// - /// - /// - /// - public VariableDefinition CreateVariable(MethodDefinition methodDef, Type variableType) - { - return CreateVariable(methodDef, GetTypeReference(variableType)); - } - #endregion - - #region SetVariableDef. - /// - /// Initializes variableDef as a new object or collection of typeDef. - /// - /// - /// - /// - public void SetVariableDefinitionFromObject(ILProcessor processor, VariableDefinition variableDef, TypeDefinition typeDef) - { - TypeReference type = variableDef.VariableType; - if (type.IsValueType) - { - // structs are created with Initobj - processor.Emit(OpCodes.Ldloca, variableDef); - processor.Emit(OpCodes.Initobj, type); - } - else if (typeDef.InheritsFrom(base.Session)) - { - MethodReference soCreateInstanceMr = processor.Body.Method.Module.ImportReference(() => UnityEngine.ScriptableObject.CreateInstance()); - GenericInstanceMethod genericInstanceMethod = soCreateInstanceMr.GetElementMethod().MakeGenericMethod(new TypeReference[] { type }); - processor.Emit(OpCodes.Call, genericInstanceMethod); - processor.Emit(OpCodes.Stloc, variableDef); - } - else - { - MethodDefinition constructorMethodDef = type.GetConstructor(base.Session); - if (constructorMethodDef == null) - { - base.LogError($"{type.Name} can't be deserialized because a default constructor could not be found. Create a default constructor or a custom serializer/deserializer."); - return; - } - - MethodReference constructorMethodRef = processor.Body.Method.Module.ImportReference(constructorMethodDef); - processor.Emit(OpCodes.Newobj, constructorMethodRef); - processor.Emit(OpCodes.Stloc, variableDef); - } - } - - /// - /// Assigns value to a VariableDef. - /// - /// - /// - /// - public void SetVariableDefinitionFromInt(ILProcessor processor, VariableDefinition variableDef, int value) - { - processor.Emit(OpCodes.Ldc_I4, value); - processor.Emit(OpCodes.Stloc, variableDef); - } - /// - /// Assigns value to a VariableDef. - /// - /// - /// - /// - public void SetVariableDefinitionFromParameter(ILProcessor processor, VariableDefinition variableDef, ParameterDefinition value) - { - processor.Emit(OpCodes.Ldarg, value); - processor.Emit(OpCodes.Stloc, variableDef); - } - #endregion. - - /// - /// Returns if an instruction is a call to a method. - /// - /// - /// - /// - public bool IsCallToMethod(Instruction instruction, out MethodDefinition calledMethod) - { - if (instruction.OpCode == OpCodes.Call && instruction.Operand is MethodDefinition method) - { - calledMethod = method; - return true; - } - else - { - calledMethod = null; - return false; - } - } - - - /// - /// Returns if a serializer and deserializer exist for typeRef. - /// - /// - /// True to create if missing. - /// - public bool HasSerializerAndDeserializer(TypeReference typeRef, bool create) - { - //Make sure it's imported into current module. - typeRef = base.ImportReference(typeRef); - //Can be serialized/deserialized. - bool hasWriter = base.GetClass().HasSerializer(typeRef, create); - bool hasReader = base.GetClass().HasDeserializer(typeRef, create); - - return (hasWriter && hasReader); - } - - /// - /// Creates a return of default value for methodDef. - /// - /// - public List CreateRetDefault(MethodDefinition methodDef, ModuleDefinition importReturnModule = null) - { - ILProcessor processor = methodDef.Body.GetILProcessor(); - List instructions = new List(); - //If requires a value return. - if (methodDef.ReturnType != methodDef.Module.TypeSystem.Void) - { - //Import type first. - methodDef.Module.ImportReference(methodDef.ReturnType); - if (importReturnModule != null) - importReturnModule.ImportReference(methodDef.ReturnType); - VariableDefinition vd = base.GetClass().CreateVariable(methodDef, methodDef.ReturnType); - instructions.Add(processor.Create(OpCodes.Ldloca_S, vd)); - instructions.Add(processor.Create(OpCodes.Initobj, vd.VariableType)); - instructions.Add(processor.Create(OpCodes.Ldloc, vd)); - } - instructions.Add(processor.Create(OpCodes.Ret)); - - return instructions; - } - - #region GeneratedComparers - /// - /// Creates an equality comparer for dataTr. - /// - public MethodDefinition CreateEqualityComparer(TypeReference dataTr) - { - bool created; - MethodDefinition comparerMd; - if (!_comparerDelegates.TryGetValue(dataTr.FullName, out comparerMd)) - { - comparerMd = GetOrCreateMethod(GeneratedComparer_ClassTypeDef, out created, WriterProcessor.GENERATED_METHOD_ATTRIBUTES, - $"Comparer___{dataTr.FullName}", base.Module.TypeSystem.Boolean); - - /* Nullables are not yet supported for automatic - * comparers. Let user know they must make their own. */ - if (dataTr.IsGenericInstance)// dataTr.IsNullable(base.Session)) - { - base.LogError($"Equality comparers cannot be automatically generated for generic types. Create a custom comparer for {dataTr.FullName}."); - return null; - } - if (dataTr.IsArray) - { - base.LogError($"Equality comparers cannot be automatically generated for collections. Create a custom comparer for {dataTr.FullName}."); - return null; - } - - RegisterComparerDelegate(comparerMd, dataTr); - CreateComparerMethod(); - CreateComparerDelegate(comparerMd, dataTr); - } - - return comparerMd; - - void CreateComparerMethod() - { - //Add parameters. - ParameterDefinition v0Pd = CreateParameter(comparerMd, dataTr, "value0"); - ParameterDefinition v1Pd = CreateParameter(comparerMd, dataTr, "value1"); - ILProcessor processor = comparerMd.Body.GetILProcessor(); - comparerMd.Body.InitLocals = true; - - /* If type is a Unity type do not try to - * create a comparer other than ref comparer, as Unity will have built in ones. */ - if (dataTr.CachedResolve(base.Session).Module.Name.Contains("UnityEngine")) - { - CreateValueOrReferenceComparer(); - } - /* Generic types must have a comparer created for the - * generic encapulation as well the argument types. */ - else if (dataTr.IsGenericInstance) - { - CreateGenericInstanceComparer(); - //Create a class or struct comparer for the container. - if (!dataTr.IsClassOrStruct(base.Session)) - { - base.Session.LogError($"Generic data type {dataTr} was expected to be in a container but is not."); - return; - } - else - { - CreateClassOrStructComparer(); - } - } - //Class or struct. - else if (dataTr.IsClassOrStruct(base.Session)) - { - CreateClassOrStructComparer(); - } - //Value type. - else if (dataTr.IsValueType) - { - CreateValueOrReferenceComparer(); - } - //Unhandled type. - else - { - base.Session.LogError($"Comparer data type {dataTr.FullName} is unhandled."); - return; - } - - void CreateGenericInstanceComparer() - { - /* Create for arguments first. */ - GenericInstanceType git = dataTr as GenericInstanceType; - if (git == null || git.GenericArguments.Count == 0) - { - base.LogError($"Comparer data is generic but generic type returns null, or has no generic arguments."); - return; - } - foreach (TypeReference tr in git.GenericArguments) - { - TypeReference trImported = base.ImportReference(tr); - CreateEqualityComparer(trImported); - } - } - - - - void CreateClassOrStructComparer() - { - //Class or struct. - Instruction exitMethodInst = processor.Create(OpCodes.Ldc_I4_0); - - //Fields. - foreach (FieldDefinition fieldDef in dataTr.FindAllSerializableFields(base.Session - , null, WriterProcessor.EXCLUDED_ASSEMBLY_PREFIXES)) - { - base.ImportReference(fieldDef); - MethodDefinition recursiveMd = CreateEqualityComparer(fieldDef.FieldType); - if (recursiveMd == null) - break; - processor.Append(GetLoadParameterInstruction(comparerMd, v0Pd)); - processor.Emit(OpCodes.Ldfld, fieldDef); - processor.Append(GetLoadParameterInstruction(comparerMd, v1Pd)); - processor.Emit(OpCodes.Ldfld, fieldDef); - FinishTypeReferenceCompare(fieldDef.FieldType); - } - - //Properties. - foreach (PropertyDefinition propertyDef in dataTr.FindAllSerializableProperties(base.Session - , null, WriterProcessor.EXCLUDED_ASSEMBLY_PREFIXES)) - { - MethodReference getMr = base.Module.ImportReference(propertyDef.GetMethod); - MethodDefinition recursiveMd = CreateEqualityComparer(getMr.ReturnType); - if (recursiveMd == null) - break; - processor.Append(GetLoadParameterInstruction(comparerMd, v0Pd)); - processor.Emit(OpCodes.Call, getMr); - processor.Append(GetLoadParameterInstruction(comparerMd, v1Pd)); - processor.Emit(OpCodes.Call, getMr); - FinishTypeReferenceCompare(propertyDef.PropertyType); - } - - //Return true; - processor.Emit(OpCodes.Ldc_I4_1); - processor.Emit(OpCodes.Ret); - processor.Append(exitMethodInst); - processor.Emit(OpCodes.Ret); - - - void FinishTypeReferenceCompare(TypeReference tr) - { - /* If a class or struct see if it already has a comparer - * using IEquatable. If so then call the comparer method. - * Otherwise make a new comparer and call it. */ - if (tr.IsClassOrStruct(base.Session)) - { - //Make equatable for type. - GenericInstanceType git = IEquatable_TypeRef.MakeGenericInstanceType(tr); - bool createNestedComparer = !tr.CachedResolve(base.Session).ImplementsInterface(git.FullName); - //Create new. - if (createNestedComparer) - { - MethodDefinition cMd = CreateEqualityComparer(tr); - processor.Emit(OpCodes.Call, cMd); - processor.Emit(OpCodes.Brfalse, exitMethodInst); - } - //Call existing. - else - { - MethodDefinition cMd = tr.CachedResolve(base.Session).GetMethod("op_Equality"); - if (cMd == null) - { - base.LogError($"Type {tr.FullName} implements IEquatable but the comparer method could not be found."); - return; - } - else - { - MethodReference mr = base.ImportReference(cMd); - processor.Emit(OpCodes.Call, mr); - processor.Emit(OpCodes.Brfalse, exitMethodInst); - } - } - } - //Value types do not need to check custom comparers. - else - { - processor.Emit(OpCodes.Bne_Un, exitMethodInst); - } - - } - } - - void CreateValueOrReferenceComparer() - { - base.ImportReference(dataTr); - processor.Append(GetLoadParameterInstruction(comparerMd, v0Pd)); - processor.Append(GetLoadParameterInstruction(comparerMd, v1Pd)); - processor.Emit(OpCodes.Ceq); - processor.Emit(OpCodes.Ret); - } - - } - - } - - /// - /// Registers a comparer method. - /// - /// - /// - public void RegisterComparerDelegate(MethodDefinition methodDef, TypeReference dataTr) - { - _comparerDelegates.Add(dataTr.FullName, methodDef); - } - /// - /// Creates a delegate for GeneratedComparers. - /// - public void CreateComparerDelegate(MethodDefinition comparerMd, TypeReference dataTr) - { - dataTr = base.ImportReference(dataTr); - //Initialize delegate for made comparer. - List insts = new List(); - ILProcessor processor = GeneratedComparer_OnLoadMethodDef.Body.GetILProcessor(); - //Create a Func delegate - insts.Add(processor.Create(OpCodes.Ldnull)); - insts.Add(processor.Create(OpCodes.Ldftn, comparerMd)); - - GenericInstanceType git; - git = FunctionT3TypeRef.MakeGenericInstanceType(dataTr, dataTr, GetTypeReference(typeof(bool))); - MethodReference functionConstructorInstanceMethodRef = FunctionT3ConstructorMethodRef.MakeHostInstanceGeneric(base.Session, git); - insts.Add(processor.Create(OpCodes.Newobj, functionConstructorInstanceMethodRef)); - - //Call delegate to ReplicateComparer.Compare(T, T); - git = GeneratedComparer_TypeRef.MakeGenericInstanceType(dataTr); - MethodReference comparerMr = GeneratedComparer_Compare_Set_MethodRef.MakeHostInstanceGeneric(base.Session, git); - insts.Add(processor.Create(OpCodes.Call, comparerMr)); - processor.InsertFirst(insts); - } - - - - /// - /// Returns an OpCode for loading a parameter. - /// - public OpCode GetLoadParameterOpCode(ParameterDefinition pd) - { - TypeReference tr = pd.ParameterType; - return (tr.IsValueType && tr.IsClassOrStruct(base.Session)) ? OpCodes.Ldarga : OpCodes.Ldarg; - } - - /// - /// Returns an instruction for loading a parameter.s - /// - public Instruction GetLoadParameterInstruction(MethodDefinition md, ParameterDefinition pd) - { - ILProcessor processor = md.Body.GetILProcessor(); - OpCode oc = GetLoadParameterOpCode(pd); - return processor.Create(oc, pd); - } - - /// - /// Creates an IsDefault comparer for dataTr. - /// - public void CreateIsDefaultComparer(TypeReference dataTr, MethodDefinition compareMethodDef) - { - GeneralHelper gh = base.GetClass(); - - MethodDefinition isDefaultMd = gh.GetOrCreateMethod(GeneratedComparer_ClassTypeDef, out bool created, WriterProcessor.GENERATED_METHOD_ATTRIBUTES, - $"IsDefault___{dataTr.FullName}", base.Module.TypeSystem.Boolean); - //Already done. This can happen if the same replicate data is used in multiple places. - if (!created) - return; - - MethodReference compareMr = base.ImportReference(compareMethodDef); - CreateIsDefaultMethod(); - CreateIsDefaultDelegate(); - - void CreateIsDefaultMethod() - { - //Add parameters. - ParameterDefinition v0Pd = gh.CreateParameter(isDefaultMd, dataTr, "value0"); - ILProcessor processor = isDefaultMd.Body.GetILProcessor(); - isDefaultMd.Body.InitLocals = true; - - - processor.Emit(OpCodes.Ldarg, v0Pd); - //If a struct. - if (dataTr.IsValueType) - { - //Init a default local. - VariableDefinition defaultVd = gh.CreateVariable(isDefaultMd, dataTr); - processor.Emit(OpCodes.Ldloca, defaultVd); - processor.Emit(OpCodes.Initobj, dataTr); - processor.Emit(OpCodes.Ldloc, defaultVd); - } - //If a class. - else - { - processor.Emit(OpCodes.Ldnull); - } - - processor.Emit(OpCodes.Call, compareMr); - processor.Emit(OpCodes.Ret); - - - } - - //Creates a delegate to compare two of replicateTr. - void CreateIsDefaultDelegate() - { - //Initialize delegate for made comparer. - List insts = new List(); - ILProcessor processor = GeneratedComparer_OnLoadMethodDef.Body.GetILProcessor(); - //Create a Func delegate - insts.Add(processor.Create(OpCodes.Ldnull)); - insts.Add(processor.Create(OpCodes.Ldftn, isDefaultMd)); - - GenericInstanceType git; - git = gh.FunctionT2TypeRef.MakeGenericInstanceType(dataTr, gh.GetTypeReference(typeof(bool))); - MethodReference funcCtorMethodRef = gh.FunctionT2ConstructorMethodRef.MakeHostInstanceGeneric(base.Session, git); - insts.Add(processor.Create(OpCodes.Newobj, funcCtorMethodRef)); - - //Call delegate to ReplicateComparer.IsDefault(T). - git = GeneratedComparer_TypeRef.MakeGenericInstanceType(dataTr); - MethodReference isDefaultMr = GeneratedComparer_IsDefault_Set_MethodRef.MakeHostInstanceGeneric(base.Session, git); - insts.Add(processor.Create(OpCodes.Call, isDefaultMr)); - processor.InsertFirst(insts); - } - - } - #endregion - } -} - diff --git a/Assets/FishNet/CodeGenerating/Helpers/GeneralHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/GeneralHelper.cs.meta deleted file mode 100644 index 804c6a0..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/GeneralHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6139ff104f3c24442b26dbc4e40d5ce5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/GenericReaderHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/GenericReaderHelper.cs deleted file mode 100644 index c42cb5a..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/GenericReaderHelper.cs +++ /dev/null @@ -1 +0,0 @@ -//Remove on 2024/01/01 \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/GenericReaderHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/GenericReaderHelper.cs.meta deleted file mode 100644 index 9fd930e..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/GenericReaderHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8bc93cce5d44d604c805976e696dd7da -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/GenericWriterHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/GenericWriterHelper.cs deleted file mode 100644 index c42cb5a..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/GenericWriterHelper.cs +++ /dev/null @@ -1 +0,0 @@ -//Remove on 2024/01/01 \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/GenericWriterHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/GenericWriterHelper.cs.meta deleted file mode 100644 index 87f5a07..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/GenericWriterHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: dcb8399b7678ff1429b6e211e6f26d10 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/NetworkBehaviourHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/NetworkBehaviourHelper.cs deleted file mode 100644 index 95c10a8..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/NetworkBehaviourHelper.cs +++ /dev/null @@ -1,443 +0,0 @@ -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.CodeGenerating.Processing; -using FishNet.Configuring; -using FishNet.Managing.Logging; -using FishNet.Object; -using FishNet.Object.Delegating; -using FishNet.Object.Helping; -using FishNet.Object.Prediction.Delegating; -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -namespace FishNet.CodeGenerating.Helping -{ - internal class NetworkBehaviourHelper : CodegenBase - { - #region Reflection references. - //Names. - internal string FullName; - //Prediction. - public string ClearReplicateCache_Method_Name = nameof(NetworkBehaviour.ClearReplicateCache_Internal); - public MethodReference Replicate_Server_MethodRef; - public MethodReference Replicate_Client_MethodRef; - public MethodReference Replicate_Reader_MethodRef; - public MethodReference Replicate_ExitEarly_A_MethodRef; - public MethodReference Reconcile_ExitEarly_A_MethodRef; - public MethodReference Reconcile_Server_MethodRef; - public MethodReference Reconcile_Client_MethodRef; - public MethodReference Reconcile_Reader_MethodRef; - public MethodReference RegisterReplicateRpc_MethodRef; - public MethodReference RegisterReconcileRpc_MethodRef; - public MethodReference ReplicateRpcDelegateConstructor_MethodRef; - public MethodReference ReconcileRpcDelegateConstructor_MethodRef; - //RPCs. - public MethodReference SendServerRpc_MethodRef; - public MethodReference SendObserversRpc_MethodRef; - public MethodReference SendTargetRpc_MethodRef; - public MethodReference DirtySyncType_MethodRef; - public MethodReference RegisterServerRpc_MethodRef; - public MethodReference RegisterObserversRpc_MethodRef; - public MethodReference RegisterTargetRpc_MethodRef; - public MethodReference ServerRpcDelegateConstructor_MethodRef; - public MethodReference ClientRpcDelegateConstructor_MethodRef; - //Is checks. - public MethodReference IsClient_MethodRef; - public MethodReference IsOwner_MethodRef; - public MethodReference IsServer_MethodRef; - public MethodReference IsHost_MethodRef; - //Misc. - public TypeReference TypeRef; - public MethodReference OwnerMatches_MethodRef; - public MethodReference LocalConnection_MethodRef; - public MethodReference Owner_MethodRef; - public MethodReference ReadSyncVar_MethodRef; - public MethodReference NetworkInitializeIfDisabled_MethodRef; - //TimeManager. - public MethodReference TimeManager_MethodRef; - #endregion - - #region Const. - internal const uint MAX_RPC_ALLOWANCE = ushort.MaxValue; - internal const string AWAKE_METHOD_NAME = "Awake"; - internal const string DISABLE_LOGGING_TEXT = "This message may be disabled by setting the Logging field in your attribute to LoggingType.Off"; - #endregion - - public override bool ImportReferences() - { - Type networkBehaviourType = typeof(NetworkBehaviour); - TypeRef = base.ImportReference(networkBehaviourType); - FullName = networkBehaviourType.FullName; - base.ImportReference(networkBehaviourType); - - //ServerRpcDelegate and ClientRpcDelegate constructors. - ServerRpcDelegateConstructor_MethodRef = base.ImportReference(typeof(ServerRpcDelegate).GetConstructors().First()); - ClientRpcDelegateConstructor_MethodRef = base.ImportReference(typeof(ClientRpcDelegate).GetConstructors().First()); - //Prediction Rpc delegate constructors. - ReplicateRpcDelegateConstructor_MethodRef = base.ImportReference(typeof(ReplicateRpcDelegate).GetConstructors().First()); - ReconcileRpcDelegateConstructor_MethodRef = base.ImportReference(typeof(ReconcileRpcDelegate).GetConstructors().First()); - - foreach (MethodInfo mi in networkBehaviourType.GetMethods((BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic))) - { - //CreateDelegates. - if (mi.Name == nameof(NetworkBehaviour.RegisterServerRpc_Internal)) - RegisterServerRpc_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.RegisterObserversRpc_Internal)) - RegisterObserversRpc_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.RegisterTargetRpc_Internal)) - RegisterTargetRpc_MethodRef = base.ImportReference(mi); - //SendPredictions. - else if (mi.Name == nameof(NetworkBehaviour.RegisterReplicateRpc_Internal)) - RegisterReplicateRpc_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.RegisterReconcileRpc_Internal)) - RegisterReconcileRpc_MethodRef = base.ImportReference(mi); - //SendRpcs. - else if (mi.Name == nameof(NetworkBehaviour.SendServerRpc_Internal)) - SendServerRpc_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.SendObserversRpc_Internal)) - SendObserversRpc_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.SendTargetRpc_Internal)) - SendTargetRpc_MethodRef = base.ImportReference(mi); - //Prediction. - else if (mi.Name == nameof(NetworkBehaviour.Replicate_ExitEarly_A_Internal)) - Replicate_ExitEarly_A_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.Replicate_Server_Internal)) - Replicate_Server_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.Replicate_Reader_Internal)) - Replicate_Reader_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.Reconcile_Reader_Internal)) - Reconcile_Reader_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.Reconcile_ExitEarly_A_Internal)) - Reconcile_ExitEarly_A_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.Reconcile_Server_Internal)) - Reconcile_Server_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.Replicate_Client_Internal)) - Replicate_Client_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.Reconcile_Client_Internal)) - Reconcile_Client_MethodRef = base.ImportReference(mi); - //Misc. - else if (mi.Name == nameof(NetworkBehaviour.OwnerMatches)) - OwnerMatches_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.ReadSyncVar)) - ReadSyncVar_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.DirtySyncType)) - DirtySyncType_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(NetworkBehaviour.NetworkInitializeIfDisabled)) - NetworkInitializeIfDisabled_MethodRef = base.ImportReference(mi); - } - - foreach (PropertyInfo pi in networkBehaviourType.GetProperties((BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic))) - { - //Server/Client states. - if (pi.Name == nameof(NetworkBehaviour.IsClient)) - IsClient_MethodRef = base.ImportReference(pi.GetMethod); - else if (pi.Name == nameof(NetworkBehaviour.IsServer)) - IsServer_MethodRef = base.ImportReference(pi.GetMethod); - else if (pi.Name == nameof(NetworkBehaviour.IsHost)) - IsHost_MethodRef = base.ImportReference(pi.GetMethod); - else if (pi.Name == nameof(NetworkBehaviour.IsOwner)) - IsOwner_MethodRef = base.ImportReference(pi.GetMethod); - //Owner. - else if (pi.Name == nameof(NetworkBehaviour.Owner)) - Owner_MethodRef = base.ImportReference(pi.GetMethod); - else if (pi.Name == nameof(NetworkBehaviour.LocalConnection)) - LocalConnection_MethodRef = base.ImportReference(pi.GetMethod); - //Misc. - else if (pi.Name == nameof(NetworkBehaviour.TimeManager)) - TimeManager_MethodRef = base.ImportReference(pi.GetMethod); - } - - return true; - } - - /// - /// Returnsthe child most Awake by iterating up childMostTypeDef. - /// - /// - /// - /// - internal MethodDefinition GetAwakeMethodDefinition(TypeDefinition typeDef) - { - return typeDef.GetMethod(AWAKE_METHOD_NAME); - } - - - /// - /// Creates a replicate delegate. - /// - /// - /// - /// - /// - internal void CreateReplicateDelegate(MethodDefinition originalMethodDef, MethodDefinition readerMethodDef, uint methodHash) - { - MethodDefinition methodDef = originalMethodDef.DeclaringType.GetMethod(NetworkBehaviourProcessor.NETWORKINITIALIZE_EARLY_INTERNAL_NAME); - ILProcessor processor = methodDef.Body.GetILProcessor(); - - List insts = new List(); - insts.Add(processor.Create(OpCodes.Ldarg_0)); - - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)methodHash)); - - /* Create delegate and call NetworkBehaviour method. */ - insts.Add(processor.Create(OpCodes.Ldnull)); - insts.Add(processor.Create(OpCodes.Ldftn, readerMethodDef)); - - /* Has to be done last. This allows the NetworkBehaviour to - * initialize it's fields first. */ - processor.InsertLast(insts); - } - - - - /// - /// Creates a RPC delegate for rpcType. - /// - /// - /// - /// - /// - internal void CreateRpcDelegate(bool runLocally, TypeDefinition typeDef, MethodDefinition readerMethodDef, RpcType rpcType, uint methodHash, CustomAttribute rpcAttribute) - { - - - MethodDefinition methodDef = typeDef.GetMethod(NetworkBehaviourProcessor.NETWORKINITIALIZE_EARLY_INTERNAL_NAME); - ILProcessor processor = methodDef.Body.GetILProcessor(); - - List insts = new List(); - insts.Add(processor.Create(OpCodes.Ldarg_0)); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)methodHash)); - - /* Create delegate and call NetworkBehaviour method. */ - insts.Add(processor.Create(OpCodes.Ldarg_0)); - insts.Add(processor.Create(OpCodes.Ldftn, readerMethodDef)); - //Server. - if (rpcType == RpcType.Server) - { - insts.Add(processor.Create(OpCodes.Newobj, ServerRpcDelegateConstructor_MethodRef)); - insts.Add(processor.Create(OpCodes.Call, RegisterServerRpc_MethodRef)); - } - //Observers. - else if (rpcType == RpcType.Observers) - { - insts.Add(processor.Create(OpCodes.Newobj, ClientRpcDelegateConstructor_MethodRef)); - insts.Add(processor.Create(OpCodes.Call, RegisterObserversRpc_MethodRef)); - } - //Target - else if (rpcType == RpcType.Target) - { - insts.Add(processor.Create(OpCodes.Newobj, ClientRpcDelegateConstructor_MethodRef)); - insts.Add(processor.Create(OpCodes.Call, RegisterTargetRpc_MethodRef)); - } - - /* Has to be done last. This allows the NetworkBehaviour to - * initialize it's fields first. */ - processor.InsertLast(insts); - } - - /// - /// Creates exit method condition if local client is not owner. - /// - /// True if to ret when owner, false to ret when not owner. - /// Returns Ret instruction. - internal Instruction CreateLocalClientIsOwnerCheck(MethodDefinition methodDef, LoggingType loggingType, bool notifyMessageCanBeDisabled, bool retIfOwner, bool insertFirst) - { - List instructions = new List(); - /* This is placed after the if check. - * Should the if check pass then code - * jumps to this instruction. */ - ILProcessor processor = methodDef.Body.GetILProcessor(); - Instruction endIf = processor.Create(OpCodes.Nop); - - instructions.Add(processor.Create(OpCodes.Ldarg_0)); //argument: this - //If !base.IsOwner endIf. - instructions.Add(processor.Create(OpCodes.Call, IsOwner_MethodRef)); - if (retIfOwner) - instructions.Add(processor.Create(OpCodes.Brfalse, endIf)); - else - instructions.Add(processor.Create(OpCodes.Brtrue, endIf)); - //If logging is not disabled. - if (loggingType != LoggingType.Off) - { - string disableLoggingText = (notifyMessageCanBeDisabled) ? DISABLE_LOGGING_TEXT : string.Empty; - string msg = (retIfOwner) ? - $"Cannot complete action because you are the owner of this object. {disableLoggingText}." : - $"Cannot complete action because you are not the owner of this object. {disableLoggingText}."; - - instructions.AddRange(base.GetClass().LogMessage(methodDef, msg, loggingType)); - } - //Return block. - Instruction retInst = processor.Create(OpCodes.Ret); - instructions.Add(retInst); - //After if statement, jumped to when successful check. - instructions.Add(endIf); - - if (insertFirst) - { - processor.InsertFirst(instructions); - } - else - { - foreach (Instruction inst in instructions) - processor.Append(inst); - } - - return retInst; - } - - /// - /// Creates exit method condition if remote client is not owner. - /// - /// - internal Instruction CreateRemoteClientIsOwnerCheck(ILProcessor processor, ParameterDefinition connectionParameterDef) - { - /* This is placed after the if check. - * Should the if check pass then code - * jumps to this instruction. */ - Instruction endIf = processor.Create(OpCodes.Nop); - - processor.Emit(OpCodes.Ldarg_0); //argument: this - //If !base.IsOwner endIf. - processor.Emit(OpCodes.Ldarg, connectionParameterDef); - processor.Emit(OpCodes.Call, OwnerMatches_MethodRef); - processor.Emit(OpCodes.Brtrue, endIf); - //Return block. - Instruction retInst = processor.Create(OpCodes.Ret); - processor.Append(retInst); - - //After if statement, jumped to when successful check. - processor.Append(endIf); - - return retInst; - } - - /// - /// Creates exit method condition if not client. - /// - /// - /// - /// - internal void CreateIsClientCheck(MethodDefinition methodDef, LoggingType loggingType, bool useStatic, bool insertFirst) - { - /* This is placed after the if check. - * Should the if check pass then code - * jumps to this instruction. */ - ILProcessor processor = methodDef.Body.GetILProcessor(); - Instruction endIf = processor.Create(OpCodes.Nop); - - List instructions = new List(); - //Checking against the NetworkObject. - if (!useStatic) - { - instructions.Add(processor.Create(OpCodes.Ldarg_0)); //argument: this - //If (!base.IsClient) - instructions.Add(processor.Create(OpCodes.Call, IsClient_MethodRef)); - } - //Checking instanceFinder. - else - { - instructions.Add(processor.Create(OpCodes.Call, base.GetClass().InstanceFinder_IsClient_MethodRef)); - } - instructions.Add(processor.Create(OpCodes.Brtrue, endIf)); - //If warning then also append warning text. - if (loggingType != LoggingType.Off) - { - string msg = $"Cannot complete action because client is not active. This may also occur if the object is not yet initialized or if it does not contain a NetworkObject component. {DISABLE_LOGGING_TEXT}."; - instructions.AddRange(base.GetClass().LogMessage(methodDef, msg, loggingType)); - } - //Add return. - instructions.AddRange(CreateRetDefault(methodDef)); - //After if statement, jumped to when successful check. - instructions.Add(endIf); - - if (insertFirst) - { - processor.InsertFirst(instructions); - } - else - { - foreach (Instruction inst in instructions) - processor.Append(inst); - } - } - - - /// - /// Creates exit method condition if not server. - /// - /// - /// - internal void CreateIsServerCheck(MethodDefinition methodDef, LoggingType loggingType, bool useStatic, bool insertFirst) - { - /* This is placed after the if check. - * Should the if check pass then code - * jumps to this instruction. */ - ILProcessor processor = methodDef.Body.GetILProcessor(); - Instruction endIf = processor.Create(OpCodes.Nop); - - List instructions = new List(); - if (!useStatic) - { - instructions.Add(processor.Create(OpCodes.Ldarg_0)); //argument: this - //If (!base.IsServer) - instructions.Add(processor.Create(OpCodes.Call, IsServer_MethodRef)); - } - //Checking instanceFinder. - else - { - instructions.Add(processor.Create(OpCodes.Call, base.GetClass().InstanceFinder_IsServer_MethodRef)); - } - instructions.Add(processor.Create(OpCodes.Brtrue, endIf)); - //If warning then also append warning text. - if (loggingType != LoggingType.Off) - { - string msg = $"Cannot complete action because server is not active. This may also occur if the object is not yet initialized or if it does not contain a NetworkObject component. {DISABLE_LOGGING_TEXT}"; - instructions.AddRange(base.GetClass().LogMessage(methodDef, msg, loggingType)); - } - //Add return. - instructions.AddRange(CreateRetDefault(methodDef)); - //After if statement, jumped to when successful check. - instructions.Add(endIf); - - if (insertFirst) - { - processor.InsertFirst(instructions); - } - else - { - foreach (Instruction inst in instructions) - processor.Append(inst); - } - } - - /// - /// Creates a return using the ReturnType for methodDef. - /// - /// - /// - /// - public List CreateRetDefault(MethodDefinition methodDef, ModuleDefinition importReturnModule = null) - { - ILProcessor processor = methodDef.Body.GetILProcessor(); - List instructions = new List(); - //If requires a value return. - if (methodDef.ReturnType != methodDef.Module.TypeSystem.Void) - { - //Import type first. - methodDef.Module.ImportReference(methodDef.ReturnType); - if (importReturnModule != null) - importReturnModule.ImportReference(methodDef.ReturnType); - VariableDefinition vd = base.GetClass().CreateVariable(methodDef, methodDef.ReturnType); - instructions.Add(processor.Create(OpCodes.Ldloca_S, vd)); - instructions.Add(processor.Create(OpCodes.Initobj, vd.VariableType)); - instructions.Add(processor.Create(OpCodes.Ldloc, vd)); - } - instructions.Add(processor.Create(OpCodes.Ret)); - - return instructions; - } - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/NetworkBehaviourHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/NetworkBehaviourHelper.cs.meta deleted file mode 100644 index 55c1c3c..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/NetworkBehaviourHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0c42e06349d6890459a155a2afe17d41 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionHelper.cs deleted file mode 100644 index 2111ff4..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionHelper.cs +++ /dev/null @@ -1 +0,0 @@ -//Remove on 2023/06/01 \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionHelper.cs.meta deleted file mode 100644 index f5985b9..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: bcbcb288008d6da4eab7a5279dd6b4f8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionImports.cs b/Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionImports.cs deleted file mode 100644 index 30871f1..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionImports.cs +++ /dev/null @@ -1,42 +0,0 @@ -using FishNet.Connection; -using MonoFN.Cecil; -using System; -using System.Reflection; - -namespace FishNet.CodeGenerating.Helping -{ - internal class NetworkConnectionImports : CodegenBase - { - #region Reflection references. - //Names. - internal string FullName; - public MethodReference IsLocalClient_Get_MethodRef; - #endregion - - #region Const. - internal const uint MAX_RPC_ALLOWANCE = ushort.MaxValue; - internal const string AWAKE_METHOD_NAME = "Awake"; - internal const string DISABLE_LOGGING_TEXT = "This message may be disabled by setting the Logging field in your attribute to LoggingType.Off"; - #endregion - - public override bool ImportReferences() - { - Type type = typeof(NetworkConnection); - base.ImportReference(type); - - FullName = type.FullName; - - foreach (PropertyInfo pi in type.GetProperties()) - { - if (pi.Name == nameof(NetworkConnection.IsLocalClient)) - { - IsLocalClient_Get_MethodRef = base.ImportReference(pi.GetMethod); - break; - } - } - - return true; - } - - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionImports.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionImports.cs.meta deleted file mode 100644 index f8b4ff2..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/NetworkConnectionImports.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6d061dda8ed87ed48a08020942ad63f6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/ObjectHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/ObjectHelper.cs deleted file mode 100644 index f4adf76..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/ObjectHelper.cs +++ /dev/null @@ -1,94 +0,0 @@ -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.Connection; -using FishNet.Object; -using FishNet.Object.Synchronizing; -using FishNet.Object.Synchronizing.Internal; -using MonoFN.Cecil; -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace FishNet.CodeGenerating.Helping -{ - internal class ObjectHelper : CodegenBase - { - #region Reflection references. - //Fullnames. - public string SyncList_Name; - public string SyncDictionary_Name; - public string SyncHashSet_Name; - //Is checks. - public MethodReference InstanceFinder_IsServer_MethodRef; - public MethodReference InstanceFinder_IsClient_MethodRef; - //Misc. - public TypeReference NetworkBehaviour_TypeRef; - public MethodReference NetworkConnection_IsValid_MethodRef; - public MethodReference NetworkConnection_IsActive_MethodRef; - public MethodReference Dictionary_Add_UShort_SyncBase_MethodRef; - public MethodReference NetworkConnection_GetIsLocalClient_MethodRef; - #endregion - - public override bool ImportReferences() - { - Type tmpType; - /* SyncObject names. */ - //SyncList. - tmpType = typeof(SyncList<>); - base.ImportReference(tmpType); - SyncList_Name = tmpType.Name; - //SyncDictionary. - tmpType = typeof(SyncDictionary<,>); - base.ImportReference(tmpType); - SyncDictionary_Name = tmpType.Name; - //SyncHashSet. - tmpType = typeof(SyncHashSet<>); - base.ImportReference(tmpType); - SyncHashSet_Name = tmpType.Name; - - NetworkBehaviour_TypeRef = base.ImportReference(typeof(NetworkBehaviour)); - - tmpType = typeof(NetworkConnection); - TypeReference networkConnectionTr = base.ImportReference(tmpType); - foreach (PropertyDefinition item in networkConnectionTr.CachedResolve(base.Session).Properties) - { - if (item.Name == nameof(NetworkConnection.IsLocalClient)) - NetworkConnection_GetIsLocalClient_MethodRef = base.ImportReference(item.GetMethod); - } - - //Dictionary.Add(ushort, SyncBase). - Type dictType = typeof(Dictionary); - TypeReference dictTypeRef = base.ImportReference(dictType); - //Dictionary_Add_UShort_SyncBase_MethodRef = dictTypeRef.CachedResolve(base.Session).GetMethod("add_Item", ) - foreach (MethodDefinition item in dictTypeRef.CachedResolve(base.Session).Methods) - { - if (item.Name == nameof(Dictionary.Add)) - { - Dictionary_Add_UShort_SyncBase_MethodRef = base.ImportReference(item); - break; - } - } - - //InstanceFinder infos. - Type instanceFinderType = typeof(InstanceFinder); - foreach (PropertyInfo pi in instanceFinderType.GetProperties()) - { - if (pi.Name == nameof(InstanceFinder.IsClient)) - InstanceFinder_IsClient_MethodRef = base.ImportReference(pi.GetMethod); - else if (pi.Name == nameof(InstanceFinder.IsServer)) - InstanceFinder_IsServer_MethodRef = base.ImportReference(pi.GetMethod); - } - - //NetworkConnection. - foreach (PropertyInfo pi in typeof(NetworkConnection).GetProperties((BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic))) - { - if (pi.Name == nameof(NetworkConnection.IsValid)) - NetworkConnection_IsValid_MethodRef = base.ImportReference(pi.GetMethod); - else if (pi.Name == nameof(NetworkConnection.IsActive)) - NetworkConnection_IsActive_MethodRef = base.ImportReference(pi.GetMethod); - } - - return true; - } - - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/ObjectHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/ObjectHelper.cs.meta deleted file mode 100644 index 4e50b5f..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/ObjectHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 033da35314653aa4689b4582e7929295 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/PhysicsHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/PhysicsHelper.cs deleted file mode 100644 index 25224b0..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/PhysicsHelper.cs +++ /dev/null @@ -1,117 +0,0 @@ -using FishNet.CodeGenerating.Extension; -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.Connection; -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using System.Collections.Generic; -using UnityEngine; -using SR = System.Reflection; - - -namespace FishNet.CodeGenerating.Helping -{ - internal class PhysicsHelper : CodegenBase - { - #region Reflection references. - public MethodReference GetScene_MethodRef; - public MethodReference GetPhysicsScene2D_MethodRef; - public MethodReference GetPhysicsScene3D_MethodRef; - public MethodReference Physics3D_Simulate_MethodRef; - public MethodReference Physics2D_Simulate_MethodRef; - public MethodReference Physics3D_SyncTransforms_MethodRef; - public MethodReference Physics2D_SyncTransforms_MethodRef; - #endregion - - public override bool ImportReferences() - { - SR.MethodInfo locMi; - //GetScene. - locMi = typeof(GameObject).GetMethod("get_scene"); - GetScene_MethodRef = base.ImportReference(locMi); - - //Physics.SyncTransform. - foreach (SR.MethodInfo mi in typeof(Physics).GetMethods()) - { - if (mi.Name == nameof(Physics.SyncTransforms)) - { - Physics3D_SyncTransforms_MethodRef = base.ImportReference(mi); - break; - } - } - foreach (SR.MethodInfo mi in typeof(Physics2D).GetMethods()) - { - if (mi.Name == nameof(Physics2D.SyncTransforms)) - { - Physics2D_SyncTransforms_MethodRef = base.ImportReference(mi); - break; - } - } - - //PhysicsScene.Simulate. - foreach (SR.MethodInfo mi in typeof(PhysicsScene).GetMethods()) - { - if (mi.Name == nameof(PhysicsScene.Simulate)) - { - Physics3D_Simulate_MethodRef = base.ImportReference(mi); - break; - } - } - foreach (SR.MethodInfo mi in typeof(PhysicsScene2D).GetMethods()) - { - if (mi.Name == nameof(PhysicsScene2D.Simulate)) - { - Physics2D_Simulate_MethodRef = base.ImportReference(mi); - break; - } - } - - //GetPhysicsScene. - foreach (SR.MethodInfo mi in typeof(PhysicsSceneExtensions).GetMethods()) - { - if (mi.Name == nameof(PhysicsSceneExtensions.GetPhysicsScene)) - { - GetPhysicsScene3D_MethodRef = base.ImportReference(mi); - break; - } - } - foreach (SR.MethodInfo mi in typeof(PhysicsSceneExtensions2D).GetMethods()) - { - if (mi.Name == nameof(PhysicsSceneExtensions2D.GetPhysicsScene2D)) - { - GetPhysicsScene2D_MethodRef = base.ImportReference(mi); - break; - } - } - - return true; - } - - - /// - /// Returns instructions to get a physics scene from a gameObject. - /// - public List GetPhysicsScene(MethodDefinition md, VariableDefinition gameObjectVd, bool threeDimensional) - { - ILProcessor processor = md.Body.GetILProcessor(); - return GetPhysicsScene(processor, gameObjectVd, threeDimensional); - } - - /// - /// Returns instructions to get a physics scene from a gameObject. - /// - public List GetPhysicsScene(ILProcessor processor, VariableDefinition gameObjectVd, bool threeDimensional) - { - List insts = new List(); - - //gameObject.scene.GetPhysics... - insts.Add(processor.Create(OpCodes.Ldloc, gameObjectVd)); - insts.Add(processor.Create(GetScene_MethodRef.GetCallOpCode(base.Session), GetScene_MethodRef)); - if (threeDimensional) - insts.Add(processor.Create(OpCodes.Call, GetPhysicsScene3D_MethodRef)); - else - insts.Add(processor.Create(OpCodes.Call, GetPhysicsScene2D_MethodRef)); - - return insts; - } - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/PhysicsHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/PhysicsHelper.cs.meta deleted file mode 100644 index 1f43ee9..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/PhysicsHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 28ae27f7bc8e89547a606262508fdd36 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/PredictedObjectHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/PredictedObjectHelper.cs deleted file mode 100644 index b8e119d..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/PredictedObjectHelper.cs +++ /dev/null @@ -1,15 +0,0 @@ -using FishNet.Component.Prediction; -using MonoFN.Cecil; -using System; -using System.Reflection; - -namespace FishNet.CodeGenerating.Helping -{ - internal class PredictedObjectHelper : CodegenBase - { - public override bool ImportReferences() - { - return true; - } - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/PredictedObjectHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/PredictedObjectHelper.cs.meta deleted file mode 100644 index ff446ca..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/PredictedObjectHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e9a06c812bf785a44a38a5852ff866d8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/ReaderGenerator.cs b/Assets/FishNet/CodeGenerating/Helpers/ReaderGenerator.cs deleted file mode 100644 index c42cb5a..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/ReaderGenerator.cs +++ /dev/null @@ -1 +0,0 @@ -//Remove on 2024/01/01 \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/ReaderGenerator.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/ReaderGenerator.cs.meta deleted file mode 100644 index 9ff807d..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/ReaderGenerator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a8afc0f62ceeaee45aa496ba5650d010 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/ReaderHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/ReaderHelper.cs deleted file mode 100644 index c42cb5a..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/ReaderHelper.cs +++ /dev/null @@ -1 +0,0 @@ -//Remove on 2024/01/01 \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/ReaderHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/ReaderHelper.cs.meta deleted file mode 100644 index 00c2968..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/ReaderHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 07c42037569e53b4aa6701adefd3e063 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/ReaderImports.cs b/Assets/FishNet/CodeGenerating/Helpers/ReaderImports.cs deleted file mode 100644 index 4fe91b8..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/ReaderImports.cs +++ /dev/null @@ -1,71 +0,0 @@ -using FishNet.Connection; -using FishNet.Serializing; -using MonoFN.Cecil; -using System; -using System.Reflection; - -namespace FishNet.CodeGenerating.Helping -{ - internal class ReaderImports : CodegenBase - { - #region Reflection references. - public TypeReference PooledReader_TypeRef; - public TypeReference Reader_TypeRef; - public TypeReference NetworkConnection_TypeRef; - public MethodReference PooledReader_ReadNetworkBehaviour_MethodRef; - public MethodReference Reader_ReadPackedWhole_MethodRef; - public MethodReference Reader_ReadDictionary_MethodRef; - public MethodReference Reader_ReadList_MethodRef; - public MethodReference Reader_ReadListCache_MethodRef; - public MethodReference Reader_ReadArray_MethodRef; - public TypeReference GenericReaderTypeRef; - public TypeReference ReaderTypeRef; - public MethodReference ReadSetMethodRef; - public MethodReference ReadAutoPackSetMethodRef; - #endregion - - /// - /// Imports references needed by this helper. - /// - /// - /// - public override bool ImportReferences() - { - ReaderProcessor rp = base.GetClass(); - - PooledReader_TypeRef = base.ImportReference(typeof(PooledReader)); - Reader_TypeRef = base.ImportReference(typeof(Reader)); - NetworkConnection_TypeRef = base.ImportReference(typeof(NetworkConnection)); - - GenericReaderTypeRef = base.ImportReference(typeof(GenericReader<>)); - ReaderTypeRef = base.ImportReference(typeof(Reader)); - - System.Reflection.PropertyInfo readPropertyInfo; - readPropertyInfo = typeof(GenericReader<>).GetProperty(nameof(GenericReader.Read)); - ReadSetMethodRef = base.ImportReference(readPropertyInfo.GetSetMethod()); - readPropertyInfo = typeof(GenericReader<>).GetProperty(nameof(GenericReader.ReadAutoPack)); - ReadAutoPackSetMethodRef = base.ImportReference(readPropertyInfo.GetSetMethod()); - - - Type pooledReaderType = typeof(PooledReader); - foreach (MethodInfo methodInfo in pooledReaderType.GetMethods()) - { - int parameterCount = methodInfo.GetParameters().Length; - /* Special methods. */ - if (methodInfo.Name == nameof(PooledReader.ReadPackedWhole)) - Reader_ReadPackedWhole_MethodRef = base.ImportReference(methodInfo); - //Relay readers. - else if (parameterCount == 0 && methodInfo.Name == nameof(PooledReader.ReadDictionary)) - Reader_ReadDictionary_MethodRef = base.ImportReference(methodInfo); - else if (parameterCount == 0 && methodInfo.Name == nameof(PooledReader.ReadListAllocated)) - Reader_ReadList_MethodRef = base.ImportReference(methodInfo); - else if (parameterCount == 0 && methodInfo.Name == nameof(PooledReader.ReadListCacheAllocated)) - Reader_ReadListCache_MethodRef = base.ImportReference(methodInfo); - else if (parameterCount == 0 && methodInfo.Name == nameof(PooledReader.ReadArrayAllocated)) - Reader_ReadArray_MethodRef = base.ImportReference(methodInfo); - } - - return true; - } - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/ReaderImports.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/ReaderImports.cs.meta deleted file mode 100644 index e491410..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/ReaderImports.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 350861dcbcbabc447acd37e4310b0697 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/TimeManagerHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/TimeManagerHelper.cs deleted file mode 100644 index 21f2106..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/TimeManagerHelper.cs +++ /dev/null @@ -1,22 +0,0 @@ -using FishNet.Managing.Timing; -using MonoFN.Cecil; -using System; -using UnityEngine; - -namespace FishNet.CodeGenerating.Helping -{ - - internal class TimeManagerHelper : CodegenBase - { - - #region Reflection references. - #endregion - - public override bool ImportReferences() - { - return true; - } - - - } -} diff --git a/Assets/FishNet/CodeGenerating/Helpers/TimeManagerHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/TimeManagerHelper.cs.meta deleted file mode 100644 index a247b73..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/TimeManagerHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 11dbcc0798e079e4a85fe98dfc9fe23a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/TransportHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/TransportHelper.cs deleted file mode 100644 index 4816ab4..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/TransportHelper.cs +++ /dev/null @@ -1,36 +0,0 @@ -using FishNet.Transporting; -using MonoFN.Cecil; - -namespace FishNet.CodeGenerating.Helping -{ - internal class TransportHelper : CodegenBase - { - #region Reflection references. - internal TypeReference Channel_TypeRef; - #endregion - - /// - /// Resets cached values. - /// - private void ResetValues() - { - Channel_TypeRef = null; - } - - - /// - /// Imports references needed by this helper. - /// - /// - /// - public override bool ImportReferences() - { - ResetValues(); - - Channel_TypeRef = base.ImportReference(typeof(Channel)); - - return true; - } - - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/TransportHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/TransportHelper.cs.meta deleted file mode 100644 index 9821f2c..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/TransportHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6ced44bfdb3068f4cb7513c9be85729a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed.meta b/Assets/FishNet/CodeGenerating/Helpers/Typed.meta deleted file mode 100644 index f51ce71..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 192c16e1ad7eca84cbcc19073c945ca9 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed/Comparers.cs b/Assets/FishNet/CodeGenerating/Helpers/Typed/Comparers.cs deleted file mode 100644 index 429a0d4..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed/Comparers.cs +++ /dev/null @@ -1,34 +0,0 @@ -using MonoFN.Cecil; -using System.Collections.Generic; - -namespace FishNet.CodeGenerating.Helping -{ - internal class TypeDefinitionComparer : IEqualityComparer - { - public bool Equals(TypeDefinition a, TypeDefinition b) - { - return a.FullName == b.FullName; - } - - public int GetHashCode(TypeDefinition obj) - { - return obj.FullName.GetHashCode(); - } - } - - - internal class TypeReferenceComparer : IEqualityComparer - { - public bool Equals(TypeReference a, TypeReference b) - { - return a.FullName == b.FullName; - } - - public int GetHashCode(TypeReference obj) - { - return obj.FullName.GetHashCode(); - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed/Comparers.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Typed/Comparers.cs.meta deleted file mode 100644 index dff182e..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed/Comparers.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2b30600f0fdb27c4fb86c310b08f43b5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed/CreatedSyncType.cs b/Assets/FishNet/CodeGenerating/Helpers/Typed/CreatedSyncType.cs deleted file mode 100644 index c6cf9a0..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed/CreatedSyncType.cs +++ /dev/null @@ -1,49 +0,0 @@ -using MonoFN.Cecil; - -namespace FishNet.CodeGenerating.Helping -{ - - - - internal class CreatedSyncVar - { - public readonly TypeDefinition VariableTd; - public readonly MethodReference GetValueMr; - public readonly MethodReference SetValueMr; - public readonly MethodReference SetSyncIndexMr; - public readonly MethodReference ConstructorMr; - public readonly GenericInstanceType SyncVarGit; - public MethodReference HookMr; - public CreatedSyncVar(GenericInstanceType syncVarGit, TypeDefinition variableTd, MethodReference getValueMr, MethodReference setValueMr, MethodReference setSyncIndexMr,MethodReference hookMr, MethodReference constructorMr) - { - SyncVarGit = syncVarGit; - VariableTd = variableTd; - GetValueMr = getValueMr; - SetValueMr = setValueMr; - SetSyncIndexMr = setSyncIndexMr; - HookMr = hookMr; - ConstructorMr = constructorMr; - } - } - - - internal class CreatedSyncType - { - public TypeDefinition StubClassTypeDefinition; - public MethodReference GetValueMethodReference; - public MethodReference SetValueMethodReference; - public MethodReference GetPreviousClientValueMethodReference; - public MethodReference ReadMethodReference; - public MethodReference ConstructorMethodReference; - public CreatedSyncType(TypeDefinition stubClassTypeDef, MethodReference getMethodRef, MethodReference setMethodRef, MethodReference getPreviousMethodRef, MethodReference readMethodRef, MethodReference constructorMethodRef) - { - StubClassTypeDefinition = stubClassTypeDef; - GetValueMethodReference = getMethodRef; - SetValueMethodReference = setMethodRef; - GetPreviousClientValueMethodReference = getPreviousMethodRef; - ReadMethodReference = readMethodRef; - ConstructorMethodReference = constructorMethodRef; - } - } - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed/CreatedSyncType.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Typed/CreatedSyncType.cs.meta deleted file mode 100644 index 2a0abc7..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed/CreatedSyncType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0cae698c9bc732641892caabf04365dc -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed/GeneratorHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/Typed/GeneratorHelper.cs deleted file mode 100644 index 778f6c9..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed/GeneratorHelper.cs +++ /dev/null @@ -1,190 +0,0 @@ -using FishNet.CodeGenerating.Extension; -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.Object; -using FishNet.Serializing.Helping; -using FishNet.Utility.Performance; -using MonoFN.Cecil; -using System.Collections.Generic; - -namespace FishNet.CodeGenerating.Helping -{ - - - internal class GeneratorHelper : CodegenBase - { - /// - /// Gets what objectTypeRef will be serialized as. - /// - public SerializerType GetSerializerType(TypeReference objectTr, bool writer, out TypeDefinition objectTd) - { - string errorPrefix = (writer) ? "CreateWrite: " : "CreateRead: "; - objectTd = null; - - /* Check if already has a serializer. */ - if (writer) - { - if (base.GetClass().GetWriteMethodReference(objectTr) != null) - { - base.LogError($"Writer already exist for {objectTr.FullName}."); - return SerializerType.Invalid; - } - } - else - { - if (base.GetClass().GetReadMethodReference(objectTr) != null) - { - base.LogError($"Reader already exist for {objectTr.FullName}."); - return SerializerType.Invalid; - } - } - - objectTd = objectTr.CachedResolve(base.Session); - //Invalid typeDef. - if (objectTd == null) - { - base.LogError($"{errorPrefix}{objectTd.FullName} could not be resolved."); - return SerializerType.Invalid; - } - //Intentionally excluded. - if (objectTd.CustomAttributes.Count > 0) - { - foreach (CustomAttribute item in objectTd.CustomAttributes) - { - if (item.AttributeType.Is(typeof(CodegenExcludeAttribute))) - return SerializerType.Invalid; - } - } - - //By reference. - if (objectTr.IsByReference) - { - base.LogError($"{errorPrefix}Cannot pass {objectTr.Name} by reference"); - return SerializerType.Invalid; - } - /* Arrays have to be processed first because it's possible for them to meet other conditions - * below and be processed wrong. */ - else if (objectTr.IsArray) - { - if (objectTr.IsMultidimensionalArray()) - { - base.LogError($"{errorPrefix}{objectTr.Name} is an unsupported type. Multidimensional arrays are not supported"); - return SerializerType.Invalid; - } - else - { - return SerializerType.Array; - } - } - //Enum. - else if (objectTd.IsEnum) - { - return SerializerType.Enum; - } - else if (objectTd.Is(typeof(Dictionary<,>))) - { - return SerializerType.Dictionary; - } - else if (objectTd.Is(typeof(List<>))) - { - return SerializerType.List; - } - else if (objectTd.Is(typeof(ListCache<>))) - { - return SerializerType.ListCache; - } - else if (objectTd.InheritsFrom(base.Session)) - { - return SerializerType.NetworkBehaviour; - } - else if (objectTr.IsNullable(base.Session)) - { - GenericInstanceType git = objectTr as GenericInstanceType; - if (git == null || git.GenericArguments.Count != 1) - return SerializerType.Invalid; - else - return SerializerType.Nullable; - } - //Invalid type. This must be called after trying to generate everything but class. - else if (!CanGenerateSerializer(objectTd)) - { - return SerializerType.Invalid; - } - //If here then the only type left is struct or class. - else if (objectTr.IsClassOrStruct(base.Session)) - { - return SerializerType.ClassOrStruct; - } - //Unknown type. - else - { - base.LogError($"{errorPrefix}{objectTr.Name} is an unsupported type. Mostly because we don't know what the heck it is. Please let us know so we can fix this."); - return SerializerType.Invalid; - } - } - - - /// - /// Returns if objectTd can have a serializer generated for it. - /// - private bool CanGenerateSerializer(TypeDefinition objectTd) - { - string errorText = $"{objectTd.Name} is not a supported type. Use a supported type or provide a custom serializer"; - - System.Type unityObjectType = typeof(UnityEngine.Object); - //Unable to determine type, cannot generate for. - if (objectTd == null) - { - base.LogError(errorText); - return false; - } - //Component. - if (objectTd.InheritsFrom(base.Session)) - { - base.LogError(errorText); - return false; - } - //Unity Object. - if (objectTd.Is(unityObjectType)) - { - base.LogError(errorText); - return false; - } - //ScriptableObject. - if (objectTd.Is(typeof(UnityEngine.ScriptableObject))) - { - base.LogError(errorText); - return false; - } - //Has generic parameters. - if (objectTd.HasGenericParameters) - { - base.LogError(errorText); - return false; - } - //Is an interface. - if (objectTd.IsInterface) - { - base.LogError(errorText); - return false; - } - //Is abstract. - if (objectTd.IsAbstract) - { - base.LogError(errorText); - return false; - } - if (objectTd.InheritsFrom(base.Session, unityObjectType) && objectTd.IsExcluded(GeneralHelper.UNITYENGINE_ASSEMBLY_PREFIX)) - { - base.LogError(errorText); - return false; - } - - //If here type is valid. - return true; - } - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed/GeneratorHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Typed/GeneratorHelper.cs.meta deleted file mode 100644 index bf4c3fa..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed/GeneratorHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9b1882eac63e3d94aad8f41915bc1ab8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed/QOLAttributeType.cs b/Assets/FishNet/CodeGenerating/Helpers/Typed/QOLAttributeType.cs deleted file mode 100644 index 314c3d2..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed/QOLAttributeType.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace FishNet.CodeGenerating.Helping -{ - - internal enum QolAttributeType - { - None, - Server, - Client - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed/QOLAttributeType.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Typed/QOLAttributeType.cs.meta deleted file mode 100644 index f6a473d..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed/QOLAttributeType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 357a22940018b8e49976e13272c5b2ef -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed/SerializatierType.cs b/Assets/FishNet/CodeGenerating/Helpers/Typed/SerializatierType.cs deleted file mode 100644 index 17b7a7a..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed/SerializatierType.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace FishNet.CodeGenerating.Helping -{ - - internal enum SerializerType - { - Invalid, - Enum, - Array, - List, - ListCache, - NetworkBehaviour, - ClassOrStruct, - Nullable, - Dictionary, - Null, - ByReference, - MultiDimensionalArray - } - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed/SerializatierType.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Typed/SerializatierType.cs.meta deleted file mode 100644 index a993edc..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed/SerializatierType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e7f1bbf5c398c3e4e92e53ec3e49d5e9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed/SyncIndexData.cs b/Assets/FishNet/CodeGenerating/Helpers/Typed/SyncIndexData.cs deleted file mode 100644 index ecede30..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed/SyncIndexData.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MonoFN.Cecil.Cil; -using System.Collections.Generic; - -namespace FishNet.CodeGenerating.Helping -{ - - /// - /// Data used to modify an RpcIndex should the class have to be rebuilt. - /// - internal class SyncIndexData - { - public uint SyncCount = 0; - public List DelegateInstructions = new List(); - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed/SyncIndexData.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Typed/SyncIndexData.cs.meta deleted file mode 100644 index a2adbd2..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed/SyncIndexData.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 55f2e751e4788464b8394f6b8bdb548a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed/SyncType.cs b/Assets/FishNet/CodeGenerating/Helpers/Typed/SyncType.cs deleted file mode 100644 index c5dd521..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed/SyncType.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace FishNet.CodeGenerating.Helping -{ - - public enum SyncType - { - Unset, - Variable, - List, - Dictionary, - HashSet, - Custom - } - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/Typed/SyncType.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/Typed/SyncType.cs.meta deleted file mode 100644 index b60f670..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/Typed/SyncType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 44c753d6ac0c7864c9962d91703b2afe -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/WriterGenerator.cs b/Assets/FishNet/CodeGenerating/Helpers/WriterGenerator.cs deleted file mode 100644 index c42cb5a..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/WriterGenerator.cs +++ /dev/null @@ -1 +0,0 @@ -//Remove on 2024/01/01 \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/WriterGenerator.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/WriterGenerator.cs.meta deleted file mode 100644 index 06dad80..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/WriterGenerator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a4ff3023050c3ee41b59523def204ac8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/WriterHelper.cs b/Assets/FishNet/CodeGenerating/Helpers/WriterHelper.cs deleted file mode 100644 index c42cb5a..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/WriterHelper.cs +++ /dev/null @@ -1 +0,0 @@ -//Remove on 2024/01/01 \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/WriterHelper.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/WriterHelper.cs.meta deleted file mode 100644 index 33a47e1..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/WriterHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2bbdbcfc675aaff469cadbee89f49c12 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Helpers/WriterImports.cs b/Assets/FishNet/CodeGenerating/Helpers/WriterImports.cs deleted file mode 100644 index 5a40872..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/WriterImports.cs +++ /dev/null @@ -1,100 +0,0 @@ -using FishNet.Object; -using FishNet.Serializing; -using MonoFN.Cecil; -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace FishNet.CodeGenerating.Helping -{ - internal class WriterImports : CodegenBase - { - #region Reflection references. - public MethodReference WriterPool_GetWriter_MethodRef; - public MethodReference WriterPool_GetWriterLength_MethodRef; - public MethodReference Writer_WritePackedWhole_MethodRef; - public TypeReference PooledWriter_TypeRef; - public TypeReference Writer_TypeRef; - public MethodReference PooledWriter_Dispose_MethodRef; - public MethodReference Writer_WriteDictionary_MethodRef; - public MethodReference Writer_WriteList_MethodRef; - public MethodReference Writer_WriteListCache_MethodRef; - public MethodReference Writer_WriteArray_MethodRef; - public TypeReference AutoPackTypeRef; - - public TypeReference GenericWriterTypeRef; - public TypeReference WriterTypeRef; - public MethodReference WriteGetSetMethodRef; - public MethodReference WriteAutoPackGetSetMethodRef; - #endregion - - /// - /// Imports references needed by this helper. - /// - /// - /// - public override bool ImportReferences() - { - PooledWriter_TypeRef = base.ImportReference(typeof(PooledWriter)); - Writer_TypeRef = base.ImportReference(typeof(Writer)); - AutoPackTypeRef = base.ImportReference(typeof(AutoPackType)); - - GenericWriterTypeRef = base.ImportReference(typeof(GenericWriter<>)); - WriterTypeRef = base.ImportReference(typeof(Writer)); - - PropertyInfo writePropertyInfo; - writePropertyInfo = typeof(GenericWriter<>).GetProperty(nameof(GenericWriter.Write)); - WriteGetSetMethodRef = base.ImportReference(writePropertyInfo.GetSetMethod()); - writePropertyInfo = typeof(GenericWriter<>).GetProperty(nameof(GenericWriter.WriteAutoPack)); - WriteAutoPackGetSetMethodRef = base.ImportReference(writePropertyInfo.GetSetMethod()); - - //WriterPool.GetWriter - Type writerPoolType = typeof(WriterPool); - base.ImportReference(writerPoolType); - foreach (var methodInfo in writerPoolType.GetMethods()) - { - if (methodInfo.Name == nameof(WriterPool.GetWriter)) - { - //GetWriter(). - if (methodInfo.GetParameters().Length == 0) - { - WriterPool_GetWriter_MethodRef = base.ImportReference(methodInfo); - } - //GetWriter(?). - else if (methodInfo.GetParameters().Length == 1) - { - ParameterInfo pi = methodInfo.GetParameters()[0]; - //GetWriter(int). - if (pi.ParameterType == typeof(int)) - WriterPool_GetWriterLength_MethodRef = base.ImportReference(methodInfo); - } - } - } - - WriterProcessor gwh = base.GetClass(); - Type pooledWriterType = typeof(PooledWriter); - foreach (MethodInfo methodInfo in pooledWriterType.GetMethods()) - { - int parameterCount = methodInfo.GetParameters().Length; - - if (methodInfo.Name == nameof(PooledWriter.Dispose)) - PooledWriter_Dispose_MethodRef = base.ImportReference(methodInfo); - else if (methodInfo.Name == nameof(PooledWriter.WritePackedWhole)) - Writer_WritePackedWhole_MethodRef = base.ImportReference(methodInfo); - //Relay writers. - else if (parameterCount == 1 && methodInfo.Name == nameof(PooledWriter.WriteDictionary)) - Writer_WriteDictionary_MethodRef = base.ImportReference(methodInfo); - else if (parameterCount == 1 && methodInfo.Name == nameof(PooledWriter.WriteList)) - Writer_WriteList_MethodRef = base.ImportReference(methodInfo); - else if (parameterCount == 1 && methodInfo.Name == nameof(PooledWriter.WriteListCache)) - Writer_WriteListCache_MethodRef = base.ImportReference(methodInfo); - else if (parameterCount == 1 && methodInfo.Name == nameof(PooledWriter.WriteArray)) - Writer_WriteArray_MethodRef = base.ImportReference(methodInfo); - } - - return true; - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Helpers/WriterImports.cs.meta b/Assets/FishNet/CodeGenerating/Helpers/WriterImports.cs.meta deleted file mode 100644 index 43c69fa..0000000 --- a/Assets/FishNet/CodeGenerating/Helpers/WriterImports.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 425638e29bab6f1488e8865c9e3f8b57 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/ILCore.meta b/Assets/FishNet/CodeGenerating/ILCore.meta deleted file mode 100644 index 8040bd1..0000000 --- a/Assets/FishNet/CodeGenerating/ILCore.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: abe522a1ad3df3a43a5c3389e3b8ee89 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/ILCore/FishNetILPP.cs b/Assets/FishNet/CodeGenerating/ILCore/FishNetILPP.cs deleted file mode 100644 index 46528b1..0000000 --- a/Assets/FishNet/CodeGenerating/ILCore/FishNetILPP.cs +++ /dev/null @@ -1,505 +0,0 @@ -using FishNet.Broadcast; -using FishNet.CodeGenerating.Extension; -using FishNet.CodeGenerating.Helping; -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.CodeGenerating.Processing; -using FishNet.CodeGenerating.Processing.Rpc; -using FishNet.Configuring; -using FishNet.Serializing.Helping; -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using Unity.CompilationPipeline.Common.ILPostProcessing; - -namespace FishNet.CodeGenerating.ILCore -{ - public class FishNetILPP : ILPostProcessor - { - #region Const. - internal const string RUNTIME_ASSEMBLY_NAME = "FishNet.Runtime"; - #endregion - - public override bool WillProcess(ICompiledAssembly compiledAssembly) - { - if (compiledAssembly.Name.StartsWith("Unity.")) - return false; - if (compiledAssembly.Name.StartsWith("UnityEngine.")) - return false; - if (compiledAssembly.Name.StartsWith("UnityEditor.")) - return false; - if (compiledAssembly.Name.Contains("Editor")) - return false; - - /* This line contradicts the one below where referencesFishNet - * becomes true if the assembly is FishNetAssembly. This is here - * intentionally to stop codegen from running on the runtime - * fishnet assembly, but the option below is for debugging. I would - * comment out this check if I wanted to compile fishnet runtime. */ - //if (CODEGEN_THIS_NAMESPACE.Length == 0) - //{ - // if (compiledAssembly.Name == RUNTIME_ASSEMBLY_NAME) - // return false; - //} - bool referencesFishNet = FishNetILPP.IsFishNetAssembly(compiledAssembly) || compiledAssembly.References.Any(filePath => Path.GetFileNameWithoutExtension(filePath) == RUNTIME_ASSEMBLY_NAME); - return referencesFishNet; - } - public override ILPostProcessor GetInstance() => this; - - public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly) - { - AssemblyDefinition assemblyDef = ILCoreHelper.GetAssemblyDefinition(compiledAssembly); - if (assemblyDef == null) - return null; - - //Check WillProcess again; somehow certain editor scripts skip the WillProcess check. - if (!WillProcess(compiledAssembly)) - return null; - - CodegenSession session = new CodegenSession(); - if (!session.Initialize(assemblyDef.MainModule)) - return null; - - bool modified = false; - - bool fnAssembly = IsFishNetAssembly(compiledAssembly); - if (fnAssembly) - modified |= ModifyMakePublicMethods(session); - /* If one or more scripts use RPCs but don't inherit NetworkBehaviours - * then don't bother processing the rest. */ - if (session.GetClass().NonNetworkBehaviourHasInvalidAttributes(session.Module.Types)) - return new ILPostProcessResult(null, session.Diagnostics); - - modified |= session.GetClass().Process(); - modified |= session.GetClass().Process(); - modified |= CreateDeclaredSerializerDelegates(session); - modified |= CreateDeclaredSerializers(session); - modified |= CreateDeclaredComparerDelegates(session); - modified |= CreateIBroadcast(session); - modified |= CreateQOLAttributes(session); - modified |= CreateNetworkBehaviours(session); - modified |= CreateGenericReadWriteDelegates(session); - - if (fnAssembly) - { - AssemblyNameReference anr = session.Module.AssemblyReferences.FirstOrDefault(x => x.FullName == session.Module.Assembly.FullName); - if (anr != null) - session.Module.AssemblyReferences.Remove(anr); - } - - /* If there are warnings about SyncVars being in different assemblies. - * This is awful ... codegen would need to be reworked to save - * syncvars across all assemblies so that scripts referencing them from - * another assembly can have it's instructions changed. This however is an immense - * amount of work so it will have to be put on hold, for... a long.. long while. */ - if (session.DifferentAssemblySyncVars.Count > 0) - { - StringBuilder sb = new StringBuilder(); - sb.AppendLine($"Assembly {session.Module.Name} has inherited access to SyncVars in different assemblies. When accessing SyncVars across assemblies be sure to use Get/Set methods withinin the inherited assembly script to change SyncVars. Accessible fields are:"); - - foreach (FieldDefinition item in session.DifferentAssemblySyncVars) - sb.AppendLine($"Field {item.Name} within {item.DeclaringType.FullName} in assembly {item.Module.Name}."); - - session.LogWarning("v------- IMPORTANT -------v"); - session.LogWarning(sb.ToString()); - session.DifferentAssemblySyncVars.Clear(); - } - - //session.LogWarning($"Assembly {compiledAssembly.Name} took {stopwatch.ElapsedMilliseconds}."); - if (!modified) - { - return null; - } - else - { - MemoryStream pe = new MemoryStream(); - MemoryStream pdb = new MemoryStream(); - WriterParameters writerParameters = new WriterParameters - { - SymbolWriterProvider = new PortablePdbWriterProvider(), - SymbolStream = pdb, - WriteSymbols = true - }; - assemblyDef.Write(pe, writerParameters); - return new ILPostProcessResult(new InMemoryAssembly(pe.ToArray(), pdb.ToArray()), session.Diagnostics); - } - } - - /// - /// Makees methods public scope which use CodegenMakePublic attribute. - /// - /// - private bool ModifyMakePublicMethods(CodegenSession session) - { - string makePublicTypeFullName = typeof(CodegenMakePublicAttribute).FullName; - foreach (TypeDefinition td in session.Module.Types) - { - foreach (MethodDefinition md in td.Methods) - { - foreach (CustomAttribute ca in md.CustomAttributes) - { - if (ca.AttributeType.FullName == makePublicTypeFullName) - { - md.Attributes &= ~MethodAttributes.Assembly; - md.Attributes |= MethodAttributes.Public; - } - } - } - } - - //There is always at least one modified. - return true; - } - /// - /// Creates delegates for user declared serializers. - /// - internal bool CreateDeclaredSerializerDelegates(CodegenSession session) - { - bool modified = false; - - TypeAttributes readWriteExtensionTypeAttr = (TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract); - List allTypeDefs = session.Module.Types.ToList(); - foreach (TypeDefinition td in allTypeDefs) - { - if (session.GetClass().IgnoreTypeDefinition(td)) - continue; - - if (td.Attributes.HasFlag(readWriteExtensionTypeAttr)) - modified |= session.GetClass().CreateSerializerDelegates(td, true); - } - - return modified; - } - - /// - /// Creates serializers for custom types within user declared serializers. - /// - private bool CreateDeclaredSerializers(CodegenSession session) - { - bool modified = false; - - TypeAttributes readWriteExtensionTypeAttr = (TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract); - List allTypeDefs = session.Module.Types.ToList(); - foreach (TypeDefinition td in allTypeDefs) - { - if (session.GetClass().IgnoreTypeDefinition(td)) - continue; - - if (td.Attributes.HasFlag(readWriteExtensionTypeAttr)) - modified |= session.GetClass().CreateSerializers(td); - } - - return modified; - } - - /// - /// Creates delegates for user declared comparers. - /// - internal bool CreateDeclaredComparerDelegates(CodegenSession session) - { - bool modified = false; - List allTypeDefs = session.Module.Types.ToList(); - foreach (TypeDefinition td in allTypeDefs) - { - if (session.GetClass().IgnoreTypeDefinition(td)) - continue; - - modified |= session.GetClass().CreateComparerDelegates(td); - } - - return modified; - } - - - /// - /// Creaters serializers and calls for IBroadcast. - /// - /// - /// - private bool CreateIBroadcast(CodegenSession session) - { - bool modified = false; - - string networkBehaviourFullName = session.GetClass().FullName; - HashSet typeDefs = new HashSet(); - foreach (TypeDefinition td in session.Module.Types) - { - TypeDefinition climbTd = td; - do - { - //Reached NetworkBehaviour class. - if (climbTd.FullName == networkBehaviourFullName) - break; - - ///* Check initial class as well all types within - // * the class. Then check all of it's base classes. */ - if (climbTd.ImplementsInterface()) - typeDefs.Add(climbTd); - //7ms - - //Add nested. Only going to go a single layer deep. - foreach (TypeDefinition nestedTypeDef in td.NestedTypes) - { - if (nestedTypeDef.ImplementsInterface()) - typeDefs.Add(nestedTypeDef); - } - //0ms - - climbTd = climbTd.GetNextBaseTypeDefinition(session); - //this + name check 40ms - } while (climbTd != null); - - } - - - //Create reader/writers for found typeDefs. - foreach (TypeDefinition td in typeDefs) - { - TypeReference typeRef = session.ImportReference(td); - bool canSerialize = session.GetClass().HasSerializerAndDeserializer(typeRef, true); - if (!canSerialize) - session.LogError($"Broadcast {td.Name} does not support serialization. Use a supported type or create a custom serializer."); - else - modified = true; - } - - return modified; - } - - /// - /// Handles QOLAttributes such as [Server]. - /// - /// - private bool CreateQOLAttributes(CodegenSession session) - { - bool modified = false; - - bool codeStripping = false; - - List allTypeDefs = session.Module.Types.ToList(); - - /* First pass, potentially only pass. - * If code stripping them this will be run again. The first iteration - * is to ensure things are removed in the proper order. */ - foreach (TypeDefinition td in allTypeDefs) - { - if (session.GetClass().IgnoreTypeDefinition(td)) - continue; - - modified |= session.GetClass().Process(td, codeStripping); - } - - - - return modified; - } - - /// - /// Creates NetworkBehaviour changes. - /// - /// - /// - private bool CreateNetworkBehaviours(CodegenSession session) - { - bool modified = false; - //Get all network behaviours to process. - List networkBehaviourTypeDefs = session.Module.Types - .Where(td => td.IsSubclassOf(session, session.GetClass().FullName)) - .ToList(); - - //Moment a NetworkBehaviour exist the assembly is considered modified. - if (networkBehaviourTypeDefs.Count > 0) - modified = true; - - /* Remove types which are inherited. This gets the child most networkbehaviours. - * Since processing iterates all parent classes there's no reason to include them */ - RemoveInheritedTypeDefinitions(networkBehaviourTypeDefs); - //Set how many rpcs are in children classes for each typedef. - Dictionary inheritedRpcCounts = new Dictionary(); - SetChildRpcCounts(inheritedRpcCounts, networkBehaviourTypeDefs); - //Set how many synctypes are in children classes for each typedef. - Dictionary inheritedSyncTypeCounts = new Dictionary(); - SetChildSyncTypeCounts(inheritedSyncTypeCounts, networkBehaviourTypeDefs); - - /* This holds all sync types created, synclist, dictionary, var - * and so on. This data is used after all syncvars are made so - * other methods can look for references to created synctypes and - * replace accessors accordingly. */ - List<(SyncType, ProcessedSync)> allProcessedSyncs = new List<(SyncType, ProcessedSync)>(); - HashSet allProcessedCallbacks = new HashSet(); - List processedClasses = new List(); - - foreach (TypeDefinition typeDef in networkBehaviourTypeDefs) - { - session.ImportReference(typeDef); - //Synctypes processed for this nb and it's inherited classes. - List<(SyncType, ProcessedSync)> processedSyncs = new List<(SyncType, ProcessedSync)>(); - session.GetClass().Process(typeDef, processedSyncs, - inheritedSyncTypeCounts, inheritedRpcCounts); - //Add to all processed. - allProcessedSyncs.AddRange(processedSyncs); - } - - /* Must run through all scripts should user change syncvar - * from outside the networkbehaviour. */ - if (allProcessedSyncs.Count > 0) - { - foreach (TypeDefinition td in session.Module.Types) - { - session.GetClass().ReplaceGetSets(td, allProcessedSyncs); - session.GetClass().RedirectBaseCalls(); - } - } - - /* Removes typedefinitions which are inherited by - * another within tds. For example, if the collection - * td contains A, B, C and our structure is - * A : B : C then B and C will be removed from the collection - * Since they are both inherited by A. */ - void RemoveInheritedTypeDefinitions(List tds) - { - HashSet inheritedTds = new HashSet(); - /* Remove any networkbehaviour typedefs which are inherited by - * another networkbehaviour typedef. When a networkbehaviour typedef - * is processed so are all of the inherited types. */ - for (int i = 0; i < tds.Count; i++) - { - /* Iterates all base types and - * adds them to inheritedTds so long - * as the base type is not a NetworkBehaviour. */ - TypeDefinition copyTd = tds[i].GetNextBaseTypeDefinition(session); - while (copyTd != null) - { - //Class is NB. - if (copyTd.FullName == session.GetClass().FullName) - break; - - inheritedTds.Add(copyTd); - copyTd = copyTd.GetNextBaseTypeDefinition(session); - } - } - - //Remove all inherited types. - foreach (TypeDefinition item in inheritedTds) - tds.Remove(item); - } - - /* Sets how many Rpcs are within the children - * of each typedefinition. EG: if our structure is - * A : B : C, with the following RPC counts... - * A 3 - * B 1 - * C 2 - * then B child rpc counts will be 3, and C will be 4. */ - void SetChildRpcCounts(Dictionary typeDefCounts, List tds) - { - foreach (TypeDefinition typeDef in tds) - { - //Number of RPCs found while climbing typeDef. - uint childCount = 0; - - TypeDefinition copyTd = typeDef; - do - { - //How many RPCs are in copyTd. - uint copyCount = session.GetClass().GetRpcCount(copyTd); - - /* If not found it this is the first time being - * processed. When this occurs set the value - * to 0. It will be overwritten below if baseCount - * is higher. */ - uint previousCopyChildCount = 0; - if (!typeDefCounts.TryGetValue(copyTd, out previousCopyChildCount)) - typeDefCounts[copyTd] = 0; - /* If baseCount is higher then replace count for copyTd. - * This can occur when a class is inherited by several types - * and the first processed type might only have 1 rpc, while - * the next has 2. This could be better optimized but to keep - * the code easier to read, it will stay like this. */ - if (childCount > previousCopyChildCount) - typeDefCounts[copyTd] = childCount; - - //Increase baseCount with RPCs found here. - childCount += copyCount; - - copyTd = copyTd.GetNextBaseClassToProcess(session); - } while (copyTd != null); - } - - } - - - /* This performs the same functionality as SetChildRpcCounts - * but for SyncTypes. */ - void SetChildSyncTypeCounts(Dictionary typeDefCounts, List tds) - { - foreach (TypeDefinition typeDef in tds) - { - //Number of RPCs found while climbing typeDef. - uint childCount = 0; - - TypeDefinition copyTd = typeDef; - /* Iterate up to the parent script and then reverse - * the order. This is so that the topmost is 0 - * and each inerhiting script adds onto that. - * Setting child types this way makes it so parent - * types don't need to have their synctype/rpc counts - * rebuilt when scripts are later to be found - * inheriting from them. */ - List reversedTypeDefs = new List(); - do - { - reversedTypeDefs.Add(copyTd); - copyTd = copyTd.GetNextBaseClassToProcess(session); - } while (copyTd != null); - reversedTypeDefs.Reverse(); - - foreach (TypeDefinition td in reversedTypeDefs) - { - //How many RPCs are in copyTd. - uint copyCount = session.GetClass().GetSyncTypeCount(td); - /* If not found it this is the first time being - * processed. When this occurs set the value - * to 0. It will be overwritten below if baseCount - * is higher. */ - uint previousCopyChildCount = 0; - if (!typeDefCounts.TryGetValue(td, out previousCopyChildCount)) - typeDefCounts[td] = 0; - /* If baseCount is higher then replace count for copyTd. - * This can occur when a class is inherited by several types - * and the first processed type might only have 1 rpc, while - * the next has 2. This could be better optimized but to keep - * the code easier to read, it will stay like this. */ - if (childCount > previousCopyChildCount) - typeDefCounts[td] = childCount; - //Increase baseCount with RPCs found here. - childCount += copyCount; - } - } - } - - - return modified; - } - - /// - /// Creates generic delegates for all read and write methods. - /// - /// - /// - private bool CreateGenericReadWriteDelegates(CodegenSession session) - { - session.GetClass().CreateStaticMethodDelegates(); - session.GetClass().CreateStaticMethodDelegates(); - - return true; - } - - internal static bool IsFishNetAssembly(ICompiledAssembly assembly) => (assembly.Name == FishNetILPP.RUNTIME_ASSEMBLY_NAME); - internal static bool IsFishNetAssembly(CodegenSession session) => (session.Module.Assembly.Name.Name == FishNetILPP.RUNTIME_ASSEMBLY_NAME); - internal static bool IsFishNetAssembly(ModuleDefinition moduleDef) => (moduleDef.Assembly.Name.Name == FishNetILPP.RUNTIME_ASSEMBLY_NAME); - - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/ILCore/FishNetILPP.cs.meta b/Assets/FishNet/CodeGenerating/ILCore/FishNetILPP.cs.meta deleted file mode 100644 index 38eb26f..0000000 --- a/Assets/FishNet/CodeGenerating/ILCore/FishNetILPP.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f03d76b376c1d5b4591039af6fd4c9e0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/ILCore/ILCoreHelper.cs b/Assets/FishNet/CodeGenerating/ILCore/ILCoreHelper.cs deleted file mode 100644 index 054dc56..0000000 --- a/Assets/FishNet/CodeGenerating/ILCore/ILCoreHelper.cs +++ /dev/null @@ -1,38 +0,0 @@ -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using System.IO; -using Unity.CompilationPipeline.Common.ILPostProcessing; - -namespace FishNet.CodeGenerating.ILCore -{ - internal static class ILCoreHelper - { - - /// - /// Returns AssembleDefinition for compiledAssembly. - /// - /// - /// - internal static AssemblyDefinition GetAssemblyDefinition(ICompiledAssembly compiledAssembly) - { - PostProcessorAssemblyResolver assemblyResolver = new PostProcessorAssemblyResolver(compiledAssembly); - ReaderParameters readerParameters = new ReaderParameters - { - SymbolStream = new MemoryStream(compiledAssembly.InMemoryAssembly.PdbData), - SymbolReaderProvider = new PortablePdbReaderProvider(), - AssemblyResolver = assemblyResolver, - ReflectionImporterProvider = new PostProcessorReflectionImporterProvider(), - ReadingMode = ReadingMode.Immediate - }; - - AssemblyDefinition assemblyDefinition = AssemblyDefinition.ReadAssembly(new MemoryStream(compiledAssembly.InMemoryAssembly.PeData), readerParameters); - //Allows us to resolve inside FishNet assembly, such as for components. - assemblyResolver.AddAssemblyDefinitionBeingOperatedOn(assemblyDefinition); - - return assemblyDefinition; - } - - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/ILCore/ILCoreHelper.cs.meta b/Assets/FishNet/CodeGenerating/ILCore/ILCoreHelper.cs.meta deleted file mode 100644 index 63a163d..0000000 --- a/Assets/FishNet/CodeGenerating/ILCore/ILCoreHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: dfcfb917dd9268744962ae61aa0115b7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/ILCore/PostProcessorAssemblyResolver.cs b/Assets/FishNet/CodeGenerating/ILCore/PostProcessorAssemblyResolver.cs deleted file mode 100644 index 6a9ca63..0000000 --- a/Assets/FishNet/CodeGenerating/ILCore/PostProcessorAssemblyResolver.cs +++ /dev/null @@ -1,139 +0,0 @@ -using MonoFN.Cecil; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using Unity.CompilationPipeline.Common.ILPostProcessing; - -namespace FishNet.CodeGenerating -{ - internal class PostProcessorAssemblyResolver : IAssemblyResolver - { - private readonly string[] m_AssemblyReferences; - private readonly Dictionary m_AssemblyCache = new Dictionary(); - private readonly ICompiledAssembly m_CompiledAssembly; - private AssemblyDefinition m_SelfAssembly; - - public PostProcessorAssemblyResolver(ICompiledAssembly compiledAssembly) - { - m_CompiledAssembly = compiledAssembly; - m_AssemblyReferences = compiledAssembly.References; - } - - public void Dispose() { } - - public AssemblyDefinition Resolve(AssemblyNameReference name) => Resolve(name, new ReaderParameters(ReadingMode.Deferred)); - - public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) - { - lock (m_AssemblyCache) - { - if (name.Name == m_CompiledAssembly.Name) - { - return m_SelfAssembly; - } - - var fileName = FindFile(name); - if (fileName == null) - { - return null; - } - - var lastWriteTime = File.GetLastWriteTime(fileName); - var cacheKey = $"{fileName}{lastWriteTime}"; - if (m_AssemblyCache.TryGetValue(cacheKey, out var result)) - { - return result; - } - - parameters.AssemblyResolver = this; - - var ms = MemoryStreamFor(fileName); - var pdb = $"{fileName}.pdb"; - if (File.Exists(pdb)) - { - parameters.SymbolStream = MemoryStreamFor(pdb); - } - - var assemblyDefinition = AssemblyDefinition.ReadAssembly(ms, parameters); - m_AssemblyCache.Add(cacheKey, assemblyDefinition); - - return assemblyDefinition; - } - } - - private string FindFile(AssemblyNameReference name) - { - var fileName = m_AssemblyReferences.FirstOrDefault(r => Path.GetFileName(r) == $"{name.Name}.dll"); - if (fileName != null) - { - return fileName; - } - - // perhaps the type comes from an exe instead - fileName = m_AssemblyReferences.FirstOrDefault(r => Path.GetFileName(r) == $"{name.Name}.exe"); - if (fileName != null) - { - return fileName; - } - - //Unfortunately the current ICompiledAssembly API only provides direct references. - //It is very much possible that a postprocessor ends up investigating a type in a directly - //referenced assembly, that contains a field that is not in a directly referenced assembly. - //if we don't do anything special for that situation, it will fail to resolve. We should fix this - //in the ILPostProcessing API. As a workaround, we rely on the fact here that the indirect references - //are always located next to direct references, so we search in all directories of direct references we - //got passed, and if we find the file in there, we resolve to it. - return m_AssemblyReferences - .Select(Path.GetDirectoryName) - .Distinct() - .Select(parentDir => Path.Combine(parentDir, $"{name.Name}.dll")) - .FirstOrDefault(File.Exists); - } - - private static MemoryStream MemoryStreamFor(string fileName) - { - return Retry(10, TimeSpan.FromSeconds(1), () => - { - byte[] byteArray; - using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - { - byteArray = new byte[fs.Length]; - var readLength = fs.Read(byteArray, 0, (int)fs.Length); - if (readLength != fs.Length) - { - throw new InvalidOperationException("File read length is not full length of file."); - } - } - - return new MemoryStream(byteArray); - }); - } - - private static MemoryStream Retry(int retryCount, TimeSpan waitTime, Func func) - { - try - { - return func(); - } - catch (IOException) - { - if (retryCount == 0) - { - throw; - } - - Console.WriteLine($"Caught IO Exception, trying {retryCount} more times"); - Thread.Sleep(waitTime); - - return Retry(retryCount - 1, waitTime, func); - } - } - - public void AddAssemblyDefinitionBeingOperatedOn(AssemblyDefinition assemblyDefinition) - { - m_SelfAssembly = assemblyDefinition; - } - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/ILCore/PostProcessorAssemblyResolver.cs.meta b/Assets/FishNet/CodeGenerating/ILCore/PostProcessorAssemblyResolver.cs.meta deleted file mode 100644 index 1a05af5..0000000 --- a/Assets/FishNet/CodeGenerating/ILCore/PostProcessorAssemblyResolver.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2c247f4266b2864eb96e6a9ae6557d31 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporter.cs b/Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporter.cs deleted file mode 100644 index 32b9e8c..0000000 --- a/Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporter.cs +++ /dev/null @@ -1,22 +0,0 @@ -using MonoFN.Cecil; -using System.Linq; -using System.Reflection; - -namespace FishNet.CodeGenerating.ILCore -{ - internal class PostProcessorReflectionImporter : DefaultReflectionImporter - { - private const string k_SystemPrivateCoreLib = "System.Private.CoreLib"; - private readonly AssemblyNameReference m_CorrectCorlib; - - public PostProcessorReflectionImporter(ModuleDefinition module) : base(module) - { - m_CorrectCorlib = module.AssemblyReferences.FirstOrDefault(a => a.Name == "mscorlib" || a.Name == "netstandard" || a.Name == k_SystemPrivateCoreLib); - } - - public override AssemblyNameReference ImportReference(AssemblyName reference) - { - return m_CorrectCorlib != null && reference.Name == k_SystemPrivateCoreLib ? m_CorrectCorlib : base.ImportReference(reference); - } - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporter.cs.meta b/Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporter.cs.meta deleted file mode 100644 index 8dca5f1..0000000 --- a/Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 484e8ad8c4dde382ea67036b32935ef1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporterProvider.cs b/Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporterProvider.cs deleted file mode 100644 index 7d38602..0000000 --- a/Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporterProvider.cs +++ /dev/null @@ -1,12 +0,0 @@ -using MonoFN.Cecil; - -namespace FishNet.CodeGenerating.ILCore -{ - internal class PostProcessorReflectionImporterProvider : IReflectionImporterProvider - { - public IReflectionImporter GetReflectionImporter(ModuleDefinition moduleDef) - { - return new PostProcessorReflectionImporter(moduleDef); - } - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporterProvider.cs.meta b/Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporterProvider.cs.meta deleted file mode 100644 index 12a58b8..0000000 --- a/Assets/FishNet/CodeGenerating/ILCore/PostProcessorReflectionImporterProvider.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f9273a5dad109ab0783891e36c983080 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing.meta b/Assets/FishNet/CodeGenerating/Processing.meta deleted file mode 100644 index 21c7e9a..0000000 --- a/Assets/FishNet/CodeGenerating/Processing.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: b0d1eb51001374741a4c4de01c3bc05d -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/CodegenBase.cs b/Assets/FishNet/CodeGenerating/Processing/CodegenBase.cs deleted file mode 100644 index 9634513..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/CodegenBase.cs +++ /dev/null @@ -1,61 +0,0 @@ -using MonoFN.Cecil; -using SR = System.Reflection; - - -namespace FishNet.CodeGenerating -{ - internal abstract class CodegenBase - { - //Lazy debug checks. - public bool IsIsolatedAsm => (Module.Name.Contains("IsolatedAsm")); - public bool IsRuntimeAsm => (Module.Name.Contains("FishNet.Runtime")); - - public CodegenSession Session { get; private set; } - public ModuleDefinition Module { get; private set; } - - public virtual bool ImportReferences() { return true; } - - public void Initialize(CodegenSession session) - { - Session = session; - Module = session.Module; - } - - /// - /// Returns class of type if found within Session. - /// - /// - /// - internal T GetClass() where T : CodegenBase => Session.GetClass(); - - #region Logging. - /// - /// Logs a warning. - /// - /// - internal void LogWarning(string msg) => Session.LogWarning(msg); - /// - /// Logs an error. - /// - /// - internal void LogError(string msg) => Session.LogError(msg); - #endregion - - #region ImportReference. - public MethodReference ImportReference(SR.MethodBase method) => Session.ImportReference(method); - public MethodReference ImportReference(SR.MethodBase method, IGenericParameterProvider context) => Session.ImportReference(method, context); - public TypeReference ImportReference(TypeReference type) => Session.ImportReference(type); - public TypeReference ImportReference(TypeReference type, IGenericParameterProvider context) => Session.ImportReference(type, context); - public FieldReference ImportReference(FieldReference field) => Session.ImportReference(field); - public FieldReference ImportReference(FieldReference field, IGenericParameterProvider context) => Session.ImportReference(field, context); - public FieldReference ImportReference(SR.FieldInfo field) => Session.ImportReference(field); - public FieldReference ImportReference(SR.FieldInfo field, IGenericParameterProvider context) => Session.ImportReference(field, context); - public MethodReference ImportReference(MethodReference method) => Session.ImportReference(method); - public MethodReference ImportReference(MethodReference method, IGenericParameterProvider context) => Session.ImportReference(method, context); - public TypeReference ImportReference(System.Type type) => Session.ImportReference(type, null); - public TypeReference ImportReference(System.Type type, IGenericParameterProvider context) => Session.ImportReference(type, context); - #endregion - - } - -} diff --git a/Assets/FishNet/CodeGenerating/Processing/CodegenBase.cs.meta b/Assets/FishNet/CodeGenerating/Processing/CodegenBase.cs.meta deleted file mode 100644 index 90b497e..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/CodegenBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8462034e5255191499a018bd8fbbf751 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/CustomSerializerProcessor.cs b/Assets/FishNet/CodeGenerating/Processing/CustomSerializerProcessor.cs deleted file mode 100644 index 038cc61..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/CustomSerializerProcessor.cs +++ /dev/null @@ -1,359 +0,0 @@ - -using FishNet.CodeGenerating.Helping; -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.Serializing; -using FishNet.Serializing.Helping; -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.CodeGenerating.Processing -{ - internal class CustomSerializerProcessor : CodegenBase - { - - #region Types. - internal enum ExtensionType - { - None, - Write, - Read - } - - #endregion - - internal bool CreateSerializerDelegates(TypeDefinition typeDef, bool replace) - { - bool modified = false; - /* Find all declared methods and register delegates to them. - * After they are all registered create any custom writers - * needed to complete the declared methods. It's important to - * make generated writers after so that a generated method - * isn't made for a type when the user has already made a declared one. */ - foreach (MethodDefinition methodDef in typeDef.Methods) - { - ExtensionType extensionType = GetExtensionType(methodDef); - if (extensionType == ExtensionType.None) - continue; - if (base.GetClass().CodegenExclude(methodDef)) - continue; - - MethodReference methodRef = base.ImportReference(methodDef); - if (extensionType == ExtensionType.Write) - { - base.GetClass().AddWriterMethod(methodRef.Parameters[1].ParameterType, methodRef, false, !replace); - modified = true; - } - else if (extensionType == ExtensionType.Read) - { - base.GetClass().AddReaderMethod(methodRef.ReturnType, methodRef, false, !replace); - modified = true; - } - } - - return modified; - } - - /// - /// Creates serializers for any custom types for declared methods. - /// - /// - /// - internal bool CreateSerializers(TypeDefinition typeDef) - { - bool modified = false; - - List<(MethodDefinition, ExtensionType)> declaredMethods = new List<(MethodDefinition, ExtensionType)>(); - /* Go through all custom serializers again and see if - * they use any types that the user didn't make a serializer for - * and that there isn't a built-in type for. Create serializers - * for these types. */ - foreach (MethodDefinition methodDef in typeDef.Methods) - { - ExtensionType extensionType = GetExtensionType(methodDef); - if (extensionType == ExtensionType.None) - continue; - if (base.GetClass().CodegenExclude(methodDef)) - continue; - - declaredMethods.Add((methodDef, extensionType)); - modified = true; - } - //Now that all declared are loaded see if any of them need generated serializers. - foreach ((MethodDefinition methodDef, ExtensionType extensionType) in declaredMethods) - CreateSerializers(extensionType, methodDef); - - return modified; - } - - - /// - /// Creates a custom serializer for any types not handled within users declared. - /// - /// - /// - /// - /// - private void CreateSerializers(ExtensionType extensionType, MethodDefinition methodDef) - { - for (int i = 0; i < methodDef.Body.Instructions.Count; i++) - CheckToModifyInstructions(extensionType, methodDef, ref i); - } - - /// - /// Creates delegates for custom comparers. - /// - internal bool CreateComparerDelegates(TypeDefinition typeDef) - { - bool modified = false; - GeneralHelper gh = base.GetClass(); - /* Find all declared methods and register delegates to them. - * After they are all registered create any custom writers - * needed to complete the declared methods. It's important to - * make generated writers after so that a generated method - * isn't made for a type when the user has already made a declared one. */ - foreach (MethodDefinition methodDef in typeDef.Methods) - { - if (gh.CodegenExclude(methodDef)) - continue; - if (!methodDef.HasCustomAttribute()) - continue; - //Validate return type. - if (methodDef.ReturnType.FullName != gh.GetTypeReference(typeof(bool)).FullName) - { - base.LogError($"Comparer method {methodDef.Name} in type {typeDef.FullName} must return bool."); - continue; - } - /* Make sure parameters are correct. */ - //Invalid count. - if (methodDef.Parameters.Count != 2) - { - base.LogError($"Comparer method {methodDef.Name} in type {typeDef.FullName} must have exactly two parameters, each of the same type which is being compared."); - continue; - } - TypeReference p0Tr = methodDef.Parameters[0].ParameterType; - TypeReference p1Tr = methodDef.Parameters[0].ParameterType; - //Not the same types. - if (p0Tr != p1Tr) - { - base.LogError($"Both parameters must be the same type in comparer method {methodDef.Name} in type {typeDef.FullName}."); - continue; - } - - base.ImportReference(methodDef); - base.ImportReference(p0Tr); - gh.RegisterComparerDelegate(methodDef, p0Tr); - gh.CreateComparerDelegate(methodDef, p0Tr); - } - - return modified; - } - - - /// - /// Checks if instructions need to be modified and does so. - /// - /// - /// - private void CheckToModifyInstructions(ExtensionType extensionType, MethodDefinition methodDef, ref int instructionIndex) - { - Instruction instruction = methodDef.Body.Instructions[instructionIndex]; - //Fields. - if (instruction.OpCode == OpCodes.Ldsfld || instruction.OpCode == OpCodes.Ldfld) - CheckFieldReferenceInstruction(extensionType, methodDef, ref instructionIndex); - //Method calls. - else if (instruction.OpCode == OpCodes.Call || instruction.OpCode == OpCodes.Callvirt) - CheckCallInstruction(extensionType, methodDef, ref instructionIndex, (MethodReference)instruction.Operand); - } - - - /// - /// Checks if a reader or writer must be generated for a field type. - /// - /// - /// - private void CheckFieldReferenceInstruction(ExtensionType extensionType, MethodDefinition methodDef, ref int instructionIndex) - { - Instruction instruction = methodDef.Body.Instructions[instructionIndex]; - FieldReference field = (FieldReference)instruction.Operand; - TypeReference typeRef = field.DeclaringType; - - if (typeRef.IsType(typeof(GenericWriter<>)) || typeRef.IsType(typeof(GenericReader<>)) && typeRef.IsGenericInstance) - { - GenericInstanceType typeGenericInst = (GenericInstanceType)typeRef; - TypeReference parameterType = typeGenericInst.GenericArguments[0]; - CreateReaderOrWriter(extensionType, methodDef, ref instructionIndex, parameterType); - } - } - - - /// - /// Checks if a reader or writer must be generated for a call type. - /// - /// - /// - /// - /// - /// - private void CheckCallInstruction(ExtensionType extensionType, MethodDefinition methodDef, ref int instructionIndex, MethodReference method) - { - if (!method.IsGenericInstance) - return; - - //True if call is to read/write. - bool canCreate = ( - method.Is(nameof(Writer.Write)) || - method.Is(nameof(Reader.Read)) - ); - - if (canCreate) - { - GenericInstanceMethod instanceMethod = (GenericInstanceMethod)method; - TypeReference parameterType = instanceMethod.GenericArguments[0]; - if (parameterType.IsGenericParameter) - return; - - CreateReaderOrWriter(extensionType, methodDef, ref instructionIndex, parameterType); - } - } - - - /// - /// Creates a reader or writer for parameterType if needed. Otherwise calls existing reader. - /// - private void CreateReaderOrWriter(ExtensionType extensionType, MethodDefinition methodDef, ref int instructionIndex, TypeReference parameterType) - { - if (!parameterType.IsGenericParameter && parameterType.CanBeResolved(base.Session)) - { - TypeDefinition typeDefinition = parameterType.CachedResolve(base.Session); - //If class and not value type check for accessible constructor. - if (typeDefinition.IsClass && !typeDefinition.IsValueType) - { - MethodDefinition constructor = typeDefinition.GetMethod(".ctor"); - //Constructor is inaccessible, cannot create serializer for type. - if (!constructor.IsPublic) - { - base.LogError($"Unable to generator serializers for {typeDefinition.FullName} because it's constructor is not public."); - return; - } - } - - ILProcessor processor = methodDef.Body.GetILProcessor(); - - //Find already existing read or write method. - MethodReference createdMethodRef = (extensionType == ExtensionType.Write) ? - base.GetClass().GetWriteMethodReference(parameterType) : - base.GetClass().GetReadMethodReference(parameterType); - //If a created method already exist nothing further is required. - if (createdMethodRef != null) - { - TryInsertAutoPack(ref instructionIndex); - //Replace call to generic with already made serializer. - Instruction newInstruction = processor.Create(OpCodes.Call, createdMethodRef); - methodDef.Body.Instructions[instructionIndex] = newInstruction; - return; - } - else - { - createdMethodRef = (extensionType == ExtensionType.Write) ? - base.GetClass().CreateWriter(parameterType) : - base.GetClass().CreateReader(parameterType); - } - - //If method was created. - if (createdMethodRef != null) - { - TryInsertAutoPack(ref instructionIndex); - //Set new instruction. - Instruction newInstruction = processor.Create(OpCodes.Call, createdMethodRef); - methodDef.Body.Instructions[instructionIndex] = newInstruction; - } - } - - void TryInsertAutoPack(ref int insertIndex) - { - if (IsAutoPackMethod(parameterType, extensionType)) - { - ILProcessor processor = methodDef.Body.GetILProcessor(); - AutoPackType packType = base.GetClass().GetDefaultAutoPackType(parameterType); - Instruction autoPack = processor.Create(OpCodes.Ldc_I4, (int)packType); - methodDef.Body.Instructions.Insert(insertIndex, autoPack); - insertIndex++; - } - } - } - - /// - /// Returns if a typeRef serializer requires or uses autopacktype. - /// - private bool IsAutoPackMethod(TypeReference typeRef, ExtensionType extensionType) - { - if (extensionType == ExtensionType.Write) - return base.GetClass().IsAutoPackedType(typeRef); - else if (extensionType == ExtensionType.Read) - return base.GetClass().IsAutoPackedType(typeRef); - else - return false; - - } - /// - /// Returns the RPC attribute on a method, if one exist. Otherwise returns null. - /// - /// - /// - private ExtensionType GetExtensionType(MethodDefinition methodDef) - { - bool hasExtensionAttribute = methodDef.HasCustomAttribute(); - if (!hasExtensionAttribute) - return ExtensionType.None; - - bool write = (methodDef.ReturnType == methodDef.Module.TypeSystem.Void); - - //Return None for Mirror types. -#if MIRROR - if (write) - { - if (methodDef.Parameters.Count > 0 && methodDef.Parameters[0].ParameterType.FullName == "Mirror.NetworkWriter") - return ExtensionType.None; - } - else - { - if (methodDef.Parameters.Count > 0 && methodDef.Parameters[0].ParameterType.FullName == "Mirror.NetworkReader") - return ExtensionType.None; - } -#endif - - - string prefix = (write) ? WriterProcessor.WRITE_PREFIX : ReaderProcessor.READ_PREFIX; - - //Does not contain prefix. - if (methodDef.Name.Length < prefix.Length || methodDef.Name.Substring(0, prefix.Length) != prefix) - return ExtensionType.None; - - //Make sure first parameter is right. - if (methodDef.Parameters.Count >= 1) - { - TypeReference tr = methodDef.Parameters[0].ParameterType; - if (tr.FullName != base.GetClass().Writer_TypeRef.FullName && - tr.FullName != base.GetClass().Reader_TypeRef.FullName) - return ExtensionType.None; - } - - if (write && methodDef.Parameters.Count < 2) - { - base.LogError($"{methodDef.FullName} must have at least two parameters, the first being PooledWriter, and second value to write."); - return ExtensionType.None; - } - else if (!write && methodDef.Parameters.Count < 1) - { - base.LogError($"{methodDef.FullName} must have at least one parameters, the first being PooledReader."); - return ExtensionType.None; - } - - return (write) ? ExtensionType.Write : ExtensionType.Read; - } - - - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Processing/CustomSerializerProcessor.cs.meta b/Assets/FishNet/CodeGenerating/Processing/CustomSerializerProcessor.cs.meta deleted file mode 100644 index 8235bda..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/CustomSerializerProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9269fd8a62199e24c965b4c99b641244 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourProcessor.cs b/Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourProcessor.cs deleted file mode 100644 index 88f9df6..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourProcessor.cs +++ /dev/null @@ -1,637 +0,0 @@ -using FishNet.CodeGenerating.Extension; -using FishNet.CodeGenerating.Helping; -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.CodeGenerating.Processing.Rpc; -using FishNet.Configuring; -using FishNet.Object; -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using MonoFN.Collections.Generic; -using System.Collections.Generic; -using System.Linq; - -namespace FishNet.CodeGenerating.Processing -{ - internal class NetworkBehaviourProcessor : CodegenBase - { - #region Types. - private class NetworkInitializeMethodData - { - public MethodDefinition MethodDefinition; - public FieldDefinition CalledFieldDef; - public bool CalledFromAwake; - - public NetworkInitializeMethodData(MethodDefinition methodDefinition, FieldDefinition calledFieldDef) - { - MethodDefinition = methodDefinition; - CalledFieldDef = calledFieldDef; - CalledFromAwake = false; - } - } - private class AwakeMethodData - { - public MethodDefinition AwakeMethodDef; - public MethodDefinition UserLogicMethodDef; - public bool Created; - - public AwakeMethodData(MethodDefinition awakeMd, MethodDefinition userLogicMd, bool created) - { - AwakeMethodDef = awakeMd; - UserLogicMethodDef = userLogicMd; - Created = created; - } - } - #endregion - - #region Misc. - private Dictionary _earlyNetworkInitializeDatas = new Dictionary(); - private Dictionary _lateNetworkInitializeDatas = new Dictionary(); - /// - /// Methods modified or iterated during weaving. - /// - internal List ModifiedMethodDefinitions = new List(); - /// - /// Classes which have been processed for all NetworkBehaviour features. - /// - private HashSet _processedClasses = new HashSet(); - #endregion - - #region Const. - internal const string EARLY_INITIALIZED_NAME = "NetworkInitializeEarly_"; - internal const string LATE_INITIALIZED_NAME = "NetworkInitializeLate_"; - internal const string NETWORKINITIALIZE_EARLY_INTERNAL_NAME = "NetworkInitialize___Early"; - internal const string NETWORKINITIALIZE_LATE_INTERNAL_NAME = "NetworkInitialize__Late"; - private MethodAttributes PUBLIC_VIRTUAL_ATTRIBUTES = (MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig); -#pragma warning disable CS0414 - private MethodAttributes PROTECTED_VIRTUAL_ATTRIBUTES = (MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig); -#pragma warning restore CS0414 - #endregion - - internal bool Process(TypeDefinition typeDef, List<(SyncType, ProcessedSync)> allProcessedSyncs, Dictionary childSyncTypeCounts, Dictionary childRpcCounts) - { - bool modified = false; - TypeDefinition copyTypeDef = typeDef; - TypeDefinition firstTypeDef = typeDef; - - //Make collection of NBs to processor. - List typeDefs = new List(); - do - { - typeDefs.Add(copyTypeDef); - copyTypeDef = TypeDefinitionExtensionsOld.GetNextBaseClassToProcess(copyTypeDef, base.Session); - } while (copyTypeDef != null); - - /* Iterate from child-most to parent first - * while creating network initialize methods. - * This is because the child-most must call the parents - * base awake methods. */ - foreach (TypeDefinition td in typeDefs) - { - /* Class was already processed. Since child most is processed first - * this can occur if a class is inherited by multiple types. If a class - * has already been processed then there is no reason to scale up the hierarchy - * because it would have already been done. */ - if (HasClassBeenProcessed(td)) - continue; - - //Disallow nested network behaviours. - ICollection nestedTds = td.NestedTypes; - foreach (TypeDefinition item in nestedTds) - { - if (item.InheritsNetworkBehaviour(base.Session)) - { - base.LogError($"{td.FullName} contains nested NetworkBehaviours. These are not supported."); - return modified; - } - } - - /* Create NetworkInitialize before-hand so the other procesors - * can use it. */ - MethodDefinition networkInitializeIfDisabledMd; - CreateNetworkInitializeMethods(td, out networkInitializeIfDisabledMd); - CallNetworkInitializeMethods(networkInitializeIfDisabledMd); - } - - /* Reverse and do RPCs/SyncTypes. - * This counts up on children instead of the - * parent, so we do not have to rewrite - * parent numbers. */ - typeDefs.Reverse(); - - foreach (TypeDefinition td in typeDefs) - { - /* Class was already processed. Since child most is processed first - * this can occur if a class is inherited by multiple types. If a class - * has already been processed then there is no reason to scale up the hierarchy - * because it would have already been done. */ - if (HasClassBeenProcessed(td)) - continue; - - //No longer used...remove in rework. - uint rpcCount = 0; - childRpcCounts.TryGetValue(td, out rpcCount); - /* Prediction. */ - /* Run prediction first since prediction will modify - * user data passed into prediction methods. Because of this - * other RPCs should use the modified version and reader/writers - * made for prediction. */ - modified |= base.GetClass().Process(td, ref rpcCount); - //25ms - - /* RPCs. */ - modified |= base.GetClass().ProcessLocal(td, ref rpcCount); - //30ms - /* //perf rpcCounts can be optimized by having different counts - * for target, observers, server, replicate, and reoncile rpcs. Since - * each registers to their own delegates this is possible. */ - - - - /* SyncTypes. */ - uint syncTypeStartCount; - childSyncTypeCounts.TryGetValue(td, out syncTypeStartCount); - modified |= base.GetClass().Process(td, allProcessedSyncs, ref syncTypeStartCount); - //70ms - _processedClasses.Add(td); - } - - int maxAllowSyncTypes = 256; - if (allProcessedSyncs.Count > maxAllowSyncTypes) - { - base.LogError($"Found {allProcessedSyncs.Count} SyncTypes within {firstTypeDef.FullName}. The maximum number of allowed SyncTypes within type and inherited types is {maxAllowSyncTypes}. Remove SyncTypes or condense them using data containers, or a custom SyncObject."); - return false; - } - - /* If here then all inerited classes for firstTypeDef have - * been processed. */ - PrepareNetworkInitializeMethods(firstTypeDef); - - /* Make awake methods for all inherited classes - * public and virtual. This is so I can add logic - * to the firstTypeDef awake and still execute - * user awake methods. */ - List awakeDatas = new List(); - if (!CreateOrModifyAwakeMethods(firstTypeDef, ref awakeDatas)) - { - base.LogError($"Was unable to make Awake methods public virtual starting on type {firstTypeDef.FullName}."); - return modified; - } - - //NetworkInitializeEarly. - CallNetworkInitializeFromAwake(awakeDatas, true); - //Call base awake, then call user logic methods. - CallBaseAwakeOnCreatedMethods(awakeDatas); - CallAwakeUserLogic(awakeDatas); - //NetworkInitializeLate - CallNetworkInitializeFromAwake(awakeDatas, false); - //Since awake methods are erased ret has to be added at the end. - AddReturnsToAwake(awakeDatas); - - base.GetClass().CallBaseReadSyncVar(firstTypeDef); - - return modified; - } - - - /// - /// Returns if a class has been processed. - /// - /// - /// - private bool HasClassBeenProcessed(TypeDefinition typeDef) - { - return _processedClasses.Contains(typeDef); - } - - /// - /// Returns if any typeDefs have attributes which are not allowed to be used outside NetworkBehaviour. - /// - /// - /// - internal bool NonNetworkBehaviourHasInvalidAttributes(Collection typeDefs) - { - bool error = false; - foreach (TypeDefinition typeDef in typeDefs) - { - //Inherits, don't need to check. - if (typeDef.InheritsNetworkBehaviour(base.Session)) - continue; - - //Check each method for attribute. - foreach (MethodDefinition md in typeDef.Methods) - { - //Has RPC attribute but doesn't inherit from NB. - if (base.GetClass().Attributes.HasRpcAttributes(md)) - { - base.LogError($"{typeDef.FullName} has one or more RPC attributes but does not inherit from NetworkBehaviour."); - error = true; - } - } - //Check fields for attribute. - foreach (FieldDefinition fd in typeDef.Fields) - { - if (base.GetClass().GetSyncType(fd, false, out _) != SyncType.Unset) - { - base.LogError($"{typeDef.FullName} has one or more SyncType attributes but does not inherit from NetworkBehaviour."); - error = true; - } - } - } - - return error; - } - - - - /// - /// Calls the next awake method if the nested awake was created by codegen. - /// - /// - private void CallBaseAwakeOnCreatedMethods(List datas) - { - /* Method definitions are added from child most - * so they will always be going up the hierarchy. */ - for (int i = 0; i < datas.Count; i++) - { - AwakeMethodData amd = datas[i]; - /* If the awake already existed - * then let the user code be the final say - * if base is called. */ - if (!amd.Created) - continue; - - TypeDefinition typeDef = amd.AwakeMethodDef.DeclaringType; - - /* Awake will always exist because it was added previously. - * Get awake for the current declaring type. */ - MethodDefinition awakeMd = typeDef.GetMethod(NetworkBehaviourHelper.AWAKE_METHOD_NAME); - - MethodReference baseAwakeMr = typeDef.GetMethodReferenceInBase(base.Session, NetworkBehaviourHelper.AWAKE_METHOD_NAME); - if (baseAwakeMr == null) - return; - MethodDefinition baseAwakeMd = baseAwakeMr.CachedResolve(base.Session); - //MethodDefinition baseAwakeMd = typeDef.GetMethodDefinitionInBase(base.Session, NetworkBehaviourHelper.AWAKE_METHOD_NAME); - if (baseAwakeMd == null) - return; - - //Check if they already call base. - ILProcessor processor = awakeMd.Body.GetILProcessor(); - bool alreadyHasBaseCall = false; - //Check if already calls baseAwake. - foreach (var item in awakeMd.Body.Instructions) - { - //If a call or call virt. Although, callvirt should never occur. - if (item.OpCode == OpCodes.Call || item.OpCode == OpCodes.Callvirt) - { - if (item.Operand != null && item.Operand.GetType().Name == nameof(MethodDefinition)) - { - MethodDefinition md = (MethodDefinition)item.Operand; - if (md == baseAwakeMd) - { - alreadyHasBaseCall = true; - break; - } - } - } - } - - if (!alreadyHasBaseCall) - { - //Create instructions for base call. - processor.Emit(OpCodes.Ldarg_0); //base. - processor.Emit(OpCodes.Call, baseAwakeMr); - } - } - } - - - /// - /// Calls the next awake method if the nested awake was created by codegen. - /// - /// - private void CallAwakeUserLogic(List datas) - { - /* Method definitions are added from child most - * so they will always be going up the hierarchy. */ - for (int i = 0; i < datas.Count; i++) - { - AwakeMethodData amd = datas[i]; - //If was created then there is no user logic. - if (amd.Created) - continue; - //If logic method is null. Should never be the case. - if (amd.UserLogicMethodDef == null) - continue; - - MethodDefinition awakeMd = amd.AwakeMethodDef; - base.GetClass().CallCopiedMethod(awakeMd, amd.UserLogicMethodDef); - } - } - - - /// - /// Adds a check to NetworkInitialize to see if it has already run. - /// - /// - private void AddNetworkInitializeExecutedCheck(TypeDefinition firstTypeDef, bool initializeEarly) - { - TypeDefinition copyTypeDef = firstTypeDef; - AddCheck(copyTypeDef, initializeEarly); - - void AddCheck(TypeDefinition td, bool early) - { - string methodName; - string fieldName; - if (early) - { - methodName = NETWORKINITIALIZE_EARLY_INTERNAL_NAME; - fieldName = $"{EARLY_INITIALIZED_NAME}{td.FullName}_{td.Module.Name}"; - } - else - { - methodName = NETWORKINITIALIZE_LATE_INTERNAL_NAME; - fieldName = $"{LATE_INITIALIZED_NAME}{td.FullName}_{td.Module.Name}"; - } - - MethodDefinition md = td.GetMethod(methodName); - if (md == null) - return; - - TypeReference boolTr = base.GetClass().GetTypeReference(typeof(bool)); - FieldReference fr = copyTypeDef.GetOrCreateFieldReference(base.Session, fieldName, FieldAttributes.Private, boolTr, out bool created); - - if (created) - { - List insts = new List(); - ILProcessor processor = md.Body.GetILProcessor(); - //Add check if already called. - //if (alreadyInitialized) return; - Instruction skipFirstRetInst = processor.Create(OpCodes.Nop); - insts.Add(processor.Create(OpCodes.Ldarg_0)); - insts.Add(processor.Create(OpCodes.Ldfld, fr)); - insts.Add(processor.Create(OpCodes.Brfalse_S, skipFirstRetInst)); - insts.Add(processor.Create(OpCodes.Ret)); - insts.Add(skipFirstRetInst); - //Set field to true. - insts.Add(processor.Create(OpCodes.Ldarg_0)); - insts.Add(processor.Create(OpCodes.Ldc_I4_1)); - insts.Add(processor.Create(OpCodes.Stfld, fr)); - processor.InsertFirst(insts); - } - } - } - /// - /// Gets the top-most parent away method. - /// - /// - /// - private void PrepareNetworkInitializeMethods(TypeDefinition firstTypeDef) - { - TypeDefinition thisTypeDef = firstTypeDef; - - string[] initializeMethodNames = new string[] { NETWORKINITIALIZE_EARLY_INTERNAL_NAME, NETWORKINITIALIZE_LATE_INTERNAL_NAME }; - - do - { - bool canCallBase = thisTypeDef.CanProcessBaseType(base.Session); - - foreach (string mdName in initializeMethodNames) - { - /* There are no more base calls to make but we still - * need to check if the initialize methods have already ran, so do that - * here. */ - if (canCallBase) - { - /* Awake will always exist because it was added previously. - * Get awake for copy and base of copy. */ - MethodDefinition thisMd = thisTypeDef.GetMethod(mdName); - MethodReference baseMr = thisTypeDef.GetMethodReferenceInBase(base.Session, mdName); - MethodDefinition baseMd = baseMr.CachedResolve(base.Session); - ILProcessor processor = thisMd.Body.GetILProcessor(); - - bool alreadyHasBaseCall = false; - //Check if already calls baseAwake. - foreach (Instruction item in thisMd.Body.Instructions) - { - //If a call or call virt. Although, callvirt should never occur. - if (item.OpCode == OpCodes.Call || item.OpCode == OpCodes.Callvirt) - { - if (item.Operand != null && item.Operand.GetType().Name == nameof(MethodDefinition)) - { - MethodDefinition md = (MethodDefinition)item.Operand; - if (md == baseMd) - { - alreadyHasBaseCall = true; - break; - } - } - } - } - - if (!alreadyHasBaseCall) - { - //Create instructions for base call. - List instructions = new List(); - instructions.Add(processor.Create(OpCodes.Ldarg_0)); //this. - instructions.Add(processor.Create(OpCodes.Call, baseMr)); - processor.InsertFirst(instructions); - } - } - - AddNetworkInitializeExecutedCheck(thisTypeDef, (mdName == NETWORKINITIALIZE_EARLY_INTERNAL_NAME)); - } - - thisTypeDef = TypeDefinitionExtensionsOld.GetNextBaseClassToProcess(thisTypeDef, base.Session); - } while (thisTypeDef != null); - } - - /// - /// Adds returns awake method definitions within awakeDatas. - /// - private void AddReturnsToAwake(List awakeDatas) - { - foreach (AwakeMethodData amd in awakeDatas) - { - ILProcessor processor = amd.AwakeMethodDef.Body.GetILProcessor(); - //If no instructions or the last instruction isnt ret. - if (processor.Body.Instructions.Count == 0 - || processor.Body.Instructions[processor.Body.Instructions.Count - 1].OpCode != OpCodes.Ret) - { - processor.Emit(OpCodes.Ret); - } - } - } - - /// - /// Calls NetworKInitializeLate method on the typeDef. - /// - /// - private void CallNetworkInitializeFromAwake(List awakeDatas, bool callEarly) - { - /* InitializeLate should be called after the user runs - * all their Awake logic. This is so the user can configure - * sync types on Awake and it won't trigger those values - * as needing to be sent over the network, since both - * server and client will be assigning them on Awake. */ - foreach (AwakeMethodData amd in awakeDatas) - { - string methodName = (callEarly) ? NETWORKINITIALIZE_EARLY_INTERNAL_NAME : - NETWORKINITIALIZE_LATE_INTERNAL_NAME; - - TypeDefinition td = amd.AwakeMethodDef.DeclaringType; - MethodReference networkInitMr = td.GetMethodReference(base.Session, methodName); - - ILProcessor processor = amd.AwakeMethodDef.Body.GetILProcessor(); - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(networkInitMr.GetCallOpCode(base.Session), networkInitMr); - } - } - - /// - /// Creates an 'NetworkInitialize' method which is called by the childmost class to initialize scripts on Awake. - /// - private void CreateNetworkInitializeMethods(TypeDefinition typeDef, out MethodDefinition networkInitializeIfDisabledMd) - { - CreateMethod(NETWORKINITIALIZE_EARLY_INTERNAL_NAME); - CreateMethod(NETWORKINITIALIZE_LATE_INTERNAL_NAME); - - MethodDefinition baseInitIfDisabled = base.GetClass().NetworkInitializeIfDisabled_MethodRef.CachedResolve(base.Session); - networkInitializeIfDisabledMd = CreateMethod(baseInitIfDisabled.Name, baseInitIfDisabled); - - MethodDefinition CreateMethod(string name, MethodDefinition copied = null) - { - MethodDefinition md; - bool created; - if (copied == null) - md = typeDef.GetOrCreateMethodDefinition(base.Session, name, PUBLIC_VIRTUAL_ATTRIBUTES, typeDef.Module.TypeSystem.Void, out created); - else - md = typeDef.GetOrCreateMethodDefinition(base.Session, name, copied, true, out created); - - if (created) - { - //Emit ret into new method. - ILProcessor processor = md.Body.GetILProcessor(); - //End of method return. - processor.Emit(OpCodes.Ret); - } - - return md; - } - } - - - /// - /// Creates an 'NetworkInitialize' method which is called by the childmost class to initialize scripts on Awake. - /// - private void CallNetworkInitializeMethods(MethodDefinition networkInitializeIfDisabledMd) - { - ILProcessor processor = networkInitializeIfDisabledMd.Body.GetILProcessor(); - - networkInitializeIfDisabledMd.Body.Instructions.Clear(); - CallMethod(NETWORKINITIALIZE_EARLY_INTERNAL_NAME); - CallMethod(NETWORKINITIALIZE_LATE_INTERNAL_NAME); - processor.Emit(OpCodes.Ret); - - void CallMethod(string name) - { - MethodReference initIfDisabledMr = networkInitializeIfDisabledMd.DeclaringType.GetMethodReference(base.Session, name); - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(initIfDisabledMr.GetCallOpCode(base.Session), initIfDisabledMr); - } - } - - - /// - /// Creates Awake method for and all parents of typeDef using the parentMostAwakeMethodDef as a template. - /// - /// True if successful. - private bool CreateOrModifyAwakeMethods(TypeDefinition typeDef, ref List datas) - { - //Now update all scopes/create methods. - TypeDefinition copyTypeDef = typeDef; - do - { - bool created; - MethodDefinition awakeMd = copyTypeDef.GetOrCreateMethodDefinition(base.Session, NetworkBehaviourHelper.AWAKE_METHOD_NAME, PUBLIC_VIRTUAL_ATTRIBUTES, copyTypeDef.Module.TypeSystem.Void, out created); - - //Awake is found. Check for invalid return type. - if (!created) - { - if (awakeMd.ReturnType != copyTypeDef.Module.TypeSystem.Void) - { - base.LogError($"IEnumerator Awake methods are not supported within NetworkBehaviours."); - return false; - } - awakeMd.Attributes = PUBLIC_VIRTUAL_ATTRIBUTES; - } - //Aways was made. - else - { - ILProcessor processor = awakeMd.Body.GetILProcessor(); - processor.Emit(OpCodes.Ret); - } - - MethodDefinition logicMd = base.GetClass().CopyIntoNewMethod(awakeMd, $"{NetworkBehaviourHelper.AWAKE_METHOD_NAME}___UserLogic", out _); - //Clear original awake. - awakeMd.Body.Instructions.Clear(); - datas.Add(new AwakeMethodData(awakeMd, logicMd, created)); - - copyTypeDef = TypeDefinitionExtensionsOld.GetNextBaseClassToProcess(copyTypeDef, base.Session); - - } while (copyTypeDef != null); - - - return true; - } - - /// - /// Makes all Awake methods within typeDef and base classes public and virtual. - /// - /// - internal void CreateFirstNetworkInitializeCall(TypeDefinition typeDef, MethodDefinition firstUserAwakeMethodDef, MethodDefinition firstNetworkInitializeMethodDef) - { - ILProcessor processor; - //Get awake for current method. - MethodDefinition thisAwakeMethodDef = typeDef.GetMethod(NetworkBehaviourHelper.AWAKE_METHOD_NAME); - bool created = false; - - //If no awake then make one. - if (thisAwakeMethodDef == null) - { - created = true; - - thisAwakeMethodDef = new MethodDefinition(NetworkBehaviourHelper.AWAKE_METHOD_NAME, PUBLIC_VIRTUAL_ATTRIBUTES, - typeDef.Module.TypeSystem.Void); - thisAwakeMethodDef.Body.InitLocals = true; - typeDef.Methods.Add(thisAwakeMethodDef); - - processor = thisAwakeMethodDef.Body.GetILProcessor(); - processor.Emit(OpCodes.Ret); - } - - //MethodRefs for networkinitialize and awake. - MethodReference networkInitializeMethodRef = typeDef.Module.ImportReference(firstNetworkInitializeMethodDef); - - processor = thisAwakeMethodDef.Body.GetILProcessor(); - //Create instructions for base call. - List instructions = new List(); - instructions.Add(processor.Create(OpCodes.Ldarg_0)); //this. - instructions.Add(processor.Create(OpCodes.Call, networkInitializeMethodRef)); - - /* If awake was created then make a call to the users - * first awake. There's no reason to do this if awake - * already existed because the user would have control - * over making that call. */ - if (created && firstUserAwakeMethodDef != null) - { - MethodReference baseAwakeMethodRef = typeDef.Module.ImportReference(firstUserAwakeMethodDef); - instructions.Add(processor.Create(OpCodes.Ldarg_0));//this. - instructions.Add(processor.Create(OpCodes.Call, baseAwakeMethodRef)); - } - - processor.InsertFirst(instructions); - } - - - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourProcessor.cs.meta b/Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourProcessor.cs.meta deleted file mode 100644 index 1efbb02..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 23866e4d620216745a837fa99e801164 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourSyncProcessor.cs b/Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourSyncProcessor.cs deleted file mode 100644 index abb16de..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourSyncProcessor.cs +++ /dev/null @@ -1,1453 +0,0 @@ -using FishNet.CodeGenerating.Extension; -using FishNet.CodeGenerating.Helping; -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.Configuring; -using FishNet.Object; -using FishNet.Object.Synchronizing; -using FishNet.Object.Synchronizing.Internal; -using FishNet.Serializing; -using FishNet.Transporting; -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using MonoFN.Cecil.Rocks; -using MonoFN.Collections.Generic; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.CodeGenerating.Processing -{ - internal class NetworkBehaviourSyncProcessor : CodegenBase - { - #region Reflection references. - private TypeDefinition SyncBase_TypeDef; - #endregion - - #region Private. - /// - /// Last instruction to read a sync type. - /// - private Instruction _lastReadInstruction; - /// - /// Sync objects, such as get and set, created during this process. Used to skip modifying created methods. - /// - private List _createdSyncTypeMethodDefinitions = new List(); - /// - /// ReadSyncVar methods which have had their base call already made. - /// - private HashSet _baseCalledReadSyncVars = new HashSet(); - #endregion - - #region Const. - private const string SYNCVAR_PREFIX = "syncVar___"; - private const string ACCESSOR_PREFIX = "sync___"; - private const string SETREGISTERED_METHOD_NAME = "SetRegistered"; - private const string INITIALIZEINSTANCE_METHOD_NAME = "InitializeInstance"; - private const string GETSERIALIZEDTYPE_METHOD_NAME = "GetSerializedType"; - private const string SENDRATE_NAME = "SendRate"; - private const string READPERMISSIONS_NAME = "ReadPermissions"; - #endregion - - public override bool ImportReferences() - { - System.Type syncBaseType = typeof(SyncBase); - SyncBase_TypeDef = base.ImportReference(syncBaseType).Resolve(); - - return true; - } - - /// - /// Processes SyncVars and Objects. - /// - /// - /// - internal bool Process(TypeDefinition typeDef, List<(SyncType, ProcessedSync)> allProcessedSyncs, ref uint syncTypeStartCount) - { - bool modified = false; - _createdSyncTypeMethodDefinitions.Clear(); - _lastReadInstruction = null; - - FieldDefinition[] fieldDefs = typeDef.Fields.ToArray(); - foreach (FieldDefinition fd in fieldDefs) - { - CustomAttribute syncAttribute; - SyncType st = GetSyncType(fd, true, out syncAttribute); - //Not a sync type field. - if (st == SyncType.Unset) - continue; - - if (st == SyncType.Variable) - { - if (TryCreateSyncVar(syncTypeStartCount, allProcessedSyncs, typeDef, fd, syncAttribute)) - syncTypeStartCount++; - } - else if (st == SyncType.List || st == SyncType.HashSet) - { - if (TryCreateSyncList_SyncHashSet(syncTypeStartCount, allProcessedSyncs, typeDef, fd, syncAttribute, st)) - syncTypeStartCount++; - } - else if (st == SyncType.Dictionary) - { - if (TryCreateSyncDictionary(syncTypeStartCount, allProcessedSyncs, typeDef, fd, syncAttribute)) - syncTypeStartCount++; - } - else if (st == SyncType.Custom) - { - if (TryCreateCustom(syncTypeStartCount, allProcessedSyncs, typeDef, fd, syncAttribute)) - syncTypeStartCount++; - } - - modified = true; - } - - return modified; - } - - - /// - /// Gets number of SyncTypes by checking for SyncVar/Object attributes. This does not perform error checking. - /// - /// - /// - internal uint GetSyncTypeCount(TypeDefinition typeDef) - { - uint count = 0; - foreach (FieldDefinition fd in typeDef.Fields) - { - if (HasSyncTypeAttributeUnchecked(fd)) - count++; - } - - return count; - } - - /// - /// Replaces GetSets for methods which may use a SyncType. - /// - internal bool ReplaceGetSets(TypeDefinition typeDef, List<(SyncType, ProcessedSync)> allProcessedSyncs) - { - bool modified = false; - - List modifiableMethods = GetModifiableMethods(typeDef); - modified |= ReplaceGetSetDirties(modifiableMethods, allProcessedSyncs); - - return modified; - } - - /// - /// Gets SyncType fieldDef is. - /// - /// - /// - /// - internal SyncType GetSyncType(FieldDefinition fieldDef, bool validate, out CustomAttribute syncAttribute) - { - syncAttribute = null; - //If the generated field for syncvars ignore it. - if (fieldDef.Name.StartsWith(SYNCVAR_PREFIX)) - return SyncType.Unset; - - bool syncObject; - bool error; - syncAttribute = GetSyncTypeAttribute(fieldDef, out syncObject, out error); - //Do not perform further checks if an error occurred. - if (error) - return SyncType.Unset; - /* If if attribute is null the code must progress - * to throw errors when user creates a sync type - * without using the attribute. */ - if (!validate) - { - return (syncAttribute == null) ? SyncType.Unset : SyncType.Custom; - } - else - { - /* If no attribute make sure the field does not implement - * ISyncType. If it does then a SyncObject or SyncVar attribute - * should exist. */ - if (syncAttribute == null) - { - TypeDefinition foundSyncBaseTd = fieldDef.FieldType.CachedResolve(base.Session).GetClassInInheritance(base.Session, SyncBase_TypeDef); - if (foundSyncBaseTd != null && foundSyncBaseTd.ImplementsInterface()) - base.LogError($"{fieldDef.Name} within {fieldDef.DeclaringType.Name} is a SyncType but is missing the [SyncVar] or [SyncObject] attribute."); - - return SyncType.Unset; - } - - /* If the attribute is not [SyncObject] then the attribute - * is [SyncVar]. Only checks that need to be made is to make sure - * the user is not using a SyncVar attribute when they should be using a SyncObject attribute. */ - if (syncAttribute != null && !syncObject) - { - //Make sure syncvar attribute isnt on a sync object. - if (GetSyncObjectSyncType(syncAttribute) != SyncType.Unset) - { - base.LogError($"{fieldDef.Name} within {fieldDef.DeclaringType.Name} uses a [SyncVar] attribute but should be using [SyncObject]."); - return SyncType.Unset; - } - else - return SyncType.Variable; - } - - /* If here could be syncObject - * or attribute might be null. */ - if (fieldDef.FieldType.CachedResolve(base.Session).ImplementsInterfaceRecursive(base.Session)) - return GetSyncObjectSyncType(syncAttribute); - - SyncType GetSyncObjectSyncType(CustomAttribute sa) - { - //If attribute is null then throw error. - if (sa == null) - { - base.LogError($"{fieldDef.Name} within {fieldDef.DeclaringType.Name} is a SyncType but [SyncObject] attribute was not found."); - return SyncType.Unset; - } - - if (fieldDef.FieldType.Name == base.GetClass().SyncList_Name) - { - return SyncType.List; - } - else if (fieldDef.FieldType.Name == base.GetClass().SyncDictionary_Name) - { - return SyncType.Dictionary; - } - else if (fieldDef.FieldType.Name == base.GetClass().SyncHashSet_Name) - { - return SyncType.HashSet; - } - //Custom types must also implement ICustomSync. - else if (fieldDef.FieldType.CachedResolve(base.Session).ImplementsInterfaceRecursive(base.Session)) - { - return SyncType.Custom; - } - else - { - return SyncType.Unset; - } - } - - //Fall through. - if (syncAttribute != null) - base.LogError($"SyncObject attribute found on {fieldDef.Name} within {fieldDef.DeclaringType.Name} but type {fieldDef.FieldType.Name} does not inherit from SyncBase, or if a custom type does not implement ICustomSync."); - - return SyncType.Unset; - } - - } - - - /// - /// Tries to create a SyncList. - /// - private bool TryCreateCustom(uint syncTypeCount, List<(SyncType, ProcessedSync)> allProcessedSyncs, TypeDefinition typeDef, FieldDefinition originalFieldDef, CustomAttribute syncAttribute) - { - //Get the serialized type. - MethodDefinition getSerialziedTypeMd = originalFieldDef.FieldType.CachedResolve(base.Session).GetMethod(GETSERIALIZEDTYPE_METHOD_NAME); - MethodReference getSerialziedTypeMr = base.ImportReference(getSerialziedTypeMd); - Collection instructions = getSerialziedTypeMr.CachedResolve(base.Session).Body.Instructions; - - bool canSerialize = false; - TypeReference serializedDataTypeRef = null; - /* If the user is returning null then - * they are indicating a custom serializer does not - * have to be implemented. */ - if (instructions.Count == 2 && instructions[0].OpCode == OpCodes.Ldnull && instructions[1].OpCode == OpCodes.Ret) - { - canSerialize = true; - } - //If not returning null then make a serializer for return type. - else - { - foreach (Instruction item in instructions) - { - //This token references the type. - if (item.OpCode == OpCodes.Ldtoken) - { - TypeReference importedTr = null; - if (item.Operand is TypeDefinition td) - importedTr = base.ImportReference(td); - else if (item.Operand is TypeReference tr) - importedTr = base.ImportReference(tr); - - if (importedTr != null) - { - serializedDataTypeRef = importedTr; - canSerialize = base.GetClass().HasSerializerAndDeserializer(serializedDataTypeRef, true); - } - } - } - } - - //Wasn't able to determine serialized type, or create it. - if (!canSerialize) - { - base.LogError($"Custom SyncObject {originalFieldDef.Name} data type {serializedDataTypeRef.FullName} does not support serialization. Use a supported type or create a custom serializer."); - return false; - } - - bool result = InitializeCustom(syncTypeCount, typeDef, originalFieldDef, syncAttribute); - if (result) - allProcessedSyncs.Add((SyncType.Custom, null)); - return result; - } - - - /// - /// Tries to create a SyncList. - /// - private bool TryCreateSyncList_SyncHashSet(uint syncTypeCount, List<(SyncType, ProcessedSync)> allProcessedSyncs, TypeDefinition typeDef, FieldDefinition originalFieldDef, CustomAttribute syncAttribute, SyncType syncType) - { - //Import fieldType to module. - TypeReference fieldTypeTr = base.ImportReference(originalFieldDef.FieldType); - //Make sure type can be serialized. - GenericInstanceType tmpGenerinstanceType = fieldTypeTr as GenericInstanceType; - //this returns the correct data type, eg SyncList would return int. - TypeReference dataTypeRef = base.ImportReference(tmpGenerinstanceType.GenericArguments[0]); - - bool canSerialize = base.GetClass().HasSerializerAndDeserializer(dataTypeRef, true); - if (!canSerialize) - { - base.LogError($"SyncObject {originalFieldDef.Name} data type {dataTypeRef.FullName} does not support serialization. Use a supported type or create a custom serializer."); - return false; - } - - bool result = InitializeSyncList_SyncHashSet(syncTypeCount, typeDef, originalFieldDef, syncAttribute); - if (result) - allProcessedSyncs.Add((syncType, null)); - return result; - } - - /// - /// Tries to create a SyncDictionary. - /// - private bool TryCreateSyncDictionary(uint syncTypeCount, List<(SyncType, ProcessedSync)> allProcessedSyncs, TypeDefinition typeDef, FieldDefinition originalFieldDef, CustomAttribute syncAttribute) - { - //Make sure type can be serialized. - GenericInstanceType tmpGenerinstanceType = originalFieldDef.FieldType as GenericInstanceType; - //this returns the correct data type, eg SyncList would return int. - TypeReference keyTypeRef = tmpGenerinstanceType.GenericArguments[0]; - TypeReference valueTypeRef = tmpGenerinstanceType.GenericArguments[1]; - - bool canSerialize; - //Check key serializer. - canSerialize = base.GetClass().HasSerializerAndDeserializer(keyTypeRef, true); - if (!canSerialize) - { - base.LogError($"SyncObject {originalFieldDef.Name} key type {keyTypeRef.FullName} does not support serialization. Use a supported type or create a custom serializer."); - return false; - } - //Check value serializer. - canSerialize = base.GetClass().HasSerializerAndDeserializer(valueTypeRef, true); - if (!canSerialize) - { - base.LogError($"SyncObject {originalFieldDef.Name} value type {valueTypeRef.FullName} does not support serialization. Use a supported type or create a custom serializer."); - return false; - } - - bool result = InitializeSyncDictionary(syncTypeCount, typeDef, originalFieldDef, syncAttribute); - if (result) - allProcessedSyncs.Add((SyncType.Dictionary, null)); - return result; - } - - - /// - /// Tries to create a SyncVar. - /// - private bool TryCreateSyncVar(uint syncCount, List<(SyncType, ProcessedSync)> allProcessedSyncs, TypeDefinition typeDef, FieldDefinition fieldDef, CustomAttribute syncAttribute) - { - bool canSerialize = base.GetClass().HasSerializerAndDeserializer(fieldDef.FieldType, true); - if (!canSerialize) - { - base.LogError($"SyncVar {fieldDef.FullName} field type {fieldDef.FieldType.FullName} does not support serialization. Use a supported type or create a custom serializer."); - return false; - } - - if (base.Module != typeDef.Module) - { - //Only display warning if field is exposed. - if (!fieldDef.Attributes.HasFlag(FieldAttributes.Private)) - base.Session.DifferentAssemblySyncVars.Add(fieldDef); - return false; - } - - FieldDefinition syncVarFd; - MethodReference accessorSetValueMr; - MethodReference accessorGetValueMr; - - bool created = CreateSyncVar(syncCount, typeDef, fieldDef, syncAttribute, out syncVarFd, out accessorSetValueMr, out accessorGetValueMr); - if (created) - { - FieldReference originalFr = base.ImportReference(fieldDef); - allProcessedSyncs.Add((SyncType.Variable, new ProcessedSync(originalFr, syncVarFd, accessorSetValueMr, accessorGetValueMr))); - } - - return created; - } - - - - /// - /// Returns if fieldDef has a SyncType attribute. No error checking is performed. - /// - /// - /// - private bool HasSyncTypeAttributeUnchecked(FieldDefinition fieldDef) - { - foreach (CustomAttribute customAttribute in fieldDef.CustomAttributes) - { - if (base.GetClass().IsSyncVarAttribute(customAttribute.AttributeType.FullName)) - return true; - else if (base.GetClass().IsSyncObjectAttribute(customAttribute.AttributeType.FullName)) - return true; - } - - return false; - } - - - /// - /// Returns the syncvar attribute on a method, if one exist. Otherwise returns null. - /// - /// - /// - private CustomAttribute GetSyncTypeAttribute(FieldDefinition fieldDef, out bool syncObject, out bool error) - { - CustomAttribute foundAttribute = null; - //Becomes true if an error occurred during this process. - error = false; - syncObject = false; - - foreach (CustomAttribute customAttribute in fieldDef.CustomAttributes) - { - if (base.GetClass().IsSyncVarAttribute(customAttribute.AttributeType.FullName)) - syncObject = false; - else if (base.GetClass().IsSyncObjectAttribute(customAttribute.AttributeType.FullName)) - syncObject = true; - else - continue; - - //A syncvar attribute already exist. - if (foundAttribute != null) - { - base.LogError($"{fieldDef.Name} cannot have multiple SyncType attributes."); - error = true; - } - //Static. - if (fieldDef.IsStatic) - { - base.LogError($"{fieldDef.Name} SyncType cannot be static."); - error = true; - } - //Generic. - if (fieldDef.FieldType.IsGenericParameter) - { - base.LogError($"{fieldDef.Name} SyncType cannot be be generic."); - error = true; - } - //SyncObject readonly check. - if (syncObject && !fieldDef.Attributes.HasFlag(FieldAttributes.InitOnly)) - { - /* If missing readonly see if the user specified - * they want the object to be serialized. */ - bool requireReadOnly = customAttribute.GetField(nameof(SyncObjectAttribute.RequireReadOnly), true); - if (requireReadOnly) - base.LogError($"{fieldDef.Name} SyncObject must be readonly."); - error = true; - } - - - //If all checks passed. - if (!error) - foundAttribute = customAttribute; - } - - //If an error occurred then reset results. - if (error) - foundAttribute = null; - - return foundAttribute; - } - - /// - /// Creates a syncVar class for the user's syncvar. - /// - /// - /// - /// - private bool CreateSyncVar(uint syncCount, TypeDefinition typeDef, FieldDefinition originalFieldDef, CustomAttribute syncTypeAttribute, out FieldDefinition createdSyncVarFd, out MethodReference accessorSetValueMethodRef, out MethodReference accessorGetValueMethodRef) - { - accessorGetValueMethodRef = null; - accessorSetValueMethodRef = null; - CreatedSyncVar createdSyncVar; - createdSyncVarFd = CreateSyncVarFieldDefinition(typeDef, originalFieldDef, out createdSyncVar); - - if (createdSyncVarFd != null) - { - MethodReference hookMr = GetSyncVarHookMethodReference(typeDef, originalFieldDef, syncTypeAttribute); - createdSyncVar.HookMr = hookMr; - - //If accessor was made add it's methods to createdSyncTypeObjects. - if (CreateSyncVarAccessor(originalFieldDef, createdSyncVarFd, createdSyncVar, out accessorGetValueMethodRef, - out accessorSetValueMethodRef, hookMr) != null) - { - _createdSyncTypeMethodDefinitions.Add(accessorGetValueMethodRef.CachedResolve(base.Session)); - _createdSyncTypeMethodDefinitions.Add(accessorSetValueMethodRef.CachedResolve(base.Session)); - } - - InitializeSyncVar(syncCount, createdSyncVarFd, typeDef, originalFieldDef, syncTypeAttribute, createdSyncVar); - - MethodDefinition syncVarReadMd = CreateSyncVarRead(typeDef, syncCount, originalFieldDef, accessorSetValueMethodRef); - if (syncVarReadMd != null) - _createdSyncTypeMethodDefinitions.Add(syncVarReadMd); - - return true; - } - else - { - return false; - } - - } - - /// - /// Creates or gets a SyncType class for originalFieldDef. - /// - /// - private FieldDefinition CreateSyncVarFieldDefinition(TypeDefinition typeDef, FieldDefinition originalFieldDef, out CreatedSyncVar createdSyncVar) - { - createdSyncVar = base.GetClass().GetCreatedSyncVar(originalFieldDef, true); - if (createdSyncVar == null) - return null; - - originalFieldDef.Attributes &= ~FieldAttributes.Private; - originalFieldDef.Attributes |= FieldAttributes.Public; - - FieldDefinition createdFieldDef = new FieldDefinition($"{SYNCVAR_PREFIX}{originalFieldDef.Name}", originalFieldDef.Attributes, createdSyncVar.SyncVarGit); - if (createdFieldDef == null) - { - base.LogError($"Could not create field for Sync type {originalFieldDef.FieldType.FullName}, name of {originalFieldDef.Name}."); - return null; - } - - typeDef.Fields.Add(createdFieldDef); - return createdFieldDef; - } - - /// - /// Validates and gets the hook MethodReference for a SyncVar if available. - /// - /// - /// - /// - /// - private MethodReference GetSyncVarHookMethodReference(TypeDefinition typeDef, FieldDefinition originalFieldDef, CustomAttribute attribute) - { - string hook = attribute.GetField("OnChange", string.Empty); - //No hook is specified. - if (string.IsNullOrEmpty(hook)) - return null; - - MethodDefinition md = typeDef.GetMethod(hook); - - if (md != null) - { - string incorrectParametersMsg = $"OnChange method for {originalFieldDef.FullName} must contain 3 parameters in order of {originalFieldDef.FieldType.Name} oldValue, {originalFieldDef.FieldType.Name} newValue, {base.Module.TypeSystem.Boolean} asServer."; - //Not correct number of parameters. - if (md.Parameters.Count != 3) - { - base.LogError(incorrectParametersMsg); - return null; - } - /* Check if any parameters are not - * the expected type. */ - if (md.Parameters[0].ParameterType.CachedResolve(base.Session) != originalFieldDef.FieldType.CachedResolve(base.Session) || - md.Parameters[1].ParameterType.CachedResolve(base.Session) != originalFieldDef.FieldType.CachedResolve(base.Session) || - md.Parameters[2].ParameterType.CachedResolve(base.Session) != base.Module.TypeSystem.Boolean.CachedResolve(base.Session)) - { - base.LogError(incorrectParametersMsg); - return null; - } - - //If here everything checks out, return a method reference to hook method. - return base.ImportReference(md); - } - //Hook specified but no method found. - else - { - base.LogError($"Could not find method name {hook} for SyncType {originalFieldDef.FullName}."); - return null; - } - } - - /// - /// Creates accessor for a SyncVar. - /// - /// - private FieldDefinition CreateSyncVarAccessor(FieldDefinition originalFd, FieldDefinition createdSyncVarFd, CreatedSyncVar createdSyncVar, out MethodReference accessorGetValueMr, out MethodReference accessorSetValueMr, MethodReference hookMr) - { - /* Create and add property definition. */ - PropertyDefinition createdPropertyDef = new PropertyDefinition($"SyncAccessor_{originalFd.Name}", PropertyAttributes.None, originalFd.FieldType); - createdPropertyDef.DeclaringType = originalFd.DeclaringType; - //add the methods and property to the type. - originalFd.DeclaringType.Properties.Add(createdPropertyDef); - - ILProcessor processor; - - /* Get method for property definition. */ - MethodDefinition createdGetMethodDef = originalFd.DeclaringType.AddMethod($"{ACCESSOR_PREFIX}get_value_{originalFd.Name}", MethodAttributes.Public | - MethodAttributes.SpecialName | MethodAttributes.HideBySig, - originalFd.FieldType); - createdGetMethodDef.SemanticsAttributes = MethodSemanticsAttributes.Getter; - - processor = createdGetMethodDef.Body.GetILProcessor(); - processor.Emit(OpCodes.Ldarg_0); //this. - processor.Emit(OpCodes.Ldfld, originalFd); - processor.Emit(OpCodes.Ret); - accessorGetValueMr = base.ImportReference(createdGetMethodDef); - //Add getter to properties. - createdPropertyDef.GetMethod = createdGetMethodDef; - - /* Set method. */ - //Create the set method - MethodDefinition createdSetMethodDef = originalFd.DeclaringType.AddMethod($"{ACCESSOR_PREFIX}set_value_{originalFd.Name}", MethodAttributes.Public | - MethodAttributes.SpecialName | - MethodAttributes.HideBySig); - createdSetMethodDef.SemanticsAttributes = MethodSemanticsAttributes.Setter; - - ParameterDefinition valueParameterDef = base.GetClass().CreateParameter(createdSetMethodDef, originalFd.FieldType, "value"); - ParameterDefinition calledByUserParameterDef = base.GetClass().CreateParameter(createdSetMethodDef, typeof(bool), "asServer"); - processor = createdSetMethodDef.Body.GetILProcessor(); - - /* Assign to new value. Do this first because SyncVar calls hook - * and value needs to be updated before hook. Only update - * value if calledByUser(asServer) or (!calledByUser && !base.IsServer). - * This ensures clientHost will not overwrite server value. */ - - Instruction afterChangeFieldInst = processor.Create(OpCodes.Nop); - Instruction beforeChangeFieldInst = processor.Create(OpCodes.Nop); - //if (calledByUser || !base.IsServer) - processor.Emit(OpCodes.Ldarg, calledByUserParameterDef); - processor.Emit(OpCodes.Brtrue, beforeChangeFieldInst); - processor.Emit(OpCodes.Ldarg_0); //this. - processor.Emit(OpCodes.Call, base.GetClass().IsServer_MethodRef); - processor.Emit(OpCodes.Brtrue, afterChangeFieldInst); - - // _originalField = value; - processor.Append(beforeChangeFieldInst); - processor.Emit(OpCodes.Ldarg_0); //this. - processor.Emit(OpCodes.Ldarg, valueParameterDef); - processor.Emit(OpCodes.Stfld, originalFd); - processor.Append(afterChangeFieldInst); - - Instruction retInst = processor.Create(OpCodes.Ret); - - if (!Configuration.Configurations.CodeStripping.IsBuilding) - { - processor.Emit(OpCodes.Call, base.GetClass().Application_IsPlaying_MethodRef); - processor.Emit(OpCodes.Brfalse_S, retInst); - } - // SyncVar<>.SetValue(....); - processor.Emit(OpCodes.Ldarg_0); //this. - processor.Emit(OpCodes.Ldfld, createdSyncVarFd); - processor.Emit(OpCodes.Ldarg, valueParameterDef); - processor.Emit(OpCodes.Ldarg, calledByUserParameterDef); - processor.Emit(createdSyncVar.SetValueMr.GetCallOpCode(base.Session), createdSyncVar.SetValueMr); - - processor.Append(retInst); - accessorSetValueMr = base.ImportReference(createdSetMethodDef); - //Add setter to properties. - createdPropertyDef.SetMethod = createdSetMethodDef; - - return originalFd; - } - - /// - /// Sets methods used from SyncBase for typeDef. - /// - /// - internal bool SetSyncBaseMethods(TypeDefinition typeDef, out MethodReference setRegisteredMr, out MethodReference initializeInstanceMr) - { - setRegisteredMr = null; - initializeInstanceMr = null; - //Find the SyncBase class. - TypeDefinition syncBaseTd = null; - TypeDefinition copyTd = typeDef; - do - { - if (copyTd.Name == nameof(SyncBase)) - { - syncBaseTd = copyTd; - break; - } - copyTd = copyTd.GetNextBaseTypeDefinition(base.Session); - } while (copyTd != null); - - //If SyncBase isn't found. - if (syncBaseTd == null) - { - base.LogError($"Could not find SyncBase within type {typeDef.FullName}."); - return false; - } - else - { - //InitializeInstance. - initializeInstanceMr = syncBaseTd.GetMethodReference(base.Session, INITIALIZEINSTANCE_METHOD_NAME); - //SetSyncIndex. - setRegisteredMr = syncBaseTd.GetMethodReference(base.Session, SETREGISTERED_METHOD_NAME); - return true; - } - - } - - /// - /// Initializes a custom SyncObject. - /// - internal bool InitializeCustom(uint syncCount, TypeDefinition typeDef, FieldDefinition originalFieldDef, CustomAttribute attribute) - { - float sendRate = 0.1f; - WritePermission writePermissions = WritePermission.ServerOnly; - ReadPermission readPermissions = ReadPermission.Observers; - Channel channel = Channel.Reliable; - //If attribute isn't null then override values. - if (attribute != null) - { - sendRate = attribute.GetField(SENDRATE_NAME, -1f); - writePermissions = WritePermission.ServerOnly; - readPermissions = attribute.GetField(READPERMISSIONS_NAME, ReadPermission.Observers); - channel = Channel.Reliable; //attribute.GetField("Channel", Channel.Reliable); - } - - //Set needed methods from syncbase. - MethodReference setSyncIndexMr; - MethodReference initializeInstanceMr; - if (!SetSyncBaseMethods(originalFieldDef.FieldType.CachedResolve(base.Session), out setSyncIndexMr, out initializeInstanceMr)) - return false; - - MethodDefinition injectionMethodDef; - ILProcessor processor; - - uint hash = (uint)syncCount; - List insts = new List(); - - /* Initialize with attribute settings. */ - injectionMethodDef = typeDef.GetMethod(NetworkBehaviourProcessor.NETWORKINITIALIZE_EARLY_INTERNAL_NAME); - processor = injectionMethodDef.Body.GetILProcessor(); - // - - insts.Add(processor.Create(OpCodes.Ldarg_0)); //this. - insts.Add(processor.Create(OpCodes.Ldfld, originalFieldDef)); - insts.Add(processor.Create(OpCodes.Ldarg_0)); //this again for NetworkBehaviour. - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)hash)); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)writePermissions)); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)readPermissions)); - insts.Add(processor.Create(OpCodes.Ldc_R4, sendRate)); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)channel)); - insts.Add(processor.Create(OpCodes.Ldc_I4_1)); //true for syncObject. - insts.Add(processor.Create(OpCodes.Call, initializeInstanceMr)); - processor.InsertFirst(insts); - - insts.Clear(); - /* Set NetworkBehaviour and SyncIndex to use. */ - injectionMethodDef = typeDef.GetMethod(NetworkBehaviourProcessor.NETWORKINITIALIZE_LATE_INTERNAL_NAME); - processor = injectionMethodDef.Body.GetILProcessor(); - // - insts.Add(processor.Create(OpCodes.Ldarg_0)); //this. - insts.Add(processor.Create(OpCodes.Ldfld, originalFieldDef)); - insts.Add(processor.Create(setSyncIndexMr.GetCallOpCode(base.Session), setSyncIndexMr)); - - processor.InsertLast(insts); - - return true; - } - - - - /// - /// Initializes a SyncList. - /// - internal bool InitializeSyncList_SyncHashSet(uint syncCount, TypeDefinition typeDef, FieldDefinition originalFieldDef, CustomAttribute attribute) - { - float sendRate = 0.1f; - WritePermission writePermissions = WritePermission.ServerOnly; - ReadPermission readPermissions = ReadPermission.Observers; - Channel channel = Channel.Reliable; - //If attribute isn't null then override values. - if (attribute != null) - { - sendRate = attribute.GetField(SENDRATE_NAME, -1f); - writePermissions = WritePermission.ServerOnly; - readPermissions = attribute.GetField(READPERMISSIONS_NAME, ReadPermission.Observers); - channel = Channel.Reliable; //attribute.GetField("Channel", Channel.Reliable); - } - - //This import shouldn't be needed but cecil is stingy so rather be safe than sorry. - base.ImportReference(originalFieldDef); - - //Set needed methods from syncbase. - MethodReference setSyncIndexMr; - MethodReference initializeInstanceMr; - if (!SetSyncBaseMethods(originalFieldDef.FieldType.CachedResolve(base.Session), out setSyncIndexMr, out initializeInstanceMr)) - return false; - - MethodDefinition injectionMethodDef; - ILProcessor processor; - - uint hash = (uint)syncCount; - List insts = new List(); - - /* Initialize with attribute settings. */ - injectionMethodDef = typeDef.GetMethod(NetworkBehaviourProcessor.NETWORKINITIALIZE_EARLY_INTERNAL_NAME); - processor = injectionMethodDef.Body.GetILProcessor(); - - //InitializeInstance. - insts.Add(processor.Create(OpCodes.Ldarg_0)); //this. - insts.Add(processor.Create(OpCodes.Ldfld, originalFieldDef)); - insts.Add(processor.Create(OpCodes.Ldarg_0)); //this again for NetworkBehaviour. - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)hash)); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)writePermissions)); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)readPermissions)); - insts.Add(processor.Create(OpCodes.Ldc_R4, sendRate)); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)channel)); - insts.Add(processor.Create(OpCodes.Ldc_I4_1)); //true for syncObject. - insts.Add(processor.Create(OpCodes.Call, initializeInstanceMr)); - processor.InsertFirst(insts); - - insts.Clear(); - /* Set NetworkBehaviour and SyncIndex to use. */ - injectionMethodDef = typeDef.GetMethod(NetworkBehaviourProcessor.NETWORKINITIALIZE_LATE_INTERNAL_NAME); - processor = injectionMethodDef.Body.GetILProcessor(); - - insts.Add(processor.Create(OpCodes.Ldarg_0)); //this. - insts.Add(processor.Create(OpCodes.Ldfld, originalFieldDef)); - insts.Add(processor.Create(setSyncIndexMr.GetCallOpCode(base.Session), setSyncIndexMr)); - - processor.InsertLast(insts); - - return true; - } - - - - /// - /// Initializes a SyncDictionary. - /// - internal bool InitializeSyncDictionary(uint syncCount, TypeDefinition typeDef, FieldDefinition originalFieldDef, CustomAttribute attribute) - { - float sendRate = 0.1f; - WritePermission writePermissions = WritePermission.ServerOnly; - ReadPermission readPermissions = ReadPermission.Observers; - Channel channel = Channel.Reliable; - //If attribute isn't null then override values. - if (attribute != null) - { - sendRate = attribute.GetField(SENDRATE_NAME, -1f); - writePermissions = WritePermission.ServerOnly; - readPermissions = attribute.GetField(READPERMISSIONS_NAME, ReadPermission.Observers); - channel = Channel.Reliable; //attribute.GetField("Channel", Channel.Reliable); - } - - //This import shouldn't be needed but cecil is stingy so rather be safe than sorry. - base.ImportReference(originalFieldDef); - - //Set needed methods from syncbase. - MethodReference setRegisteredMr; - MethodReference initializeInstanceMr; - if (!SetSyncBaseMethods(originalFieldDef.FieldType.CachedResolve(base.Session), out setRegisteredMr, out initializeInstanceMr)) - return false; - - MethodDefinition injectionMethodDef = typeDef.GetMethod(NetworkBehaviourProcessor.NETWORKINITIALIZE_EARLY_INTERNAL_NAME); - ILProcessor processor = injectionMethodDef.Body.GetILProcessor(); - - uint hash = (uint)syncCount; - List insts = new List(); - - /* Initialize with attribute settings. */ - insts.Add(processor.Create(OpCodes.Ldarg_0)); //this. - insts.Add(processor.Create(OpCodes.Ldfld, originalFieldDef)); - insts.Add(processor.Create(OpCodes.Ldarg_0)); //this again for NetworkBehaviour. - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)hash)); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)writePermissions)); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)readPermissions)); - insts.Add(processor.Create(OpCodes.Ldc_R4, sendRate)); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)channel)); - insts.Add(processor.Create(OpCodes.Ldc_I4_1)); //true for syncObject. - insts.Add(processor.Create(OpCodes.Call, initializeInstanceMr)); - processor.InsertFirst(insts); - - insts.Clear(); - /* Set NetworkBehaviour and SyncIndex to use. */ - injectionMethodDef = typeDef.GetMethod(NetworkBehaviourProcessor.NETWORKINITIALIZE_LATE_INTERNAL_NAME); - processor = injectionMethodDef.Body.GetILProcessor(); - - insts.Add(processor.Create(OpCodes.Ldarg_0)); //this. - insts.Add(processor.Create(OpCodes.Ldfld, originalFieldDef)); - insts.Add(processor.Create(setRegisteredMr.GetCallOpCode(base.Session), setRegisteredMr)); - - processor.InsertFirst(insts); - - return true; - } - - - /// - /// Initializes a SyncVar<>. - /// - internal void InitializeSyncVar(uint syncCount, FieldDefinition createdFd, TypeDefinition typeDef, FieldDefinition originalFd, CustomAttribute attribute, CreatedSyncVar createdSyncVar) - { - GeneralHelper gh = base.GetClass(); - - //Get all possible attributes. - float sendRate = attribute.GetField(SENDRATE_NAME, -1f); - WritePermission writePermissions = WritePermission.ServerOnly; - ReadPermission readPermissions = attribute.GetField(READPERMISSIONS_NAME, ReadPermission.Observers); - Channel channel = attribute.GetField("Channel", Channel.Reliable); - - MethodDefinition injectionMethodDef = typeDef.GetMethod(NetworkBehaviourProcessor.NETWORKINITIALIZE_EARLY_INTERNAL_NAME); - ILProcessor processor = injectionMethodDef.Body.GetILProcessor(); - - uint hash = (uint)syncCount; - List insts = new List(); - //Initialize fieldDef with values from attribute. - insts.Add(processor.Create(OpCodes.Ldarg_0)); //this. - insts.Add(processor.Create(OpCodes.Ldarg_0)); //this again for NetworkBehaviour. - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)hash)); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)writePermissions)); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)readPermissions)); - insts.Add(processor.Create(OpCodes.Ldc_R4, sendRate)); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)channel)); - insts.Add(processor.Create(OpCodes.Ldarg_0)); //this. - - insts.Add(processor.Create(OpCodes.Ldfld, originalFd.MakeHostGenericIfNeeded(base.Session))); //initial value. - insts.Add(processor.Create(OpCodes.Newobj, createdSyncVar.ConstructorMr)); - insts.Add(processor.Create(OpCodes.Stfld, createdFd.MakeHostGenericIfNeeded(base.Session))); - - //If there is a hook method. - if (createdSyncVar.HookMr != null) - { - //SyncVar.add_OnChanged (event). - TypeDefinition svTd = base.GetClass().SyncVar_TypeRef.CachedResolve(base.Session); - GenericInstanceType svGit = svTd.MakeGenericInstanceType(new TypeReference[] { originalFd.FieldType }); - MethodDefinition addMd = svTd.GetMethod("add_OnChange"); - MethodReference syncVarAddMr = addMd.MakeHostInstanceGeneric(base.Session, svGit); - - //Action constructor. - GenericInstanceType actionGit = gh.ActionT3_TypeRef.MakeGenericInstanceType( - originalFd.FieldType, originalFd.FieldType, - base.GetClass().GetTypeReference(typeof(bool))); - MethodReference gitActionCtorMr = gh.ActionT3Constructor_MethodRef.MakeHostInstanceGeneric(base.Session, actionGit); - - // syncVar___field.OnChanged += UserHookMethod; - insts.Add(processor.Create(OpCodes.Ldarg_0)); - insts.Add(processor.Create(OpCodes.Ldfld, createdFd)); - insts.Add(processor.Create(OpCodes.Ldarg_0)); - - //Load the callback function. - MethodDefinition hookMd = createdSyncVar.HookMr.CachedResolve(base.Session); - OpCode ldOpCode; - if (hookMd.IsVirtual) - { - insts.Add(processor.Create(OpCodes.Dup)); - ldOpCode = OpCodes.Ldvirtftn; - } - else - { - ldOpCode = OpCodes.Ldftn; - } - insts.Add(processor.Create(ldOpCode, hookMd)); - - insts.Add(processor.Create(OpCodes.Newobj, gitActionCtorMr)); - insts.Add(processor.Create(syncVarAddMr.GetCallOpCode(base.Session), syncVarAddMr)); - } - processor.InsertFirst(insts); - - insts.Clear(); - /* Set NetworkBehaviour and SyncIndex to use. */ - injectionMethodDef = typeDef.GetMethod(NetworkBehaviourProcessor.NETWORKINITIALIZE_LATE_INTERNAL_NAME); - processor = injectionMethodDef.Body.GetILProcessor(); - - //Set NB and SyncIndex to SyncVar<>. - insts.Add(processor.Create(OpCodes.Ldarg_0)); //this. - insts.Add(processor.Create(OpCodes.Ldfld, createdFd)); - insts.Add(processor.Create(createdSyncVar.SetSyncIndexMr.GetCallOpCode(base.Session), createdSyncVar.SetSyncIndexMr)); - - processor.InsertFirst(insts); - } - - /// - /// Replaces GetSets for methods which may use a SyncType. - /// - /// - /// - internal bool ReplaceGetSetDirties(List modifiableMethods, List<(SyncType, ProcessedSync)> processedSyncs) - { - //Build processed syncs into dictionary for quicker loookups. - Dictionary> processedLookup = new Dictionary>(); - foreach ((SyncType st, ProcessedSync ps) in processedSyncs) - { - if (st != SyncType.Variable) - continue; - - List result; - if (!processedLookup.TryGetValue(ps.OriginalFieldRef, out result)) - { - result = new List() { ps }; - processedLookup.Add(ps.OriginalFieldRef, result); - } - - result.Add(ps); - } - - bool modified = false; - foreach (MethodDefinition methodDef in modifiableMethods) - modified |= ReplaceGetSetDirty(methodDef, processedLookup); - - return modified; - } - - /// - /// Replaces GetSets for a method which may use a SyncType. - /// - /// - /// - private bool ReplaceGetSetDirty(MethodDefinition methodDef, Dictionary> processedLookup) - { - if (methodDef == null) - { - base.LogError($"An object expecting value was null. Please try saving your script again."); - return false; - } - if (methodDef.IsAbstract) - return false; - if (_createdSyncTypeMethodDefinitions.Contains(methodDef)) - return false; - if (methodDef.Name == NetworkBehaviourProcessor.NETWORKINITIALIZE_EARLY_INTERNAL_NAME) - return false; - - - bool modified = false; - - for (int i = 0; i < methodDef.Body.Instructions.Count; i++) - { - Instruction inst = methodDef.Body.Instructions[i]; - - /* Loading a field. (Getter) */ - if (inst.OpCode == OpCodes.Ldfld && inst.Operand is FieldReference opFieldld) - { - FieldReference resolvedOpField = opFieldld.CachedResolve(base.Session); - if (resolvedOpField == null) - resolvedOpField = opFieldld.DeclaringType.CachedResolve(base.Session).GetFieldReference(opFieldld.Name, base.Session); - - modified |= ProcessGetField(methodDef, i, resolvedOpField, processedLookup); - } - /* Load address, reference field. */ - else if (inst.OpCode == OpCodes.Ldflda && inst.Operand is FieldReference opFieldlda) - { - FieldReference resolvedOpField = opFieldlda.CachedResolve(base.Session); - if (resolvedOpField == null) - resolvedOpField = opFieldlda.DeclaringType.CachedResolve(base.Session).GetFieldReference(opFieldlda.Name, base.Session); - - modified |= ProcessAddressField(methodDef, i, resolvedOpField, processedLookup); - } - /* Setting a field. (Setter) */ - else if (inst.OpCode == OpCodes.Stfld && inst.Operand is FieldReference opFieldst) - { - FieldReference resolvedOpField = opFieldst.CachedResolve(base.Session); - if (resolvedOpField == null) - resolvedOpField = opFieldst.DeclaringType.CachedResolve(base.Session).GetFieldReference(opFieldst.Name, base.Session); - - modified |= ProcessSetField(methodDef, i, resolvedOpField, processedLookup); - } - - } - - return modified; - } - - /// - /// Replaces Gets for a method which may use a SyncType. - /// - /// - /// - /// - /// - private bool ProcessGetField(MethodDefinition methodDef, int instructionIndex, FieldReference resolvedOpField, Dictionary> processedLookup) - { - Instruction inst = methodDef.Body.Instructions[instructionIndex]; - - //If was a replaced field. - if (processedLookup.TryGetValue(resolvedOpField, out List psLst)) - { - ProcessedSync ps = GetProcessedSync(resolvedOpField, psLst); - if (ps == null) - return false; - //Don't modify the accessor method. - if (ps.GetMethodRef.CachedResolve(base.Session) == methodDef) - return false; - - //Generic type. - if (resolvedOpField.DeclaringType.IsGenericInstance || resolvedOpField.DeclaringType.HasGenericParameters) - { - FieldReference newField = inst.Operand as FieldReference; - GenericInstanceType git = (GenericInstanceType)newField.DeclaringType; - MethodReference syncvarGetMr = ps.GetMethodRef.MakeHostInstanceGeneric(base.Session, git); - inst.OpCode = syncvarGetMr.GetCallOpCode(base.Session); - inst.Operand = syncvarGetMr; - } - //Strong type. - else - { - inst.OpCode = OpCodes.Call; - inst.Operand = ps.GetMethodRef; - } - - return true; - } - else - { - return false; - } - } - - - /// - /// Replaces Sets for a method which may use a SyncType. - /// - /// - /// - /// - /// - private bool ProcessSetField(MethodDefinition methodDef, int instructionIndex, FieldReference resolvedOpField, Dictionary> processedLookup) - { - Instruction inst = methodDef.Body.Instructions[instructionIndex]; - - /* Find any instructions that are jmp/breaking to the one we are modifying. - * These need to be modified to call changed instruction. */ - HashSet brInstructions = new HashSet(); - foreach (Instruction item in methodDef.Body.Instructions) - { - bool canJmp = (item.OpCode == OpCodes.Br || item.OpCode == OpCodes.Brfalse || item.OpCode == OpCodes.Brfalse_S || item.OpCode == OpCodes.Brtrue || item.OpCode == OpCodes.Brtrue_S || item.OpCode == OpCodes.Br_S); - if (!canJmp) - continue; - if (item.Operand == null) - continue; - if (item.Operand is Instruction jmpInst && jmpInst == inst) - brInstructions.Add(item); - } - - //If was a replaced field. - if (processedLookup.TryGetValue(resolvedOpField, out List psLst)) - { - ProcessedSync ps = GetProcessedSync(resolvedOpField, psLst); - if (ps == null) - return false; - //Don't modify the accessor method. - if (ps.SetMethodRef.CachedResolve(base.Session) == methodDef) - return false; - ILProcessor processor = methodDef.Body.GetILProcessor(); - - //Generic type. - if (resolvedOpField.DeclaringType.IsGenericInstance || resolvedOpField.DeclaringType.HasGenericParameters) - { - //Pass in true for as server. - Instruction boolTrueInst = processor.Create(OpCodes.Ldc_I4_1); - methodDef.Body.Instructions.Insert(instructionIndex, boolTrueInst); - - FieldReference newField = inst.Operand as FieldReference; - GenericInstanceType git = (GenericInstanceType)newField.DeclaringType; - inst.OpCode = OpCodes.Call; - inst.Operand = ps.SetMethodRef.MakeHostInstanceGeneric(base.Session, git); - } - //Strong typed. - else - { - - - //Pass in true for as server. - Instruction boolTrueInst = processor.Create(OpCodes.Ldc_I4_1); - methodDef.Body.Instructions.Insert(instructionIndex, boolTrueInst); - inst.OpCode = OpCodes.Call; - inst.Operand = ps.SetMethodRef; - } - - - /* If any instructions are still pointing - * to modified value then they need to be - * redirected to the instruction right above it. - * This is because the boolTrueInst, to indicate - * value is being set as server. */ - foreach (Instruction item in brInstructions) - { - if (item.Operand is Instruction jmpInst && jmpInst == inst) - { - //Use the same index that was passed in, which is now one before modified instruction. - Instruction newInst = methodDef.Body.Instructions[instructionIndex]; - item.Operand = newInst; - } - } - - return true; - } - else - { - return false; - } - } - - /// - /// Replaces address Sets for a method which may use a SyncType. - /// - /// - /// - /// - /// - private bool ProcessAddressField(MethodDefinition methodDef, int instructionIndex, FieldReference resolvedOpField, Dictionary> processedLookup) - { - Instruction inst = methodDef.Body.Instructions[instructionIndex]; - //Check if next instruction is Initobj, which would be setting a new instance. - Instruction nextInstr = inst.Next; - if (nextInstr.OpCode != OpCodes.Initobj) - return false; - - //If was a replaced field. - if (processedLookup.TryGetValue(resolvedOpField, out List psLst)) - { - ProcessedSync ps = GetProcessedSync(resolvedOpField, psLst); - if (ps == null) - return false; - //Don't modify the accessor method. - if (ps.GetMethodRef.CachedResolve(base.Session) == methodDef || ps.SetMethodRef.CachedResolve(base.Session) == methodDef) - return false; - - ILProcessor processor = methodDef.Body.GetILProcessor(); - - VariableDefinition tmpVariableDef = base.GetClass().CreateVariable(methodDef, resolvedOpField.FieldType); - processor.InsertBefore(inst, processor.Create(OpCodes.Ldloca, tmpVariableDef)); - processor.InsertBefore(inst, processor.Create(OpCodes.Initobj, resolvedOpField.FieldType)); - processor.InsertBefore(inst, processor.Create(OpCodes.Ldloc, tmpVariableDef)); - Instruction newInstr = processor.Create(OpCodes.Call, ps.SetMethodRef); - processor.InsertBefore(inst, newInstr); - - /* Pass in true for as server. - * The instruction index is 3 past ld. */ - Instruction boolTrueInst = processor.Create(OpCodes.Ldc_I4_1); - methodDef.Body.Instructions.Insert(instructionIndex + 3, boolTrueInst); - - processor.Remove(inst); - processor.Remove(nextInstr); - - return true; - } - else - { - return false; - } - } - - /// - /// Calls ReadSyncVar going up the hierarchy. - /// - /// - internal void CallBaseReadSyncVar(TypeDefinition firstTypeDef) - { - string readSyncVarName = base.GetClass().ReadSyncVar_MethodRef.Name; - //TypeDef which needs to make the base call. - MethodDefinition callerMd = null; - TypeDefinition copyTd = firstTypeDef; - do - { - MethodDefinition readMd; - - readMd = copyTd.GetMethod(readSyncVarName); - if (readMd != null) - callerMd = readMd; - - /* If baseType exist and it's not networkbehaviour - * look into calling the ReadSyncVar method. */ - if (copyTd.BaseType != null && copyTd.BaseType.FullName != base.GetClass().FullName) - { - readMd = copyTd.BaseType.CachedResolve(base.Session).GetMethod(readSyncVarName); - //Not all classes will have syncvars to read. - if (!_baseCalledReadSyncVars.Contains(callerMd) && readMd != null && callerMd != null) - { - MethodReference baseReadMr = copyTd.GetMethodReferenceInBase(base.Session, readSyncVarName);// readMd.GetMethodReferenceInBase (base.Session, base.ImportReference(readMd); - ILProcessor processor = callerMd.Body.GetILProcessor(); - ParameterDefinition asServerPd = callerMd.Parameters[2]; - /* Calls base.ReadSyncVar and if result is true - * then exit methods. This is because a true return means the base - * was able to process the syncvar. */ - List baseCallInsts = new List(); - Instruction skipBaseReturn = processor.Create(OpCodes.Nop); - baseCallInsts.Add(processor.Create(OpCodes.Ldarg_0)); //This. - baseCallInsts.Add(processor.Create(OpCodes.Ldarg_1)); //PooledReader. - baseCallInsts.Add(processor.Create(OpCodes.Ldarg_2)); //Index. - baseCallInsts.Add(processor.Create(OpCodes.Ldarg, asServerPd)); //AsServer. - baseCallInsts.Add(processor.Create(OpCodes.Call, baseReadMr)); - baseCallInsts.Add(processor.Create(OpCodes.Brfalse_S, skipBaseReturn)); - baseCallInsts.Add(processor.Create(OpCodes.Ldc_I4_1)); - baseCallInsts.Add(processor.Create(OpCodes.Ret)); - baseCallInsts.Add(skipBaseReturn); - processor.InsertFirst(baseCallInsts); - - _baseCalledReadSyncVars.Add(callerMd); - } - } - - copyTd = TypeDefinitionExtensionsOld.GetNextBaseClassToProcess(copyTd, base.Session); - - } while (copyTd != null); - - } - - /// - /// Reads a PooledReader locally then sets value to the SyncVars accessor. - /// - /// - /// - /// - private MethodDefinition CreateSyncVarRead(TypeDefinition typeDef, uint syncIndex, FieldDefinition originalFieldDef, MethodReference accessorSetMethodRef) - { - Instruction jmpGoalInst; - ILProcessor processor; - - //Get the read sync method, or create it if not present. - MethodDefinition readSyncMethodDef = typeDef.GetMethod(base.GetClass().ReadSyncVar_MethodRef.Name); - if (readSyncMethodDef == null) - { - readSyncMethodDef = new MethodDefinition(base.GetClass().ReadSyncVar_MethodRef.Name, - (MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual), - typeDef.Module.TypeSystem.Void); - readSyncMethodDef.ReturnType = base.GetClass().GetTypeReference(typeof(bool)); - - base.GetClass().CreateParameter(readSyncMethodDef, typeof(PooledReader)); - base.GetClass().CreateParameter(readSyncMethodDef, typeof(uint)); - base.GetClass().CreateParameter(readSyncMethodDef, typeof(bool)); - readSyncMethodDef.Body.InitLocals = true; - - processor = readSyncMethodDef.Body.GetILProcessor(); - //Return false as fall through. - processor.Emit(OpCodes.Ldc_I4_0); - processor.Emit(OpCodes.Ret); - - typeDef.Methods.Add(readSyncMethodDef); - } - //Already created. - else - { - processor = readSyncMethodDef.Body.GetILProcessor(); - } - - ParameterDefinition pooledReaderPd = readSyncMethodDef.Parameters[0]; - ParameterDefinition indexPd = readSyncMethodDef.Parameters[1]; - ParameterDefinition asServerPd = readSyncMethodDef.Parameters[2]; - VariableDefinition nextValueVariableDef; - List readInsts; - - /* Create a nop instruction placed at the first index of the method. - * All instructions will be added before this, then the nop will be - * removed afterwards. This ensures the newer instructions will - * be above the previous. This let's the IL jump to a previously - * created read instruction when the latest one fails conditions. */ - Instruction nopPlaceHolderInst = processor.Create(OpCodes.Nop); - - readSyncMethodDef.Body.Instructions.Insert(0, nopPlaceHolderInst); - - /* If there was a previously made read then set jmp goal to the first - * condition for it. Otherwise set it to the last instruction, which would - * be a ret. Keep in mind if ret has a value we must go back 2 index - * rather than one. */ - jmpGoalInst = (_lastReadInstruction != null) ? _lastReadInstruction : - readSyncMethodDef.Body.Instructions[readSyncMethodDef.Body.Instructions.Count - 2]; - - //Check index first. if (index != syncIndex) return - Instruction nextLastReadInstruction = processor.Create(OpCodes.Ldarg, indexPd); - processor.InsertBefore(jmpGoalInst, nextLastReadInstruction); - - uint hash = (uint)syncIndex; - processor.InsertBefore(jmpGoalInst, processor.Create(OpCodes.Ldc_I4, (int)hash)); - //processor.InsertBefore(jmpGoalInst, processor.Create(OpCodes.Ldc_I4, syncIndex)); - processor.InsertBefore(jmpGoalInst, processor.Create(OpCodes.Bne_Un, jmpGoalInst)); - //PooledReader.ReadXXXX() - readInsts = base.GetClass().CreateRead(readSyncMethodDef, pooledReaderPd, - originalFieldDef.FieldType, out nextValueVariableDef); - if (readInsts == null) - return null; - //Add each instruction from CreateRead. - foreach (Instruction i in readInsts) - processor.InsertBefore(jmpGoalInst, i); - - //Call accessor with new value and passing in asServer. - processor.InsertBefore(jmpGoalInst, processor.Create(OpCodes.Ldarg_0)); //this. - processor.InsertBefore(jmpGoalInst, processor.Create(OpCodes.Ldloc, nextValueVariableDef)); - //processor.InsertBefore(jmpGoalInst, processor.Create(OpCodes.Ldc_I4_0)); - processor.InsertBefore(jmpGoalInst, processor.Create(OpCodes.Ldarg, asServerPd)); - processor.InsertBefore(jmpGoalInst, processor.Create(OpCodes.Call, accessorSetMethodRef)); - //Return true when able to process. - processor.InsertBefore(jmpGoalInst, processor.Create(OpCodes.Ldc_I4_1)); - processor.InsertBefore(jmpGoalInst, processor.Create(OpCodes.Ret)); - - _lastReadInstruction = nextLastReadInstruction; - processor.Remove(nopPlaceHolderInst); - - return readSyncMethodDef; - } - - /// - /// Returns methods which may be modified by code generation. - /// - /// - /// - private List GetModifiableMethods(TypeDefinition typeDef) - { - List results = new List(); - - CheckTypeDefinition(typeDef); - //Have to add nested types because this are where courotines are stored. - foreach (TypeDefinition nestedTd in typeDef.NestedTypes) - CheckTypeDefinition(nestedTd); - - void CheckTypeDefinition(TypeDefinition td) - { - foreach (MethodDefinition methodDef in td.Methods) - { - if (methodDef.Name == ".cctor") - continue; - if (methodDef.IsConstructor) - continue; - if (methodDef.Body == null) - continue; - - results.Add(methodDef); - } - - foreach (PropertyDefinition propertyDef in td.Properties) - { - if (propertyDef.GetMethod != null) - results.Add(propertyDef.GetMethod); - if (propertyDef.SetMethod != null) - results.Add(propertyDef.SetMethod); - } - } - - return results; - } - - /// - /// Returns the ProcessedSync entry for resolvedOpField. - /// - /// - /// - /// - private ProcessedSync GetProcessedSync(FieldReference resolvedOpField, List psLst) - { - for (int i = 0; i < psLst.Count; i++) - { - if (psLst[i].OriginalFieldRef == resolvedOpField) - return psLst[i]; - } - - /* Fall through, not found. */ - base.LogError($"Unable to find user referenced field for {resolvedOpField.Name}."); - return null; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourSyncProcessor.cs.meta b/Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourSyncProcessor.cs.meta deleted file mode 100644 index 1ee148f..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/NetworkBehaviourSyncProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ec95af37f78b9e340b5eaa199c1af94a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/Prediction.meta b/Assets/FishNet/CodeGenerating/Processing/Prediction.meta deleted file mode 100644 index 00224f1..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Prediction.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -<<<<<<<< HEAD:Assets/FishNet/CodeGenerating/Processing/Prediction.meta -guid: 07f594347080e6547b13253aa03402e3 -folderAsset: yes -======== -guid: 89b00a3741f72ac4e861a08cf1202228 ->>>>>>>> origin/3-pre-3.1:Assets/Test/InitializeOrder/InitializeOrder_Test.unity.meta -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/Prediction/PredictionProcessor.cs b/Assets/FishNet/CodeGenerating/Processing/Prediction/PredictionProcessor.cs deleted file mode 100644 index a31463b..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Prediction/PredictionProcessor.cs +++ /dev/null @@ -1,960 +0,0 @@ -using FishNet.CodeGenerating.Extension; -using FishNet.CodeGenerating.Helping; -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.Connection; -using FishNet.Object; -using FishNet.Object.Prediction; -using FishNet.Object.Prediction.Delegating; -using FishNet.Serializing; -using FishNet.Serializing.Helping; -using FishNet.Transporting; -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using MonoFN.Cecil.Rocks; -using System.Collections.Generic; -using UnityEngine; -using SR = System.Reflection; - -namespace FishNet.CodeGenerating.Processing -{ - internal class PredictionProcessor : CodegenBase - { - #region Types. - private enum InsertType - { - First, - Last, - Current - } - - private class CreatedPredictionFields - { - /// - /// Delegate for calling replicate user logic. - /// - public readonly FieldReference ReplicateULDelegate; - /// - /// Delegate for calling replicate user logic. - /// - public readonly FieldReference ReconcileULDelegate; - /// - /// Replicate data buffered on the server. - /// - public readonly FieldReference ServerReplicateDatas; - /// - /// Replicate data buffered on the client. - /// - public readonly FieldReference ClientReplicateDatas; - /// - /// Last reconcile data received from the server. - /// - public readonly FieldReference ReconcileData; - /// - /// A buffer to read replicates into. - /// - public readonly FieldReference ServerReplicateReaderBuffer; - - public CreatedPredictionFields(FieldReference replicateULDelegate, FieldReference reconcileULDelegate, FieldReference serverReplicateDatas, FieldReference clientReplicateDatas, FieldReference reconcileData, - FieldReference serverReplicateReaderBuffer) - { - ReplicateULDelegate = replicateULDelegate; - ReconcileULDelegate = reconcileULDelegate; - ServerReplicateDatas = serverReplicateDatas; - ClientReplicateDatas = clientReplicateDatas; - ReconcileData = reconcileData; - ServerReplicateReaderBuffer = serverReplicateReaderBuffer; - } - } - - private class PredictionReaders - { - public MethodReference ReplicateReader; - public MethodReference ReconcileReader; - - public PredictionReaders(MethodReference replicateReader, MethodReference reconcileReader) - { - ReplicateReader = replicateReader; - ReconcileReader = reconcileReader; - } - } - - #endregion - - #region Public. - public string IReplicateData_FullName = typeof(IReplicateData).FullName; - public string IReconcileData_FullName = typeof(IReconcileData).FullName; - public TypeReference ReplicateULDelegate_TypeRef; - public TypeReference ReconcileULDelegate_TypeRef; - public MethodReference IReplicateData_GetTick_MethodRef; - public MethodReference IReplicateData_SetTick_MethodRef; - public MethodReference IReconcileData_GetTick_MethodRef; - public MethodReference IReconcileData_SetTick_MethodRef; - public MethodReference Unity_GetGameObject_MethodRef; - #endregion - - #region Const. - public const string REPLICATE_LOGIC_PREFIX = "Logic_Replicate___"; - public const string REPLICATE_READER_PREFIX = "Reader_Replicate___"; - public const string RECONCILE_LOGIC_PREFIX = "Logic_Reconcile___"; - public const string RECONCILE_READER_PREFIX = "Reader_Reconcile___"; - #endregion - - public override bool ImportReferences() - { - System.Type locType; - SR.MethodInfo locMi; - - ReplicateULDelegate_TypeRef = base.ImportReference(typeof(ReplicateUserLogicDelegate<>)); - ReconcileULDelegate_TypeRef = base.ImportReference(typeof(ReconcileUserLogicDelegate<>)); - - //GetGameObject. - locMi = typeof(UnityEngine.Component).GetMethod("get_gameObject"); - Unity_GetGameObject_MethodRef = base.ImportReference(locMi); - - //Get/Set tick. - locType = typeof(IReplicateData); - foreach (SR.MethodInfo mi in locType.GetMethods()) - { - if (mi.Name == nameof(IReplicateData.GetTick)) - IReplicateData_GetTick_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(IReplicateData.SetTick)) - IReplicateData_SetTick_MethodRef = base.ImportReference(mi); - } - - locType = typeof(IReconcileData); - foreach (SR.MethodInfo mi in locType.GetMethods()) - { - if (mi.Name == nameof(IReconcileData.GetTick)) - IReconcileData_GetTick_MethodRef = base.ImportReference(mi); - else if (mi.Name == nameof(IReconcileData.SetTick)) - IReconcileData_SetTick_MethodRef = base.ImportReference(mi); - } - - return true; - } - - internal bool Process(TypeDefinition typeDef, ref uint rpcCount) - { - bool modified = false; - modified |= ProcessLocal(typeDef, ref rpcCount); - - return modified; - } - - #region Setup and checks. - /// - /// Gets number of predictions by checking for prediction attributes. This does not perform error checking. - /// - /// - /// - internal uint GetPredictionCount(TypeDefinition typeDef) - { - /* Currently only one prediction method is allowed per typeDef. - * Return 1 soon as a method is found. */ - foreach (MethodDefinition methodDef in typeDef.Methods) - { - foreach (CustomAttribute customAttribute in methodDef.CustomAttributes) - { - if (customAttribute.Is(base.GetClass().ReplicateAttribute_FullName)) - return 1; - } - } - - return 0; - } - - - /// - /// Ensures only one prediction and reconile method exist per typeDef, and outputs finding. - /// - /// True if there is only one set of prediction methods. False if none, or more than one set. - internal bool GetPredictionMethods(TypeDefinition typeDef, out MethodDefinition replicateMd, out MethodDefinition reconcileMd) - { - replicateMd = null; - reconcileMd = null; - - bool error = false; - foreach (MethodDefinition methodDef in typeDef.Methods) - { - foreach (CustomAttribute customAttribute in methodDef.CustomAttributes) - { - if (customAttribute.Is(base.GetClass().ReplicateAttribute_FullName)) - { - if (!MethodIsPrivate(methodDef) || AlreadyFound(replicateMd)) - error = true; - else - replicateMd = methodDef; - } - else if (customAttribute.Is(base.GetClass().ReconcileAttribute_FullName)) - { - if (!MethodIsPrivate(methodDef) || AlreadyFound(reconcileMd)) - error = true; - else - reconcileMd = methodDef; - } - if (error) - break; - } - if (error) - break; - } - - bool MethodIsPrivate(MethodDefinition md) - { - bool isPrivate = md.Attributes.HasFlag(MethodAttributes.Private); - if (!isPrivate) - base.LogError($"Method {md.Name} within {typeDef.Name} is a prediction method and must be private."); - return isPrivate; - } - - bool AlreadyFound(MethodDefinition md) - { - bool alreadyFound = (md != null); - if (alreadyFound) - base.LogError($"{typeDef.Name} contains multiple prediction sets; currently only one set is allowed."); - - return alreadyFound; - } - - if (!error && ((replicateMd == null) != (reconcileMd == null))) - { - base.LogError($"{typeDef.Name} must contain both a [Replicate] and [Reconcile] method when using prediction."); - error = true; - } - - if (error || (replicateMd == null) || (reconcileMd == null)) - return false; - else - return true; - } - #endregion - - private bool ProcessLocal(TypeDefinition typeDef, ref uint rpcCount) - { - MethodDefinition replicateMd; - MethodDefinition reconcileMd; - - //Not using prediction methods. - if (!GetPredictionMethods(typeDef, out replicateMd, out reconcileMd)) - return false; - - //If replication methods found but this hierarchy already has max. - if (rpcCount >= NetworkBehaviourHelper.MAX_RPC_ALLOWANCE) - { - base.LogError($"{typeDef.FullName} and inherited types exceed {NetworkBehaviourHelper.MAX_RPC_ALLOWANCE} replicated methods. Only {NetworkBehaviourHelper.MAX_RPC_ALLOWANCE} replicated methods are supported per inheritance hierarchy."); - return false; - } - - bool parameterError = false; - parameterError |= HasParameterError(replicateMd, typeDef, true); - parameterError |= HasParameterError(reconcileMd, typeDef, false); - if (parameterError) - return false; - - TypeDefinition replicateDataTd = replicateMd.Parameters[0].ParameterType.CachedResolve(base.Session); - TypeDefinition reconcileDataTd = reconcileMd.Parameters[0].ParameterType.CachedResolve(base.Session); - //Ensure datas implement interfaces. - bool interfacesImplemented = true; - DataImplementInterfaces(replicateMd, true, ref interfacesImplemented); - DataImplementInterfaces(reconcileMd, false, ref interfacesImplemented); - if (!interfacesImplemented) - return false; - if (!TickFieldIsNonSerializable(replicateDataTd, true)) - return false; - if (!TickFieldIsNonSerializable(reconcileDataTd, false)) - return false; - - /* Make sure data can serialize. Use array type, this will - * generate a serializer for element type as well. */ - bool canSerialize; - //Make sure replicate data can serialize. - canSerialize = base.GetClass().HasSerializerAndDeserializer(replicateDataTd.MakeArrayType(), true); - if (!canSerialize) - { - base.LogError($"Replicate data type {replicateDataTd.Name} does not support serialization. Use a supported type or create a custom serializer."); - return false; - } - //Make sure reconcile data can serialize. - canSerialize = base.GetClass().HasSerializerAndDeserializer(reconcileDataTd, true); - if (!canSerialize) - { - base.LogError($"Reconcile data type {reconcileDataTd.Name} does not support serialization. Use a supported type or create a custom serializer."); - return false; - } - //Creates fields for buffers. - CreatedPredictionFields predictionFields; - CreateFields(typeDef, replicateMd, reconcileMd, out predictionFields); - - PredictionReaders predictionReaders; - MethodDefinition replicateULMd; - MethodDefinition reconcileULMd; - CreatePredictionMethods(typeDef, replicateMd, reconcileMd, predictionFields, rpcCount, out predictionReaders, out replicateULMd, out reconcileULMd); - InitializeCollections(typeDef, replicateMd, predictionFields); - InitializeULDelegates(typeDef, predictionFields, replicateMd, reconcileMd, replicateULMd, reconcileULMd); - RegisterRpcs(typeDef, rpcCount, predictionReaders); - - rpcCount++; - return true; - } - - /// - /// Ensures the tick field for GetTick is non-serializable. - /// - /// - /// - private bool TickFieldIsNonSerializable(TypeDefinition dataTd, bool replicate) - { - string methodName = (replicate) ? IReplicateData_GetTick_MethodRef.Name : IReconcileData_GetTick_MethodRef.Name; - MethodDefinition getMd = dataTd.GetMethod(methodName); - - //Try to find ldFld. - Instruction ldFldInst = null; - foreach (Instruction item in getMd.Body.Instructions) - { - if (item.OpCode == OpCodes.Ldfld) - { - ldFldInst = item; - break; - } - } - - //If ldFld not found. - if (ldFldInst == null) - { - base.LogError($"{dataTd.FullName} method {getMd.Name} does not return a field type for the Tick. Make a new private field of uint type and return it's value within {getMd.Name}."); - return false; - } - //Make sure the field is private. - else - { - FieldDefinition fd = (FieldDefinition)ldFldInst.Operand; - if (!fd.Attributes.HasFlag(FieldAttributes.Private)) - { - base.LogError($"{dataTd.FullName} method {getMd.Name} returns a tick field but it's not marked as private. Make the field {fd.Name} private."); - return false; - } - } - - //All checks pass. - return true; - } - - private void DataImplementInterfaces(MethodDefinition methodDef, bool isReplicate, ref bool interfacesImplemented) - { - TypeReference dataTr = methodDef.Parameters[0].ParameterType; - string interfaceName = (isReplicate) ? IReplicateData_FullName : IReconcileData_FullName; - //If does not implement. - if (!dataTr.CachedResolve(base.Session).ImplementsInterfaceRecursive(base.Session, interfaceName)) - { - string name = (isReplicate) ? typeof(IReplicateData).Name : typeof(IReconcileData).Name; - base.LogError($"Prediction data type {dataTr.Name} for method {methodDef.Name} in class {methodDef.DeclaringType.Name} must implement the {name} interface."); - interfacesImplemented = false; - } - } - - /// - /// Registers RPCs that prediction uses. - /// - private void RegisterRpcs(TypeDefinition typeDef, uint hash, PredictionReaders readers) - { - MethodDefinition injectionMethodDef = typeDef.GetMethod(NetworkBehaviourProcessor.NETWORKINITIALIZE_EARLY_INTERNAL_NAME); - ILProcessor processor = injectionMethodDef.Body.GetILProcessor(); - List insts = new List(); - - Register(readers.ReplicateReader.CachedResolve(base.Session), true); - Register(readers.ReconcileReader.CachedResolve(base.Session), false); - - void Register(MethodDefinition readerMd, bool replicate) - { - insts.Add(processor.Create(OpCodes.Ldarg_0)); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)hash)); - /* Create delegate and call NetworkBehaviour method. */ - insts.Add(processor.Create(OpCodes.Ldarg_0)); - insts.Add(processor.Create(OpCodes.Ldftn, readerMd)); - - MethodReference ctorMr; - MethodReference callMr; - if (replicate) - { - ctorMr = base.GetClass().ReplicateRpcDelegateConstructor_MethodRef; - callMr = base.GetClass().RegisterReplicateRpc_MethodRef; - } - else - { - ctorMr = base.GetClass().ReconcileRpcDelegateConstructor_MethodRef; - callMr = base.GetClass().RegisterReconcileRpc_MethodRef; - } - - insts.Add(processor.Create(OpCodes.Newobj, ctorMr)); - insts.Add(processor.Create(OpCodes.Call, callMr)); - } - - processor.InsertLast(insts); - } - - /// - /// Initializes collection fields made during this process. - /// - /// - private void InitializeCollections(TypeDefinition typeDef, MethodDefinition replicateMd, CreatedPredictionFields predictionFields) - { - GeneralHelper gh = base.GetClass(); - TypeReference replicateDataTr = replicateMd.Parameters[0].ParameterType; - MethodDefinition injectionMethodDef = typeDef.GetMethod(NetworkBehaviourProcessor.NETWORKINITIALIZE_EARLY_INTERNAL_NAME); - ILProcessor processor = injectionMethodDef.Body.GetILProcessor(); - - Generate(predictionFields.ClientReplicateDatas, true); - Generate(predictionFields.ServerReplicateDatas, false); - - void Generate(FieldReference fr, bool isList) - { - MethodDefinition ctorMd = base.GetClass().List_TypeRef.CachedResolve(base.Session).GetConstructor(); - GenericInstanceType collectionGit; - if (isList) - gh.GetGenericLists(replicateDataTr, out collectionGit); - else - gh.GetGenericQueues(replicateDataTr, out collectionGit); - MethodReference ctorMr = ctorMd.MakeHostInstanceGeneric(base.Session, collectionGit); - - List insts = new List(); - - insts.Add(processor.Create(OpCodes.Ldarg_0)); - insts.Add(processor.Create(OpCodes.Newobj, ctorMr)); - insts.Add(processor.Create(OpCodes.Stfld, fr)); - processor.InsertFirst(insts); - } - } - - /// - /// Initializes collection fields made during this process. - /// - /// - private void InitializeULDelegates(TypeDefinition typeDef, CreatedPredictionFields predictionFields, MethodDefinition replicateMd, MethodDefinition reconcileMd, MethodDefinition replicateULMd, MethodDefinition reconcileULMd) - { - TypeReference replicateDataTr = replicateMd.Parameters[0].ParameterType; - TypeReference reconcileDataTr = reconcileMd.Parameters[0].ParameterType; - MethodDefinition injectionMethodDef = typeDef.GetMethod(NetworkBehaviourProcessor.NETWORKINITIALIZE_EARLY_INTERNAL_NAME); - ILProcessor processor = injectionMethodDef.Body.GetILProcessor(); - List insts = new List(); - - Generate(replicateULMd, replicateDataTr, predictionFields.ReplicateULDelegate, typeof(ReplicateUserLogicDelegate<>), ReplicateULDelegate_TypeRef); - Generate(reconcileULMd, reconcileDataTr, predictionFields.ReconcileULDelegate, typeof(ReconcileUserLogicDelegate<>), ReconcileULDelegate_TypeRef); - - void Generate(MethodDefinition ulMd, TypeReference dataTr, FieldReference fr, System.Type delegateType, TypeReference delegateTr) - { - insts.Clear(); - - MethodDefinition ctorMd = delegateTr.CachedResolve(base.Session).GetFirstConstructor(base.Session, true); - GenericInstanceType collectionGit; - GetGenericULDelegate(dataTr, delegateType, out collectionGit); - MethodReference ctorMr = ctorMd.MakeHostInstanceGeneric(base.Session, collectionGit); - - insts.Add(processor.Create(OpCodes.Ldarg_0)); - insts.Add(processor.Create(OpCodes.Ldarg_0)); - insts.Add(processor.Create(OpCodes.Ldftn, ulMd)); - insts.Add(processor.Create(OpCodes.Newobj, ctorMr)); - insts.Add(processor.Create(OpCodes.Stfld, fr)); - processor.InsertFirst(insts); - } - } - - - - /// - /// Creates field buffers for replicate datas. - /// - /// - /// - /// - /// - private void CreateFields(TypeDefinition typeDef, MethodDefinition replicateMd, MethodDefinition reconcileMd, out CreatedPredictionFields predictionFields) - { - GeneralHelper gh = base.GetClass(); - TypeReference replicateDataTr = replicateMd.Parameters[0].ParameterType; - TypeReference replicateDataArrTr = replicateDataTr.MakeArrayType(); - TypeReference reconcileDataTr = reconcileMd.Parameters[0].ParameterType; - - GenericInstanceType replicateULDelegateGit; - GenericInstanceType reconcileULDelegateGit; - GenericInstanceType lstDataGit; - GenericInstanceType queueDataGit; - GetGenericULDelegate(replicateDataTr, typeof(ReplicateUserLogicDelegate<>), out replicateULDelegateGit); - GetGenericULDelegate(reconcileDataTr, typeof(ReconcileUserLogicDelegate<>), out reconcileULDelegateGit); - gh.GetGenericLists(replicateDataTr, out lstDataGit); - gh.GetGenericQueues(replicateDataTr, out queueDataGit); - - /* Data buffer. */ - FieldDefinition replicateULDelegateFd = new FieldDefinition($"_replicateULDelegate___{replicateMd.Name}", FieldAttributes.Private, replicateULDelegateGit); - FieldDefinition reconcileULDelegateFd = new FieldDefinition($"_reconcileULDelegate___{reconcileMd.Name}", FieldAttributes.Private, reconcileULDelegateGit); - FieldDefinition serverReplicatesFd = new FieldDefinition($"_serverReplicates___{replicateMd.Name}", FieldAttributes.Private, queueDataGit); - FieldDefinition clientReplicatesFd = new FieldDefinition($"_clientReplicates___{replicateMd.Name}", FieldAttributes.Private, lstDataGit); - FieldDefinition reconcileDataFd = new FieldDefinition($"_reconcileData___{replicateMd.Name}", FieldAttributes.Private, reconcileDataTr); - FieldDefinition serverReplicatesReadBufferFd = new FieldDefinition($"{replicateMd.Name}___serverReplicateReadBuffer", FieldAttributes.Private, replicateDataArrTr); - - typeDef.Fields.Add(replicateULDelegateFd); - typeDef.Fields.Add(reconcileULDelegateFd); - typeDef.Fields.Add(serverReplicatesFd); - typeDef.Fields.Add(clientReplicatesFd); - typeDef.Fields.Add(reconcileDataFd); - typeDef.Fields.Add(serverReplicatesReadBufferFd); - - predictionFields = new CreatedPredictionFields(replicateULDelegateFd, reconcileULDelegateFd, serverReplicatesFd, clientReplicatesFd, reconcileDataFd, - serverReplicatesReadBufferFd); - } - - /// - /// Returns if there are any errors with the prediction methods parameters and will print if so. - /// - private bool HasParameterError(MethodDefinition methodDef, TypeDefinition typeDef, bool replicateMethod) - { - //Replicate: data, asServer, channel, replaying. - //Reconcile: data, asServer, channel. - int count = (replicateMethod) ? 4 : 3; - - //Check parameter count. - if (methodDef.Parameters.Count != count) - { - PrintParameterExpectations(); - return true; - } - - //Data check. - if (!methodDef.Parameters[0].ParameterType.IsClassOrStruct(base.Session)) - { - base.LogError($"Prediction methods must use a class or structure as the first parameter type. Structures are recommended to avoid allocations."); - return true; - } - //asServer - if (methodDef.Parameters[1].ParameterType.Name != typeof(bool).Name) - { - PrintParameterExpectations(); - return true; - } - //Channel. - if (methodDef.Parameters[2].ParameterType.Name != typeof(Channel).Name) - { - PrintParameterExpectations(); - return true; - } - if (replicateMethod) - { - //replaying - if (methodDef.Parameters[3].ParameterType.Name != typeof(bool).Name) - { - PrintParameterExpectations(); - return true; - } - - } - - void PrintParameterExpectations() - { - if (replicateMethod) - base.LogError($"Replicate method {methodDef.Name} within {typeDef.Name} requires exactly {count} parameters. In order: replicate data, asServer boolean, channel = Channel.Unreliable, replaying boolean."); - else - base.LogError($"Reconcile method {methodDef.Name} within {typeDef.Name} requires exactly {count} parameters. In order: replicate data, asServer boolean, channel = Channel.Unreliable."); - } - - //No errors with parameters. - return false; - } - - /// - /// Creates all methods needed for a RPC. - /// - /// - /// - /// - private bool CreatePredictionMethods(TypeDefinition typeDef, MethodDefinition replicateMd, MethodDefinition reconcileMd, CreatedPredictionFields predictionFields, uint rpcCount, out PredictionReaders predictionReaders, out MethodDefinition replicateULMd, out MethodDefinition reconcileULMd) - { - GeneralHelper gh = base.GetClass(); - NetworkBehaviourHelper nbh = base.GetClass(); - predictionReaders = null; - - string copySuffix = "___UL"; - replicateULMd = base.GetClass().CopyIntoNewMethod(replicateMd, $"{replicateMd.Name}{copySuffix}", out _); - reconcileULMd = base.GetClass().CopyIntoNewMethod(reconcileMd, $"{reconcileMd.Name}{copySuffix}", out _); - replicateMd.Body.Instructions.Clear(); - reconcileMd.Body.Instructions.Clear(); - - MethodDefinition replicateReader; - MethodDefinition reconcileReader; - - if (!CreateReplicate()) - return false; - if (!CreateReconcile()) - return false; - - CreateClearReplicateCacheMethod(typeDef, replicateMd.Parameters[0].ParameterType, predictionFields); - CreateReplicateReader(typeDef, replicateMd, predictionFields, out replicateReader); - CreateReconcileReader(typeDef, reconcileMd, predictionFields, out reconcileReader); - predictionReaders = new PredictionReaders(replicateReader, reconcileReader); - - bool CreateReplicate() - { - ILProcessor processor = replicateMd.Body.GetILProcessor(); - ParameterDefinition replicateDataPd = replicateMd.Parameters[0]; - MethodDefinition comparerMd = gh.CreateEqualityComparer(replicateDataPd.ParameterType); - gh.CreateIsDefaultComparer(replicateDataPd.ParameterType, comparerMd); - ParameterDefinition asServerPd = replicateMd.Parameters[1]; - ParameterDefinition replayingPd = replicateMd.Parameters[3]; - - Instruction exitMethodInst = processor.Create(OpCodes.Nop); - //Exit early conditions. - processor.Emit(OpCodes.Ldarg_0); //base. - processor.Emit(OpCodes.Ldarg, asServerPd); - processor.Emit(OpCodes.Ldarg, replayingPd); - processor.Emit(OpCodes.Call, base.GetClass().Replicate_ExitEarly_A_MethodRef); - processor.Emit(OpCodes.Brtrue, exitMethodInst); - - //Wrap server content in an asServer if statement. - Instruction notAsServerInst = processor.Create(OpCodes.Nop); - processor.Emit(OpCodes.Ldarg, asServerPd); - processor.Emit(OpCodes.Brfalse, notAsServerInst); - /***************************/ - ServerCreateReplicate(replicateMd, predictionFields); - processor.Emit(OpCodes.Br, exitMethodInst); - /***************************/ - - //Wrap client content in an !asServer if statement. - processor.Append(notAsServerInst); - /***************************/ - ClientCreateReplicate(replicateMd, predictionFields, rpcCount); - /***************************/ - - processor.Append(exitMethodInst); - processor.Emit(OpCodes.Ret); - - return true; - } - - - bool CreateReconcile() - { - ILProcessor processor = reconcileMd.Body.GetILProcessor(); - ParameterDefinition reconcileDataPd = reconcileMd.Parameters[0]; - ParameterDefinition asServerPd = reconcileMd.Parameters[1]; - ParameterDefinition channelPd = reconcileMd.Parameters[2]; - TypeReference replicateDataTr = replicateMd.Parameters[0].ParameterType; - - //ExitEarly A. - Instruction exitMethodInst = processor.Create(OpCodes.Nop); - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldarg, asServerPd); - processor.Emit(OpCodes.Ldarga, channelPd); - processor.Emit(OpCodes.Call, base.GetClass().Reconcile_ExitEarly_A_MethodRef); - processor.Emit(OpCodes.Brtrue, exitMethodInst); - - //Wrap server content in an asServer if statement. - Instruction notAsServerInst = processor.Create(OpCodes.Nop); - processor.Emit(OpCodes.Ldarg, asServerPd); - processor.Emit(OpCodes.Brfalse, notAsServerInst); - /***************************/ - ServerCreateReconcile(reconcileMd, predictionFields, ref rpcCount); - /***************************/ - processor.Emit(OpCodes.Br, exitMethodInst); - - processor.Append(notAsServerInst); - - MethodReference reconcileClientGim = nbh.Reconcile_Client_MethodRef.GetMethodReference( - base.Session, new TypeReference[] { reconcileDataPd.ParameterType, replicateDataTr }); - //(ReplicateULDelegate replicateDel, ReconcileULDelegate reconcileDel, List collection, - //T data, Channel channel) where T : IReconcileData - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldfld, predictionFields.ReconcileULDelegate); - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldfld, predictionFields.ReplicateULDelegate); - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldfld, predictionFields.ClientReplicateDatas); - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldfld, predictionFields.ReconcileData); - processor.Emit(OpCodes.Ldarg, channelPd); - processor.Emit(OpCodes.Call, reconcileClientGim); - - processor.Append(exitMethodInst); - processor.Emit(OpCodes.Ret); - return true; - } - - return true; - } - - #region Universal prediction. - /// - /// Creates an override for the method responsible for resetting replicates. - /// - /// - /// - private void CreateClearReplicateCacheMethod(TypeDefinition typeDef, TypeReference dataTr, CreatedPredictionFields predictionFields) - { - GeneralHelper gh = base.GetClass(); - string clearDatasName = base.GetClass().ClearReplicateCache_Method_Name; - MethodDefinition md = typeDef.GetMethod(clearDatasName); - - //Already exist when it shouldn't. - if (md != null) - { - base.LogWarning($"{typeDef.Name} overrides method {md.Name} when it should not. Logic within {md.Name} will be replaced by code generation."); - md.Body.Instructions.Clear(); - } - else - { - md = new MethodDefinition(clearDatasName, (MethodAttributes.Public | MethodAttributes.Virtual), base.Module.TypeSystem.Void); - gh.CreateParameter(md, typeof(bool), "asServer"); - typeDef.Methods.Add(md); - base.ImportReference(md); - } - - ILProcessor processor = md.Body.GetILProcessor(); - - GenericInstanceType dataListGit; - gh.GetGenericLists(dataTr, out dataListGit); - //Get clear method. - MethodReference lstClearMr = gh.List_Clear_MethodRef.MakeHostInstanceGeneric(base.Session, dataListGit); - ParameterDefinition asServerPd = md.Parameters[0]; - - Instruction afterAsServerInst = processor.Create(OpCodes.Nop); - Instruction resetTicksInst = processor.Create(OpCodes.Nop); - - processor.Emit(OpCodes.Ldarg, asServerPd); - processor.Emit(OpCodes.Brfalse_S, afterAsServerInst); - - //Clear on server replicates. - MethodReference clrQueueMr = base.ImportReference(typeof(NetworkBehaviour).GetMethod(nameof(NetworkBehaviour.ClearQueue_Server_Internal))); - GenericInstanceMethod clrQueueGim = clrQueueMr.MakeGenericMethod(new TypeReference[] { dataTr }); - - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldfld, predictionFields.ServerReplicateDatas); - processor.Emit(clrQueueMr.GetCallOpCode(base.Session), clrQueueGim); - processor.Emit(OpCodes.Br_S, resetTicksInst); - processor.Append(afterAsServerInst); - //Clear on client replicates. - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldfld, predictionFields.ClientReplicateDatas); - processor.Emit(lstClearMr.GetCallOpCode(base.Session), lstClearMr); - - processor.Append(resetTicksInst); - processor.Emit(OpCodes.Ret); - } - - /// - /// Outputs generic ReplicateULDelegate for dataTr. - /// - private void GetGenericULDelegate(TypeReference dataTr, System.Type delegateType, out GenericInstanceType git) - { - TypeReference delDataTr = base.ImportReference(delegateType); - git = delDataTr.MakeGenericInstanceType(new TypeReference[] { dataTr }); - } - - /// - /// Subtracts 1 from a field. - /// - private List SubtractFromField(MethodDefinition methodDef, FieldDefinition fieldDef) - { - List insts = new List(); - ILProcessor processor = methodDef.Body.GetILProcessor(); - - // _field--; - insts.Add(processor.Create(OpCodes.Ldarg_0)); - insts.Add(processor.Create(OpCodes.Ldarg_0)); - insts.Add(processor.Create(OpCodes.Ldfld, fieldDef)); - insts.Add(processor.Create(OpCodes.Ldc_I4_1)); - insts.Add(processor.Create(OpCodes.Sub)); - insts.Add(processor.Create(OpCodes.Stfld, fieldDef)); - - return insts; - } - /// - /// Subtracts 1 from a variable. - /// - private List SubtractFromVariable(MethodDefinition methodDef, VariableDefinition variableDef) - { - List insts = new List(); - ILProcessor processor = methodDef.Body.GetILProcessor(); - - // variable--; - insts.Add(processor.Create(OpCodes.Ldloc, variableDef)); - insts.Add(processor.Create(OpCodes.Ldc_I4_1)); - insts.Add(processor.Create(OpCodes.Sub)); - insts.Add(processor.Create(OpCodes.Stloc, variableDef)); - - return insts; - } - - /// - /// Subtracts 1 from a variable. - /// - private List SubtractOneVariableFromAnother(MethodDefinition methodDef, VariableDefinition srcVd, VariableDefinition modifierVd) - { - List insts = new List(); - ILProcessor processor = methodDef.Body.GetILProcessor(); - - // variable -= v2; - insts.Add(processor.Create(OpCodes.Ldloc, srcVd)); - insts.Add(processor.Create(OpCodes.Ldloc, modifierVd)); - insts.Add(processor.Create(OpCodes.Sub)); - insts.Add(processor.Create(OpCodes.Stloc, srcVd)); - - return insts; - } - #endregion - - #region Server side. - /// - /// Creates replicate code for client. - /// - private void ServerCreateReplicate(MethodDefinition replicateMd, CreatedPredictionFields predictionFields) - { - ILProcessor processor = replicateMd.Body.GetILProcessor(); - - ParameterDefinition replicateDataPd = replicateMd.Parameters[0]; - ParameterDefinition channelPd = replicateMd.Parameters[2]; - TypeReference replicateDataTr = replicateDataPd.ParameterType; - - GenericInstanceMethod replicateGim = base.GetClass().Replicate_Server_MethodRef.MakeGenericMethod(new TypeReference[] { replicateDataTr }); - - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldfld, predictionFields.ReplicateULDelegate); - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldfld, predictionFields.ServerReplicateDatas); - processor.Emit(OpCodes.Ldarg, channelPd); - processor.Emit(OpCodes.Call, replicateGim); - } - - /// - /// Creates a reader for replicate data received from clients. - /// - private bool CreateReplicateReader(TypeDefinition typeDef, MethodDefinition replicateMd, CreatedPredictionFields predictionFields, out MethodDefinition result) - { - string methodName = $"{REPLICATE_READER_PREFIX}{replicateMd.Name}"; - MethodDefinition createdMd = new MethodDefinition(methodName, - MethodAttributes.Private, - replicateMd.Module.TypeSystem.Void); - typeDef.Methods.Add(createdMd); - createdMd.Body.InitLocals = true; - - ILProcessor processor = createdMd.Body.GetILProcessor(); - - GeneralHelper gh = base.GetClass(); - NetworkBehaviourHelper nbh = base.GetClass(); - - TypeReference dataTr = replicateMd.Parameters[0].ParameterType; - //Create parameters. - ParameterDefinition readerPd = gh.CreateParameter(createdMd, typeof(PooledReader)); - ParameterDefinition networkConnectionPd = gh.CreateParameter(createdMd, typeof(NetworkConnection)); - ParameterDefinition channelPd = gh.CreateParameter(createdMd, typeof(Channel)); - - MethodReference replicateReaderGim = nbh.Replicate_Reader_MethodRef.GetMethodReference(base.Session, dataTr); - - processor.Emit(OpCodes.Ldarg_0); - //Reader, NetworkConnection. - processor.Emit(OpCodes.Ldarg, readerPd); - processor.Emit(OpCodes.Ldarg, networkConnectionPd); - //arrBuffer. - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldfld, predictionFields.ServerReplicateReaderBuffer); - //replicates. - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldfld, predictionFields.ServerReplicateDatas); - //Channel. - processor.Emit(OpCodes.Ldarg, channelPd); - processor.Emit(OpCodes.Call, replicateReaderGim); - //Add end of method. - processor.Emit(OpCodes.Ret); - result = createdMd; - return true; - } - - /// - /// Creates server side code for reconcileMd. - /// - /// - /// - private void ServerCreateReconcile(MethodDefinition reconcileMd, CreatedPredictionFields predictionFields, ref uint rpcCount) - { - ParameterDefinition reconcileDataPd = reconcileMd.Parameters[0]; - ParameterDefinition channelPd = reconcileMd.Parameters[2]; - ILProcessor processor = reconcileMd.Body.GetILProcessor(); - - GenericInstanceMethod methodGim = base.GetClass().Reconcile_Server_MethodRef.MakeGenericMethod(new TypeReference[] { reconcileDataPd.ParameterType }); - - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldc_I4, (int)rpcCount); - processor.Emit(OpCodes.Ldarg, reconcileDataPd); - processor.Emit(OpCodes.Ldarg, channelPd); - processor.Emit(OpCodes.Call, methodGim); - - rpcCount++; - } - #endregion - - #region Client side. - /// - /// Creates replicate code for client. - /// - private void ClientCreateReplicate(MethodDefinition replicateMd, CreatedPredictionFields predictionFields, uint rpcCount) - { - ParameterDefinition dataPd = replicateMd.Parameters[0]; - ParameterDefinition channelPd = replicateMd.Parameters[2]; - TypeReference dataTr = dataPd.ParameterType; - - ILProcessor processor = replicateMd.Body.GetILProcessor(); - - //Make method reference NB.SendReplicateRpc - GenericInstanceMethod replicateClientGim = base.GetClass().Replicate_Client_MethodRef.MakeGenericMethod(new TypeReference[] { dataTr }); - processor.Emit(OpCodes.Ldarg_0);//base. - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldfld, predictionFields.ReplicateULDelegate); - processor.Emit(OpCodes.Ldc_I4, (int)rpcCount); - processor.Emit(OpCodes.Ldarg_0);//this. - processor.Emit(OpCodes.Ldfld, predictionFields.ClientReplicateDatas.CachedResolve(base.Session)); - processor.Emit(OpCodes.Ldarg, dataPd); - processor.Emit(OpCodes.Ldarg, channelPd); - processor.Emit(OpCodes.Call, replicateClientGim); - } - - /// - /// Creates a reader for replicate data received from clients. - /// - private bool CreateReconcileReader(TypeDefinition typeDef, MethodDefinition reconcileMd, CreatedPredictionFields predictionFields, out MethodDefinition result) - { - string methodName = $"{RECONCILE_READER_PREFIX}{reconcileMd.Name}"; - MethodDefinition createdMd = new MethodDefinition(methodName, - MethodAttributes.Private, - reconcileMd.Module.TypeSystem.Void); - typeDef.Methods.Add(createdMd); - createdMd.Body.InitLocals = true; - - ILProcessor processor = createdMd.Body.GetILProcessor(); - - GeneralHelper gh = base.GetClass(); - NetworkBehaviourHelper nbh = base.GetClass(); - - TypeReference dataTr = reconcileMd.Parameters[0].ParameterType; - //Create parameters. - ParameterDefinition readerPd = gh.CreateParameter(createdMd, typeof(PooledReader)); - ParameterDefinition channelPd = gh.CreateParameter(createdMd, typeof(Channel)); - - MethodReference methodGim = nbh.Reconcile_Reader_MethodRef.GetMethodReference(base.Session, dataTr); - - processor.Emit(OpCodes.Ldarg_0); - //Reader, data, channel. - processor.Emit(OpCodes.Ldarg, readerPd); - //Data to assign read value to. - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Ldflda, predictionFields.ReconcileData); - //Channel. - processor.Emit(OpCodes.Ldarg, channelPd); - processor.Emit(OpCodes.Call, methodGim); - //Add end of method. - processor.Emit(OpCodes.Ret); - - result = createdMd; - return true; - } - #endregion - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Processing/Prediction/PredictionProcessor.cs.meta b/Assets/FishNet/CodeGenerating/Processing/Prediction/PredictionProcessor.cs.meta deleted file mode 100644 index c8266bc..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Prediction/PredictionProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d0663606e86b0b34bae85df164747e72 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/QOLAttributeProcessor.cs b/Assets/FishNet/CodeGenerating/Processing/QOLAttributeProcessor.cs deleted file mode 100644 index dd5f02d..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/QOLAttributeProcessor.cs +++ /dev/null @@ -1,164 +0,0 @@ -using FishNet.CodeGenerating.Helping; -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.CodeGenerating.Processing.Rpc; -using FishNet.Configuring; -using FishNet.Managing.Logging; -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using System.Collections.Generic; -using System.Linq; - -namespace FishNet.CodeGenerating.Processing -{ - internal class QolAttributeProcessor : CodegenBase - { - - internal bool Process(TypeDefinition typeDef, bool moveStrippedCalls) - { - bool modified = false; - List methods = typeDef.Methods.ToList(); - - - - foreach (MethodDefinition md in methods) - { - //Has RPC attribute, doesn't quality for a quality of life attribute. - if (base.GetClass().Attributes.HasRpcAttributes(md)) - continue; - - QolAttributeType qolType; - CustomAttribute qolAttribute = GetQOLAttribute(md, out qolType); - if (qolAttribute == null) - continue; - - /* This is a one time check to make sure the qolType is - * a supported value. Multiple methods beyond this rely on the - * value being supported. Rather than check in each method a - * single check is performed here. */ - if (qolType != QolAttributeType.Server && qolType != QolAttributeType.Client) - { - base.LogError($"QolAttributeType of {qolType.ToString()} is unhandled."); - continue; - } - - CreateAttributeMethod(md, qolAttribute, qolType); - modified = true; - } - - return modified; - } - - /// - /// Returns the RPC attribute on a method, if one exist. Otherwise returns null. - /// - /// - /// - /// - private CustomAttribute GetQOLAttribute(MethodDefinition methodDef, out QolAttributeType qolType) - { - CustomAttribute foundAttribute = null; - qolType = QolAttributeType.None; - //Becomes true if an error occurred during this process. - bool error = false; - //Nothing to check. - if (methodDef == null || methodDef.CustomAttributes == null) - return null; - - foreach (CustomAttribute customAttribute in methodDef.CustomAttributes) - { - QolAttributeType thisQolType = base.GetClass().GetQolAttributeType(customAttribute.AttributeType.FullName); - if (thisQolType != QolAttributeType.None) - { - //A qol attribute already exist. - if (foundAttribute != null) - { - base.LogError($"{methodDef.Name} {thisQolType.ToString()} method cannot have multiple quality of life attributes."); - error = true; - } - ////Static method. - //if (methodDef.IsStatic) - //{ - // CodegenSession.AddError($"{methodDef.Name} {thisQolType.ToString()} method cannot be static."); - // error = true; - //} - //Abstract method. - if (methodDef.IsAbstract) - { - base.LogError($"{methodDef.Name} {thisQolType.ToString()} method cannot be abstract."); - error = true; - } - - //If all checks passed. - if (!error) - { - foundAttribute = customAttribute; - qolType = thisQolType; - } - } - } - - //If an error occurred then reset results. - if (error) - { - foundAttribute = null; - qolType = QolAttributeType.None; - } - - return foundAttribute; - } - - /// - /// Modifies the specified method to use QolType. - /// - private void CreateAttributeMethod(MethodDefinition methodDef, CustomAttribute qolAttribute, QolAttributeType qolType) - { - bool inheritsNetworkBehaviour = methodDef.DeclaringType.InheritsNetworkBehaviour(base.Session); - - //True to use InstanceFInder. - bool useStatic = (methodDef.IsStatic || !inheritsNetworkBehaviour); - - if (qolType == QolAttributeType.Client) - { - if (!StripMethod(methodDef)) - { - LoggingType logging = qolAttribute.GetField("Logging", LoggingType.Warning); - /* Since isClient also uses insert first - * it will be put ahead of the IsOwner check, since the - * codegen processes it after IsOwner. EG... - * IsOwner will be added first, then IsClient will be added first over IsOwner. */ - bool requireOwnership = qolAttribute.GetField("RequireOwnership", false); - if (requireOwnership && useStatic) - { - base.LogError($"Method {methodDef.Name} has a [Client] attribute which requires ownership but the method may not use this attribute. Either the method is static, or the script does not inherit from NetworkBehaviour."); - return; - } - //If (!base.IsOwner); - if (requireOwnership) - base.GetClass().CreateLocalClientIsOwnerCheck(methodDef, logging, true, false, true); - //Otherwise normal IsClient check. - else - base.GetClass().CreateIsClientCheck(methodDef, logging, useStatic, true); - } - } - else if (qolType == QolAttributeType.Server) - { - if (!StripMethod(methodDef)) - { - LoggingType logging = qolAttribute.GetField("Logging", LoggingType.Warning); - base.GetClass().CreateIsServerCheck(methodDef, logging, useStatic, true); - } - } - - bool StripMethod(MethodDefinition md) - { - - - //Fall through. - return false; - } - } - - - } - -} diff --git a/Assets/FishNet/CodeGenerating/Processing/QOLAttributeProcessor.cs.meta b/Assets/FishNet/CodeGenerating/Processing/QOLAttributeProcessor.cs.meta deleted file mode 100644 index ff1a0e7..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/QOLAttributeProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5080d7597ffca904b9a9fd5926e4e5a6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/ReaderProcessor.cs b/Assets/FishNet/CodeGenerating/Processing/ReaderProcessor.cs deleted file mode 100644 index c6abcb6..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/ReaderProcessor.cs +++ /dev/null @@ -1,1114 +0,0 @@ -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.Serializing; -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using MonoFN.Cecil.Rocks; -using SR = System.Reflection; -using System.Collections.Generic; -using System; -using FishNet.CodeGenerating.ILCore; -using FishNet.CodeGenerating.Extension; -using FishNet.Utility.Performance; -using FishNet.Object; - -namespace FishNet.CodeGenerating.Helping -{ - - internal class ReaderProcessor : CodegenBase - { - - #region Reflection references. - public TypeDefinition GeneratedReaderClassTypeDef; - public MethodDefinition GeneratedReaderOnLoadMethodDef; - public readonly Dictionary InstancedReaderMethods = new Dictionary(); - public readonly Dictionary StaticReaderMethods = new Dictionary(); - public HashSet AutoPackedMethods = new HashSet(new TypeReferenceComparer()); - #endregion - - #region Misc. - /// - /// TypeReferences which have already had delegates made for. - /// - private HashSet _delegatedTypes = new HashSet(); - #endregion - - #region Const. - /// - /// Namespace to use for generated serializers and delegates. - /// - public const string GENERATED_READER_NAMESPACE = WriterProcessor.GENERATED_WRITER_NAMESPACE; - /// - /// Name to use for generated serializers class. - /// - public const string GENERATED_WRITERS_CLASS_NAME = "GeneratedReaders___Internal"; - /// - /// Attributes to use for generated serializers class. - /// - public const TypeAttributes GENERATED_TYPE_ATTRIBUTES = (TypeAttributes.BeforeFieldInit | TypeAttributes.Class | TypeAttributes.AnsiClass | - TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.Abstract | TypeAttributes.Sealed); - /// - /// Name to use for InitializeOnce method. - /// - public const string INITIALIZEONCE_METHOD_NAME = WriterProcessor.INITIALIZEONCE_METHOD_NAME; - /// - /// Attributes to use for InitializeOnce method within generated serializer classes. - /// - public const MethodAttributes INITIALIZEONCE_METHOD_ATTRIBUTES = WriterProcessor.INITIALIZEONCE_METHOD_ATTRIBUTES; - /// - /// Attritbutes to use for generated serializers. - /// - public const MethodAttributes GENERATED_METHOD_ATTRIBUTES = WriterProcessor.GENERATED_METHOD_ATTRIBUTES; - /// - /// Prefix used which all instanced and user created serializers should start with. - /// - internal const string READ_PREFIX = "Read"; - /// - /// Class name to use for generated readers. - /// - internal const string GENERATED_READERS_CLASS_NAME = "GeneratedReaders___Internal"; - /// - /// Prefix to use for generated readers. - /// - private const string GENERATED_READ_PREFIX = "Read___"; - /// - /// Types to exclude from being scanned for auto serialization. - /// - public static System.Type[] EXCLUDED_AUTO_SERIALIZER_TYPES => WriterProcessor.EXCLUDED_AUTO_SERIALIZER_TYPES; - /// - /// Types to exclude from being scanned for auto serialization. - /// - public static string[] EXCLUDED_ASSEMBLY_PREFIXES => WriterProcessor.EXCLUDED_ASSEMBLY_PREFIXES; - #endregion - - public override bool ImportReferences() => true; - - public bool Process() - { - GeneralHelper gh = base.GetClass(); - - CreateGeneratedClassData(); - FindInstancedReaders(); - CreateInstancedReaderExtensions(); - - void CreateGeneratedClassData() - { - GeneratedReaderClassTypeDef = gh.GetOrCreateClass(out _, ReaderProcessor.GENERATED_TYPE_ATTRIBUTES, ReaderProcessor.GENERATED_READERS_CLASS_NAME, null, WriterProcessor.GENERATED_WRITER_NAMESPACE); - /* If constructor isn't set then try to get or create it - * and also add it to methods if were created. */ - GeneratedReaderOnLoadMethodDef = gh.GetOrCreateMethod(GeneratedReaderClassTypeDef, out _, INITIALIZEONCE_METHOD_ATTRIBUTES, INITIALIZEONCE_METHOD_NAME, base.Module.TypeSystem.Void); - gh.CreateRuntimeInitializeOnLoadMethodAttribute(GeneratedReaderOnLoadMethodDef); - - ILProcessor ppp = GeneratedReaderOnLoadMethodDef.Body.GetILProcessor(); - ppp.Emit(OpCodes.Ret); - //GeneratedReaderOnLoadMethodDef.DeclaringType.Methods.Remove(GeneratedReaderOnLoadMethodDef); - } - - void FindInstancedReaders() - { - Type pooledWriterType = typeof(PooledReader); - foreach (SR.MethodInfo methodInfo in pooledWriterType.GetMethods()) - { - if (IsSpecialReadMethod(methodInfo)) - continue; - bool autoPackMethod; - if (IsIgnoredReadMethod(methodInfo, out autoPackMethod)) - continue; - - MethodReference methodRef = base.ImportReference(methodInfo); - /* TypeReference for the return type - * of the read method. */ - TypeReference typeRef = base.ImportReference(methodRef.ReturnType); - - /* If here all checks pass. */ - AddReaderMethod(typeRef, methodRef, true, true); - if (autoPackMethod) - AutoPackedMethods.Add(typeRef); - } - } - - return true; - } - - - /// - /// Returns if a MethodInfo is considered a special write method. - /// Special read methods have declared references within this class, and will not have extensions made for them. - /// - public bool IsSpecialReadMethod(SR.MethodInfo methodInfo) - { - /* Special methods. */ - if (methodInfo.Name == nameof(PooledReader.ReadPackedWhole)) - return true; - else if (methodInfo.Name == nameof(PooledReader.ReadArray)) - return true; - else if (methodInfo.Name == nameof(PooledReader.ReadDictionary)) - return true; - - return false; - } - - /// - /// Returns if a read method should be ignored. - /// - public bool IsIgnoredReadMethod(SR.MethodInfo methodInfo, out bool autoPackMethod) - { - autoPackMethod = false; - - if (base.GetClass().CodegenExclude(methodInfo)) - return true; - //Not long enough to be a write method. - else if (methodInfo.Name.Length < READ_PREFIX.Length) - return true; - //Method name doesn't start with writePrefix. - else if (methodInfo.Name.Substring(0, READ_PREFIX.Length) != READ_PREFIX) - return true; - SR.ParameterInfo[] parameterInfos = methodInfo.GetParameters(); - //Can have at most one parameter for packing. - if (parameterInfos.Length > 1) - return true; - //If has one parameter make sure it's a packing type. - if (parameterInfos.Length == 1) - { - autoPackMethod = (parameterInfos[0].ParameterType == typeof(AutoPackType)); - if (!autoPackMethod) - return true; - } - - return false; - } - - - - /// - /// Adds typeRef, methodDef to instanced or readerMethods. - /// - /// - /// - /// - internal void AddReaderMethod(TypeReference typeRef, MethodReference methodRef, bool instanced, bool useAdd) - { - string fullName = typeRef.GetFullnameWithoutBrackets(); - Dictionary dict = (instanced) ? - InstancedReaderMethods : StaticReaderMethods; - - if (useAdd) - dict.Add(fullName, methodRef); - else - dict[fullName] = methodRef; - } - - - /// - /// Creates a Read delegate for readMethodRef and places it within the generated reader/writer constructor. - /// - /// - /// - internal void CreateReadDelegate(MethodReference readMr, bool isStatic) - { - GeneralHelper gh = base.GetClass(); - ReaderImports ri = base.GetClass(); - - if (!isStatic) - { - //Supporting Write with types containing generics is more trouble than it's worth. - if (readMr.IsGenericInstance || readMr.HasGenericParameters) - return; - } - - //Check if ret already exist, if so remove it; ret will be added on again in this method. - if (GeneratedReaderOnLoadMethodDef.Body.Instructions.Count != 0) - { - int lastIndex = (GeneratedReaderOnLoadMethodDef.Body.Instructions.Count - 1); - if (GeneratedReaderOnLoadMethodDef.Body.Instructions[lastIndex].OpCode == OpCodes.Ret) - GeneratedReaderOnLoadMethodDef.Body.Instructions.RemoveAt(lastIndex); - } - //Check if already exist. - ILProcessor processor = GeneratedReaderOnLoadMethodDef.Body.GetILProcessor(); - TypeReference dataTypeRef = readMr.ReturnType; - if (_delegatedTypes.Contains(dataTypeRef)) - { - base.LogError($"Generic read already created for {dataTypeRef.FullName}."); - return; - } - else - { - _delegatedTypes.Add(dataTypeRef); - } - - //Create a Func delegate - processor.Emit(OpCodes.Ldnull); - processor.Emit(OpCodes.Ldftn, readMr); - - GenericInstanceType functionGenericInstance; - MethodReference functionConstructorInstanceMethodRef; - bool isAutoPacked = IsAutoPackedType(dataTypeRef); - - //Generate for autopacktype. - if (isAutoPacked) - { - functionGenericInstance = gh.FunctionT3TypeRef.MakeGenericInstanceType(ri.ReaderTypeRef, base.GetClass().AutoPackTypeRef, dataTypeRef); - functionConstructorInstanceMethodRef = gh.FunctionT3ConstructorMethodRef.MakeHostInstanceGeneric(base.Session, functionGenericInstance); - } - //Not autopacked. - else - { - functionGenericInstance = gh.FunctionT2TypeRef.MakeGenericInstanceType(ri.ReaderTypeRef, dataTypeRef); - functionConstructorInstanceMethodRef = gh.FunctionT2ConstructorMethodRef.MakeHostInstanceGeneric(base.Session, functionGenericInstance); - } - processor.Emit(OpCodes.Newobj, functionConstructorInstanceMethodRef); - - //Call delegate to GeneratedReader.Read - GenericInstanceType genericInstance = ri.GenericReaderTypeRef.MakeGenericInstanceType(dataTypeRef); - MethodReference genericReadMethodRef = (isAutoPacked) ? - ri.ReadAutoPackSetMethodRef.MakeHostInstanceGeneric(base.Session, genericInstance) : - ri.ReadSetMethodRef.MakeHostInstanceGeneric(base.Session, genericInstance); - processor.Emit(OpCodes.Call, genericReadMethodRef); - - processor.Emit(OpCodes.Ret); - } - - /// - /// Creates reader extension methods for built-in readers. - /// - private void CreateInstancedReaderExtensions() - { - if (!FishNetILPP.IsFishNetAssembly(base.Session)) - return; - - GeneralHelper gh = base.GetClass(); - ReaderProcessor gwh = base.GetClass(); - - //List staticReaders = new List(); - foreach (KeyValuePair item in InstancedReaderMethods) - { - MethodReference instancedReadMr = item.Value; - if (instancedReadMr.ContainsGenericParameter) - continue; - - TypeReference returnTr = base.ImportReference(instancedReadMr.ReturnType); - - MethodDefinition md = new MethodDefinition($"InstancedExtension___{instancedReadMr.Name}", - WriterProcessor.GENERATED_METHOD_ATTRIBUTES, - returnTr); - //Add extension parameter. - ParameterDefinition readerPd = gh.CreateParameter(md, typeof(Reader), "reader"); - //Add parameters needed by instanced writer. - List otherPds = md.CreateParameters(base.Session, instancedReadMr); - gh.MakeExtensionMethod(md); - // - gwh.GeneratedReaderClassTypeDef.Methods.Add(md); - - ILProcessor processor = md.Body.GetILProcessor(); - //Load writer. - processor.Emit(OpCodes.Ldarg, readerPd); - //Load args. - foreach (ParameterDefinition pd in otherPds) - processor.Emit(OpCodes.Ldarg, pd); - //Call instanced. - processor.Emit(instancedReadMr.GetCallOpCode(base.Session), instancedReadMr); - processor.Emit(OpCodes.Ret); - - AddReaderMethod(returnTr, md, false, true); - } - } - - /// - /// Removes typeRef from static/instanced reader methods. - /// - internal void RemoveReaderMethod(TypeReference typeRef, bool instanced) - { - string fullName = typeRef.GetFullnameWithoutBrackets(); - Dictionary dict = (instanced) ? - InstancedReaderMethods : StaticReaderMethods; - - dict.Remove(fullName); - } - - /// - /// Creates read instructions returning instructions and outputing variable of read result. - /// - internal List CreateRead(MethodDefinition methodDef, ParameterDefinition readerParameterDef, TypeReference readTypeRef, out VariableDefinition createdVariableDef) - { - ILProcessor processor = methodDef.Body.GetILProcessor(); - List insts = new List(); - MethodReference readMr = GetOrCreateReadMethodReference(readTypeRef); - if (readMr != null) - { - //Make a local variable. - createdVariableDef = base.GetClass().CreateVariable(methodDef, readTypeRef); - //pooledReader.ReadBool(); - insts.Add(processor.Create(OpCodes.Ldarg, readerParameterDef)); - //If an auto pack method then insert default value. - if (AutoPackedMethods.Contains(readTypeRef)) - { - AutoPackType packType = base.GetClass().GetDefaultAutoPackType(readTypeRef); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)packType)); - } - - - TypeReference valueTr = readTypeRef; - /* If generic then find write class for - * data type. Currently we only support one generic - * for this. */ - if (valueTr.IsGenericInstance) - { - GenericInstanceType git = (GenericInstanceType)valueTr; - TypeReference genericTr = git.GenericArguments[0]; - readMr = readMr.GetMethodReference(base.Session, genericTr); - } - - insts.Add(processor.Create(OpCodes.Call, readMr)); - //Store into local variable. - insts.Add(processor.Create(OpCodes.Stloc, createdVariableDef)); - return insts; - } - else - { - base.LogError("Reader not found for " + readTypeRef.ToString()); - createdVariableDef = null; - return null; - } - } - - - - /// - /// Creates a read for fieldRef and populates it into a created variable of class or struct type. - /// - internal bool CreateReadIntoClassOrStruct(MethodDefinition readerMd, ParameterDefinition readerPd, MethodReference readMr, VariableDefinition objectVd, FieldReference valueFr) - { - if (readMr != null) - { - ILProcessor processor = readerMd.Body.GetILProcessor(); - /* How to load object instance. If it's a structure - * then it must be loaded by address. Otherwise if - * class Ldloc can be used. */ - OpCode loadOpCode = (objectVd.VariableType.IsValueType) ? - OpCodes.Ldloca : OpCodes.Ldloc; - - /* If generic then find write class for - * data type. Currently we only support one generic - * for this. */ - if (valueFr.FieldType.IsGenericInstance) - { - GenericInstanceType git = (GenericInstanceType)valueFr.FieldType; - TypeReference genericTr = git.GenericArguments[0]; - readMr = readMr.GetMethodReference(base.Session, genericTr); - } - - processor.Emit(loadOpCode, objectVd); - //reader. - processor.Emit(OpCodes.Ldarg, readerPd); - if (IsAutoPackedType(valueFr.FieldType)) - { - AutoPackType packType = base.GetClass().GetDefaultAutoPackType(valueFr.FieldType); - processor.Emit(OpCodes.Ldc_I4, (int)packType); - } - //reader.ReadXXXX(). - processor.Emit(OpCodes.Call, readMr); - //obj.Field = result / reader.ReadXXXX(). - processor.Emit(OpCodes.Stfld, valueFr); - - return true; - } - else - { - base.LogError($"Reader not found for {valueFr.FullName}."); - return false; - } - } - - - /// - /// Creates a read for fieldRef and populates it into a created variable of class or struct type. - /// - internal bool CreateReadIntoClassOrStruct(MethodDefinition methodDef, ParameterDefinition readerPd, MethodReference readMr, VariableDefinition objectVariableDef, MethodReference setMr, TypeReference readTr) - { - if (readMr != null) - { - ILProcessor processor = methodDef.Body.GetILProcessor(); - - /* How to load object instance. If it's a structure - * then it must be loaded by address. Otherwise if - * class Ldloc can be used. */ - OpCode loadOpCode = (objectVariableDef.VariableType.IsValueType) ? - OpCodes.Ldloca : OpCodes.Ldloc; - - /* If generic then find write class for - * data type. Currently we only support one generic - * for this. */ - if (readTr.IsGenericInstance) - { - GenericInstanceType git = (GenericInstanceType)readTr; - TypeReference genericTr = git.GenericArguments[0]; - readMr = readMr.GetMethodReference(base.Session, genericTr); - } - - processor.Emit(loadOpCode, objectVariableDef); - //reader. - processor.Emit(OpCodes.Ldarg, readerPd); - if (IsAutoPackedType(readTr)) - { - AutoPackType packType = base.GetClass().GetDefaultAutoPackType(readTr); - processor.Emit(OpCodes.Ldc_I4, (int)packType); - } - //reader.ReadXXXX(). - processor.Emit(OpCodes.Call, readMr); - //obj.Property = result / reader.ReadXXXX(). - processor.Emit(OpCodes.Call, setMr); - - return true; - } - else - { - base.LogError($"Reader not found for {readTr.FullName}."); - return false; - } - } - - - - - /// - /// Creates generic write delegates for all currently known write types. - /// - internal void CreateStaticMethodDelegates() - { - foreach (KeyValuePair item in StaticReaderMethods) - base.GetClass().CreateReadDelegate(item.Value, true); - } - - - /// - /// Returns if typeRef has a deserializer. - /// - /// - /// - /// - internal bool HasDeserializer(TypeReference typeRef, bool createMissing) - { - bool result = (GetInstancedReadMethodReference(typeRef) != null) || - (GetStaticReadMethodReference(typeRef) != null); - - if (!result && createMissing) - { - if (!base.GetClass().HasNonSerializableAttribute(typeRef.CachedResolve(base.Session))) - { - MethodReference methodRef = CreateReader(typeRef); - result = (methodRef != null); - } - } - - return result; - } - - - /// - /// Returns if typeRef supports auto packing. - /// - /// - /// - internal bool IsAutoPackedType(TypeReference typeRef) - { - return AutoPackedMethods.Contains(typeRef); - } - /// - /// Creates a null check on the first argument and returns a null object if result indicates to do so. - /// - internal void CreateRetOnNull(ILProcessor processor, ParameterDefinition readerParameterDef, VariableDefinition resultVariableDef, bool useBool) - { - Instruction endIf = processor.Create(OpCodes.Nop); - - if (useBool) - CreateReadBool(processor, readerParameterDef, resultVariableDef); - else - CreateReadPackedWhole(processor, readerParameterDef, resultVariableDef); - - //If (true or == -1) jmp to endIf. True is null. - processor.Emit(OpCodes.Ldloc, resultVariableDef); - if (useBool) - { - processor.Emit(OpCodes.Brfalse, endIf); - } - else - { - //-1 - processor.Emit(OpCodes.Ldc_I4_M1); - processor.Emit(OpCodes.Bne_Un_S, endIf); - } - //Insert null. - processor.Emit(OpCodes.Ldnull); - //Exit method. - processor.Emit(OpCodes.Ret); - //End of if check. - processor.Append(endIf); - } - - /// - /// Creates a call to WriteBoolean with value. - /// - /// - /// - /// - internal void CreateReadBool(ILProcessor processor, ParameterDefinition readerParameterDef, VariableDefinition localBoolVariableDef) - { - MethodReference readBoolMethodRef = GetReadMethodReference(base.GetClass().GetTypeReference(typeof(bool))); - processor.Emit(OpCodes.Ldarg, readerParameterDef); - processor.Emit(readBoolMethodRef.GetCallOpCode(base.Session), readBoolMethodRef); - processor.Emit(OpCodes.Stloc, localBoolVariableDef); - } - - /// - /// Creates a call to WritePackWhole with value. - /// - /// - /// - internal void CreateReadPackedWhole(ILProcessor processor, ParameterDefinition readerParameterDef, VariableDefinition resultVariableDef) - { - //Reader. - processor.Emit(OpCodes.Ldarg, readerParameterDef); - //Reader.ReadPackedWhole(). - MethodReference readPwMr = base.GetClass().Reader_ReadPackedWhole_MethodRef; - processor.Emit(readPwMr.GetCallOpCode(base.Session), readPwMr); - processor.Emit(OpCodes.Conv_I4); - processor.Emit(OpCodes.Stloc, resultVariableDef); - } - - - #region GetReaderMethodReference. - /// - /// Returns the MethodReference for typeRef. - /// - /// - /// - internal MethodReference GetInstancedReadMethodReference(TypeReference typeRef) - { - string fullName = typeRef.GetFullnameWithoutBrackets(); - InstancedReaderMethods.TryGetValue(fullName, out MethodReference methodRef); - return methodRef; - } - /// - /// Returns the MethodReference for typeRef. - /// - /// - /// - internal MethodReference GetStaticReadMethodReference(TypeReference typeRef) - { - string fullName = typeRef.GetFullnameWithoutBrackets(); - StaticReaderMethods.TryGetValue(fullName, out MethodReference methodRef); - return methodRef; - } - /// - /// Returns the MethodReference for typeRef favoring instanced or static. Returns null if not found. - /// - /// - /// - /// - internal MethodReference GetReadMethodReference(TypeReference typeRef) - { - MethodReference result; - bool favorInstanced = false; - if (favorInstanced) - { - result = GetInstancedReadMethodReference(typeRef); - if (result == null) - result = GetStaticReadMethodReference(typeRef); - } - else - { - result = GetStaticReadMethodReference(typeRef); - if (result == null) - result = GetInstancedReadMethodReference(typeRef); - } - - return result; - } - /// - /// Returns the MethodReference for typeRef favoring instanced or static. - /// - /// - /// - /// - internal MethodReference GetOrCreateReadMethodReference(TypeReference typeRef) - { -#pragma warning disable CS0219 - bool favorInstanced = false; -#pragma warning restore CS0219 - //Try to get existing writer, if not present make one. - MethodReference readMethodRef = GetReadMethodReference(typeRef); - if (readMethodRef == null) - readMethodRef = CreateReader(typeRef); - - //If still null then return could not be generated. - if (readMethodRef == null) - { - base.LogError($"Could not create deserializer for {typeRef.FullName}."); - } - //Otherwise, check if generic and create writes for generic pararameters. - else if (typeRef.IsGenericInstance) - { - GenericInstanceType git = (GenericInstanceType)typeRef; - foreach (TypeReference item in git.GenericArguments) - { - MethodReference result = GetOrCreateReadMethodReference(item); - if (result == null) - { - base.LogError($"Could not create deserializer for {item.FullName}."); - return null; - } - } - } - - return readMethodRef; - } - #endregion - - - /// - /// Generates a reader for objectTypeReference if one does not already exist. - /// - /// - /// - internal MethodReference CreateReader(TypeReference objectTr) - { - MethodReference resultMr = null; - TypeDefinition objectTypeDef; - - SerializerType serializerType = base.GetClass().GetSerializerType(objectTr, false, out objectTypeDef); - if (serializerType != SerializerType.Invalid) - { - //Array. - if (serializerType == SerializerType.Array) - resultMr = CreateArrayReaderMethodReference(objectTr); - //Enum. - else if (serializerType == SerializerType.Enum) - resultMr = CreateEnumReaderMethodDefinition(objectTr); - else if (serializerType == SerializerType.Dictionary - || serializerType == SerializerType.List - || serializerType == SerializerType.ListCache) - resultMr = CreateGenericCollectionReaderMethodReference(objectTr, serializerType); - //NetworkBehaviour. - else if (serializerType == SerializerType.NetworkBehaviour) - resultMr = GetNetworkBehaviourReaderMethodReference(objectTr); - //Nullable. - else if (serializerType == SerializerType.Nullable) - resultMr = CreateNullableReaderMethodReference(objectTr); - //Class or struct. - else if (serializerType == SerializerType.ClassOrStruct) - resultMr = CreateClassOrStructReaderMethodReference(objectTr); - } - - //If was not created. - if (resultMr == null) - RemoveFromStaticReaders(objectTr); - - return resultMr; - } - - - /// - /// Removes from static writers. - /// - private void RemoveFromStaticReaders(TypeReference tr) - { - base.GetClass().RemoveReaderMethod(tr, false); - } - /// - /// Adds to static writers. - /// - private void AddToStaticReaders(TypeReference tr, MethodReference mr) - { - base.GetClass().AddReaderMethod(tr, mr.CachedResolve(base.Session), false, true); - } - - /// - /// Generates a reader for objectTypeReference if one does not already exist. - /// - /// - /// - private MethodReference CreateEnumReaderMethodDefinition(TypeReference objectTr) - { - MethodDefinition createdReaderMd = CreateStaticReaderStubMethodDefinition(objectTr); - AddToStaticReaders(objectTr, createdReaderMd); - - ILProcessor processor = createdReaderMd.Body.GetILProcessor(); - - //Get type reference for enum type. eg byte int - TypeReference underlyingTypeRef = objectTr.CachedResolve(base.Session).GetEnumUnderlyingTypeReference(); - //Get read method for underlying type. - MethodReference readMethodRef = base.GetClass().GetOrCreateReadMethodReference(underlyingTypeRef); - if (readMethodRef == null) - return null; - - ParameterDefinition readerParameterDef = createdReaderMd.Parameters[0]; - //reader.ReadXXX(). - processor.Emit(OpCodes.Ldarg, readerParameterDef); - if (base.GetClass().IsAutoPackedType(underlyingTypeRef)) - processor.Emit(OpCodes.Ldc_I4, (int)AutoPackType.Packed); - - processor.Emit(OpCodes.Call, readMethodRef); - - processor.Emit(OpCodes.Ret); - return base.ImportReference(createdReaderMd); - } - - - /// - /// Creates a read for a class type which inherits NetworkBehaviour. - /// - /// - /// - private MethodReference GetNetworkBehaviourReaderMethodReference(TypeReference objectTr) - { - MethodDefinition createdReaderMd = CreateStaticReaderStubMethodDefinition(objectTr); - AddToStaticReaders(objectTr, createdReaderMd); - - ILProcessor processor = createdReaderMd.Body.GetILProcessor(); - TypeReference networkBehaviourTypeRef = base.GetClass().GetTypeReference(typeof(NetworkBehaviour)); - - processor.Emit(OpCodes.Ldarg_0); - processor.Emit(OpCodes.Call, base.GetClass().GetReadMethodReference(networkBehaviourTypeRef)); - processor.Emit(OpCodes.Castclass, objectTr); - processor.Emit(OpCodes.Ret); - return base.ImportReference(createdReaderMd); - } - - /// - /// Creates a writer for an array. - /// - private MethodReference CreateArrayReaderMethodReference(TypeReference objectTr) - { - ReaderImports ri = base.GetClass(); - TypeReference valueTr = objectTr.GetElementType(); - - //Write not found. - if (GetOrCreateReadMethodReference(valueTr) == null) - return null; - - MethodDefinition createdMd = CreateStaticReaderStubMethodDefinition(objectTr); - AddToStaticReaders(objectTr, createdMd); - - //Find instanced writer to use. - MethodReference instancedWriteMr = ri.Reader_ReadArray_MethodRef; - //Make generic. - GenericInstanceMethod writeGim = instancedWriteMr.MakeGenericMethod(new TypeReference[] { valueTr }); - CallInstancedReader(createdMd, writeGim); - - return base.ImportReference(createdMd); - } - - - /// - /// Creates a reader for a dictionary. - /// - private MethodReference CreateDictionaryReaderMethodReference(TypeReference objectTr) - { - ReaderProcessor rp = base.GetClass(); - - GenericInstanceType genericInstance = (GenericInstanceType)objectTr; - base.ImportReference(genericInstance); - TypeReference keyTr = genericInstance.GenericArguments[0]; - TypeReference valueTr = genericInstance.GenericArguments[1]; - - /* Try to get instanced first for collection element type, if it doesn't exist then try to - * get/or make a one. */ - MethodReference keyWriteMr = rp.GetOrCreateReadMethodReference(keyTr); - MethodReference valueWriteMr = rp.GetOrCreateReadMethodReference(valueTr); - if (keyWriteMr == null || valueWriteMr == null) - return null; - - MethodDefinition createdReaderMd = CreateStaticReaderStubMethodDefinition(objectTr); - AddToStaticReaders(objectTr, createdReaderMd); - - GenericInstanceMethod readDictGim = base.GetClass().Reader_ReadDictionary_MethodRef.MakeGenericMethod(new TypeReference[] { keyTr, valueTr }); - CallInstancedReader(createdReaderMd, readDictGim); - - return base.ImportReference(createdReaderMd); - } - - - /// - /// Creates a writer for a variety of generic collections. - /// - private MethodReference CreateGenericCollectionReaderMethodReference(TypeReference objectTr, SerializerType st) - { - ReaderImports ri = base.GetClass(); - //Make value field generic. - GenericInstanceType genericInstance = (GenericInstanceType)objectTr; - base.ImportReference(genericInstance); - TypeReference valueTr = genericInstance.GenericArguments[0]; - - List genericArguments = new List(); - //Make sure all arguments have writers. - foreach (TypeReference gaTr in genericInstance.GenericArguments) - { - //Writer not found. - if (GetOrCreateReadMethodReference(gaTr) == null) - { - base.LogError($"Reader could not be found or created for type {gaTr.FullName}."); - return null; - } - genericArguments.Add(gaTr); - } - MethodReference valueWriteMr = GetOrCreateReadMethodReference(valueTr); - if (valueWriteMr == null) - return null; - - MethodDefinition createdMd = CreateStaticReaderStubMethodDefinition(objectTr); - AddToStaticReaders(objectTr, createdMd); - - //Find instanced writer to use. - MethodReference instancedReadMr; - if (st == SerializerType.Dictionary) - instancedReadMr = ri.Reader_ReadDictionary_MethodRef; - else if (st == SerializerType.List) - instancedReadMr = ri.Reader_ReadList_MethodRef; - else if (st == SerializerType.ListCache) - instancedReadMr = ri.Reader_ReadListCache_MethodRef; - else - instancedReadMr = null; - - //Not found. - if (instancedReadMr == null) - { - base.LogError($"Instanced reader not found for SerializerType {st} on object {objectTr.Name}."); - return null; - } - - //Make generic. - GenericInstanceMethod writeGim = instancedReadMr.MakeGenericMethod(genericArguments.ToArray()); - CallInstancedReader(createdMd, writeGim); - - return base.ImportReference(createdMd); - } - - - /// - /// Calls an instanced writer from a static writer. - /// - private void CallInstancedReader(MethodDefinition staticReaderMd, MethodReference instancedReaderMr) - { - ParameterDefinition readerPd = staticReaderMd.Parameters[0]; - ILProcessor processor = staticReaderMd.Body.GetILProcessor(); - processor.Emit(OpCodes.Ldarg, readerPd); - processor.Emit(instancedReaderMr.GetCallOpCode(base.Session), instancedReaderMr); - processor.Emit(OpCodes.Ret); - } - - ///// - ///// Create a reader for a list. - ///// - //private MethodReference CreateGenericTypeReader(TypeReference objectTr, SerializerType st) - //{ - // ReaderProcessor rp = base.GetClass(); - - // if (st != SerializerType.List && st != SerializerType.ListCache) - // { - // base.LogError($"Reader SerializerType {st} is not implemented"); - // return null; - // } - - // GenericInstanceType genericInstance = (GenericInstanceType)objectTr; - // base.ImportReference(genericInstance); - // TypeReference elementTr = genericInstance.GenericArguments[0]; - - // /* Try to get instanced first for collection element type, if it doesn't exist then try to - // * get/or make a one. */ - // MethodReference elementReadMr = rp.GetOrCreateReadMethodReference(elementTr); - // if (elementReadMr == null) - // return null; - - // TypeReference readerMethodTr = null; - // if (st == SerializerType.List) - // readerMethodTr = base.GetClass().GetTypeReference(typeof(List<>)); - // else if (st == SerializerType.ListCache) - // readerMethodTr = base.GetClass().GetTypeReference(typeof(ListCache<>)); - - // MethodReference readerMd = rp.GetReadMethodReference(readerMethodTr); - // MethodDefinition typedReaderMd = CreateStaticReaderStubMethodDefinition(objectTr); - - // AddToStaticReaders(objectTr, typedReaderMd); - - // ParameterDefinition readerPd = typedReaderMd.Parameters[0]; - - // //Find add method for list. - // MethodReference readerGim = readerMd.GetMethodReference(base.Session, elementTr); - // ILProcessor processor = readerMd.CachedResolve(base.Session).Body.GetILProcessor(); - // processor.Emit(OpCodes.Ldarg, readerPd); - // processor.Emit(OpCodes.Call, readerGim); - - // return elementReadMr; - //} - - - /// - /// Creates a reader method for a struct or class objectTypeRef. - /// - /// - /// - private MethodReference CreateNullableReaderMethodReference(TypeReference objectTr) - { - ReaderProcessor rp = base.GetClass(); - - GenericInstanceType objectGit = objectTr as GenericInstanceType; - TypeReference valueTr = objectGit.GenericArguments[0]; - - //Make sure object has a ctor. - MethodDefinition objectCtorMd = objectTr.GetConstructor(base.Session, 1); - if (objectCtorMd == null) - { - base.LogError($"{objectTr.Name} can't be deserialized because the nullable type does not have a constructor."); - return null; - } - - //Get the reader for the value. - MethodReference valueReaderMr = rp.GetOrCreateReadMethodReference(valueTr); - if (valueReaderMr == null) - return null; - - TypeDefinition objectTd = objectTr.CachedResolve(base.Session); - MethodDefinition createdReaderMd = CreateStaticReaderStubMethodDefinition(objectTr); - AddToStaticReaders(objectTr, createdReaderMd); - - ILProcessor processor = createdReaderMd.Body.GetILProcessor(); - - ParameterDefinition readerPd = createdReaderMd.Parameters[0]; - // create local for return value - VariableDefinition resultVd = base.GetClass().CreateVariable(createdReaderMd, objectTr); - - //Read if null into boolean. - VariableDefinition nullBoolVd = createdReaderMd.CreateVariable(base.Session, typeof(bool)); - rp.CreateReadBool(processor, readerPd, nullBoolVd); - - Instruction afterReturnNullInst = processor.Create(OpCodes.Nop); - processor.Emit(OpCodes.Ldloc, nullBoolVd); - processor.Emit(OpCodes.Brfalse, afterReturnNullInst); - //Return a null result. - base.GetClass().SetVariableDefinitionFromObject(processor, resultVd, objectTd); - processor.Emit(OpCodes.Ldloc, resultVd); - processor.Emit(OpCodes.Ret); - processor.Append(afterReturnNullInst); - - MethodReference initMr = objectCtorMd.MakeHostInstanceGeneric(base.Session, objectGit); - processor.Emit(OpCodes.Ldarg, readerPd); - //If an auto pack method then insert default value. - if (rp.IsAutoPackedType(valueTr)) - { - AutoPackType packType = base.GetClass().GetDefaultAutoPackType(valueTr); - processor.Emit(OpCodes.Ldc_I4, (int)packType); - } - processor.Emit(OpCodes.Call, valueReaderMr); - processor.Emit(OpCodes.Newobj, initMr); - processor.Emit(OpCodes.Ret); - - return base.ImportReference(createdReaderMd); - } - - - /// - /// Creates a reader method for a struct or class objectTypeRef. - /// - /// - /// - private MethodReference CreateClassOrStructReaderMethodReference(TypeReference objectTr) - { - MethodDefinition createdReaderMd = CreateStaticReaderStubMethodDefinition(objectTr); - AddToStaticReaders(objectTr, createdReaderMd); - - TypeDefinition objectTypeDef = objectTr.CachedResolve(base.Session); - ILProcessor processor = createdReaderMd.Body.GetILProcessor(); - - ParameterDefinition readerParameterDef = createdReaderMd.Parameters[0]; - // create local for return value - VariableDefinition objectVariableDef = base.GetClass().CreateVariable(createdReaderMd, objectTr); - - //If not a value type create a return null check. - if (!objectTypeDef.IsValueType) - { - VariableDefinition nullVariableDef = base.GetClass().CreateVariable(createdReaderMd, typeof(bool)); - //Load packed whole value into sizeVariableDef, exit if null indicator. - base.GetClass().CreateRetOnNull(processor, readerParameterDef, nullVariableDef, true); - } - - /* If here then not null. */ - //Make a new instance of object type and set to objectVariableDef. - base.GetClass().SetVariableDefinitionFromObject(processor, objectVariableDef, objectTypeDef); - if (!ReadFieldsAndProperties(createdReaderMd, readerParameterDef, objectVariableDef, objectTr)) - return null; - /* //codegen scriptableobjects seem to climb too high up to UnityEngine.Object when - * creating serializers/deserialized. Make sure this is not possible. */ - - //Load result and return it. - processor.Emit(OpCodes.Ldloc, objectVariableDef); - processor.Emit(OpCodes.Ret); - - return base.ImportReference(createdReaderMd); - } - - - /// - /// Reads all fields of objectTypeRef. - /// - private bool ReadFieldsAndProperties(MethodDefinition readerMd, ParameterDefinition readerPd, VariableDefinition objectVd, TypeReference objectTr) - { - ReaderProcessor rp = base.GetClass(); - - //This probably isn't needed but I'm too afraid to remove it. - if (objectTr.Module != base.Module) - objectTr = base.ImportReference(objectTr.CachedResolve(base.Session)); - - //Fields. - foreach (FieldDefinition fieldDef in objectTr.FindAllSerializableFields(base.Session - , ReaderProcessor.EXCLUDED_AUTO_SERIALIZER_TYPES, ReaderProcessor.EXCLUDED_ASSEMBLY_PREFIXES)) - { - FieldReference importedFr = base.ImportReference(fieldDef); - if (GetReadMethod(fieldDef.FieldType, out MethodReference readMr)) - rp.CreateReadIntoClassOrStruct(readerMd, readerPd, readMr, objectVd, importedFr); - } - - //Properties. - foreach (PropertyDefinition propertyDef in objectTr.FindAllSerializableProperties(base.Session - , ReaderProcessor.EXCLUDED_AUTO_SERIALIZER_TYPES, ReaderProcessor.EXCLUDED_ASSEMBLY_PREFIXES)) - { - if (GetReadMethod(propertyDef.PropertyType, out MethodReference readMr)) - { - MethodReference setMr = base.Module.ImportReference(propertyDef.SetMethod); - rp.CreateReadIntoClassOrStruct(readerMd, readerPd, readMr, objectVd, setMr, propertyDef.PropertyType); - } - } - - //Gets or creates writer method and outputs it. Returns true if method is found or created. - bool GetReadMethod(TypeReference tr, out MethodReference readMr) - { - tr = base.ImportReference(tr); - readMr = rp.GetOrCreateReadMethodReference(tr); - return (readMr != null); - } - - return true; - } - - - /// - /// Creates the stub for a new reader method. - /// - /// - /// - public MethodDefinition CreateStaticReaderStubMethodDefinition(TypeReference objectTypeRef, string nameExtension = WriterProcessor.GENERATED_WRITER_NAMESPACE) - { - string methodName = $"{GENERATED_READ_PREFIX}{objectTypeRef.FullName}{nameExtension}s"; - // create new reader for this type - TypeDefinition readerTypeDef = base.GetClass().GetOrCreateClass(out _, GENERATED_TYPE_ATTRIBUTES, GENERATED_READERS_CLASS_NAME, null); - MethodDefinition readerMethodDef = readerTypeDef.AddMethod(methodName, - ReaderProcessor.GENERATED_METHOD_ATTRIBUTES, - objectTypeRef); - - base.GetClass().CreateParameter(readerMethodDef, base.GetClass().Reader_TypeRef, "reader"); - readerMethodDef.Body.InitLocals = true; - - return readerMethodDef; - } - - - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Processing/ReaderProcessor.cs.meta b/Assets/FishNet/CodeGenerating/Processing/ReaderProcessor.cs.meta deleted file mode 100644 index d041ead..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/ReaderProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0f9d3654f5816c4409b88fa0602c6df4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/Rpc.meta b/Assets/FishNet/CodeGenerating/Processing/Rpc.meta deleted file mode 100644 index a1e3948..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Rpc.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: de5f90c539e844445be428ff2a2fdf29 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/Rpc/AttributeData.cs b/Assets/FishNet/CodeGenerating/Processing/Rpc/AttributeData.cs deleted file mode 100644 index 3d69a01..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Rpc/AttributeData.cs +++ /dev/null @@ -1,68 +0,0 @@ -using FishNet.CodeGenerating.Helping; -using FishNet.Object.Helping; -using MonoFN.Cecil; -using System.Collections.Generic; - -namespace FishNet.CodeGenerating.Processing.Rpc -{ - internal static class AttributeDataExtensions - { - - /// - /// Returns RpcTypes in datas. - /// - public static List GetRpcTypes(this List datas) - { - //RpcTypes for originalMd. - List rpcTypes = new List(); - foreach (AttributeData ad in datas) - rpcTypes.Add(ad.RpcType); - - return rpcTypes; - } - - /// - /// Gets CustomAttribute for rpcType - /// - public static CustomAttribute GetAttribute(this List datas, CodegenSession session, RpcType rpcType) - { - for (int i = 0; i < datas.Count; i++) - { - if (datas[i].RpcType == rpcType) - return datas[i].Attribute; - } - - session.LogError($"RpcType {rpcType} not found in datas."); - return null; - } - - - /// - /// Returns RpcType as flag through combining datas. - /// - /// - /// - public static RpcType GetCombinedRpcType(this List datas) - { - RpcType result = RpcType.None; - for (int i = 0; i < datas.Count; i++) - result |= datas[i].RpcType; - - return result; - } - } - - internal class AttributeData - { - public readonly CustomAttribute Attribute; - public readonly RpcType RpcType; - - public AttributeData(CustomAttribute attribute, RpcType rpcType) - { - Attribute = attribute; - RpcType = rpcType; - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Processing/Rpc/AttributeData.cs.meta b/Assets/FishNet/CodeGenerating/Processing/Rpc/AttributeData.cs.meta deleted file mode 100644 index 69cbe34..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Rpc/AttributeData.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 91f84e00db3d1ad448fb6a760afb6927 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/Rpc/Attributes.cs b/Assets/FishNet/CodeGenerating/Processing/Rpc/Attributes.cs deleted file mode 100644 index dbeb798..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Rpc/Attributes.cs +++ /dev/null @@ -1,166 +0,0 @@ -using FishNet.CodeGenerating.Helping; -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.Connection; -using FishNet.Object.Helping; -using MonoFN.Cecil; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace FishNet.CodeGenerating.Processing.Rpc -{ - internal class Attributes : CodegenBase - { - - /// - /// Returns if methodDef has any Rpc attribute. - /// - public bool HasRpcAttributes(MethodDefinition methodDef) - { - foreach (CustomAttribute customAttribute in methodDef.CustomAttributes) - { - RpcType rt = base.Session.GetClass().GetRpcAttributeType(customAttribute); - if (rt != RpcType.None) - return true; - } - - //Fall through, nothing found. - return false; - } - - /// - /// Returns a collection of RpcAttribute for methodDef. - /// - public List GetRpcAttributes(MethodDefinition methodDef) - { - List results = new List(); - string asyncAttributeFullName = typeof(AsyncStateMachineAttribute).FullName; - bool isAsync = false; - - foreach (CustomAttribute customAttribute in methodDef.CustomAttributes) - { - RpcType rt = base.Session.GetClass().GetRpcAttributeType(customAttribute); - if (rt != RpcType.None) - { - results.Add(new AttributeData(customAttribute, rt)); - } - //Not a rpc attribute. - else - { - //Check if async. - if (customAttribute.Is(asyncAttributeFullName)) - isAsync = true; - } - } - - //Nothing found, exit early. - if (results.Count == 0) - { - return results; - } - //If has at least one RPC attrivbute and is an async method. - else if (isAsync) - { - base.Session.LogError($"{methodDef.Name} is an async RPC. This feature is not currently supported. You may instead run an async method from this RPC."); - return new List(); - } - //If more than one attribute make sure the combination is allowed. - else if (results.Count >= 2) - { - RpcType allRpcTypes = results.GetCombinedRpcType(); - if (allRpcTypes != (RpcType.Observers | RpcType.Target)) - { - base.Session.LogError($"{methodDef.Name} contains multiple RPC attributes. Only ObserversRpc and TargetRpc attributes may be combined."); - return new List(); - } - } - - //Next validate that the method is setup properly for each rpcType. - foreach (AttributeData ad in results) - { - //If not valid then return empty list. - if (!IsRpcMethodValid(methodDef, ad.RpcType)) - return new List(); - } - - return results; - } - - /// - /// Returns if a RpcMethod can be serialized and has a proper signature. - /// - private bool IsRpcMethodValid(MethodDefinition methodDef, RpcType rpcType) - { - //Static method. - if (methodDef.IsStatic) - { - base.Session.LogError($"{methodDef.Name} RPC method cannot be static."); - return false; - } - //Is generic type. - else if (methodDef.HasGenericParameters) - { - base.Session.LogError($"{methodDef.Name} RPC method cannot contain generic parameters."); - return false; - } - //Abstract method. - else if (methodDef.IsAbstract) - { - base.Session.LogError($"{methodDef.Name} RPC method cannot be abstract."); - return false; - } - //Non void return. - else if (methodDef.ReturnType != methodDef.Module.TypeSystem.Void) - { - base.Session.LogError($"{methodDef.Name} RPC method must return void."); - return false; - } - //Misc failing conditions. - else - { - //Check for async attribute. - foreach (CustomAttribute ca in methodDef.CustomAttributes) - { - - } - } - //TargetRpc but missing correct parameters. - if (rpcType == RpcType.Target) - { - if (methodDef.Parameters.Count == 0 || !methodDef.Parameters[0].Is(typeof(NetworkConnection))) - { - base.Session.LogError($"Target RPC {methodDef.Name} must have a NetworkConnection as the first parameter."); - return false; - } - } - - //Make sure all parameters can be serialized. - for (int i = 0; i < methodDef.Parameters.Count; i++) - { - ParameterDefinition parameterDef = methodDef.Parameters[i]; - - //If NetworkConnection, TargetRpc, and first parameter. - if ((i == 0) && (rpcType == RpcType.Target) && parameterDef.Is(typeof(NetworkConnection))) - continue; - - if (parameterDef.ParameterType.IsGenericParameter) - { - base.Session.LogError($"RPC method{methodDef.Name} contains a generic parameter. This is currently not supported."); - return false; - } - - //Can be serialized/deserialized. - bool canSerialize = base.GetClass().HasSerializerAndDeserializer(parameterDef.ParameterType, true); - if (!canSerialize) - { - base.Session.LogError($"RPC method {methodDef.Name} parameter type {parameterDef.ParameterType.FullName} does not support serialization. Use a supported type or create a custom serializer."); - return false; - } - - } - - //Fall through, success. - return true; - } - - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Processing/Rpc/Attributes.cs.meta b/Assets/FishNet/CodeGenerating/Processing/Rpc/Attributes.cs.meta deleted file mode 100644 index e0ab4ab..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Rpc/Attributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 974ebf09757267941a86f92e5072258c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/Rpc/CreatedRpc.cs b/Assets/FishNet/CodeGenerating/Processing/Rpc/CreatedRpc.cs deleted file mode 100644 index c2bd411..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Rpc/CreatedRpc.cs +++ /dev/null @@ -1,58 +0,0 @@ -using FishNet.Object.Helping; -using MonoFN.Cecil; -using System.Collections.Generic; - -namespace FishNet.CodeGenerating.Processing.Rpc -{ - - internal class CreatedRpc - { - public MethodDefinition OriginalMethodDef; - public uint MethodHash; - public AttributeData AttributeData; - public MethodDefinition WriterMethodDef; - public MethodDefinition ReaderMethodDef; - public MethodDefinition LogicMethodDef; - public MethodDefinition RedirectMethodDef; - public bool RunLocally; - - public RpcType RpcType => AttributeData.RpcType; - public CustomAttribute Attribute => AttributeData.Attribute; - public TypeDefinition TypeDef => OriginalMethodDef.DeclaringType; - public ModuleDefinition Module => OriginalMethodDef.Module; - } - - - internal static class CreatedRpcExtensions - { - /// - /// Returns CreatedRpc for rpcType. - /// - /// - public static CreatedRpc GetCreatedRpc(this List lst, RpcType rpcType) - { - for (int i = 0; i < lst.Count; i++) - { - if (lst[i].RpcType == rpcType) - return lst[i]; - } - //Fall through. - return null; - } - - /// - /// Returns combined RpcType for all entries. - /// - /// - public static RpcType GetCombinedRpcType(this List lst) - { - RpcType result = RpcType.None; - for (int i = 0; i < lst.Count; i++) - result |= lst[i].RpcType; - - return result; - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Processing/Rpc/CreatedRpc.cs.meta b/Assets/FishNet/CodeGenerating/Processing/Rpc/CreatedRpc.cs.meta deleted file mode 100644 index bc68749..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Rpc/CreatedRpc.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c2176b6bfcc49934d8f36fba3df74d0c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/Rpc/RpcProcessor.cs b/Assets/FishNet/CodeGenerating/Processing/Rpc/RpcProcessor.cs deleted file mode 100644 index 4f2bd28..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Rpc/RpcProcessor.cs +++ /dev/null @@ -1,1084 +0,0 @@ -using FishNet.Utility.Extension; -using FishNet.CodeGenerating.Extension; -using FishNet.CodeGenerating.Helping; -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.Configuring; -using FishNet.Connection; -using FishNet.Managing.Logging; -using FishNet.Object.Helping; -using FishNet.Transporting; -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine; - -namespace FishNet.CodeGenerating.Processing.Rpc -{ - internal class RpcProcessor : CodegenBase - { - - #region Types. - private struct DelegateData - { - public RpcType RpcType; - public bool RunLocally; - public MethodDefinition OriginalMethodDef; - public MethodDefinition ReaderMethodDef; - public uint MethodHash; - public CustomAttribute RpcAttribute; - - public DelegateData(RpcType rpcType, bool runLocally, MethodDefinition originalMethodDef, MethodDefinition readerMethodDef, uint methodHash, CustomAttribute rpcAttribute) - { - RpcType = rpcType; - RunLocally = runLocally; - OriginalMethodDef = originalMethodDef; - ReaderMethodDef = readerMethodDef; - MethodHash = methodHash; - RpcAttribute = rpcAttribute; - } - } - - #endregion - - #region Public. - /// - /// Attribute helper. - /// - public Attributes Attributes = new Attributes(); - #endregion - - private List<(MethodDefinition, MethodDefinition)> _virtualRpcs = new List<(MethodDefinition createdLogicMd, MethodDefinition originalRpcMd)>(); - - #region Const. - private const string LOGIC_PREFIX = "RpcLogic___"; - private const string WRITER_PREFIX = "RpcWriter___"; - private const string READER_PREFIX = "RpcReader___"; - private const string REQUIREOWNERSHIP_NAME = "RequireOwnership"; - private const string RUNLOCALLY_NAME = "RunLocally"; - private const string EXCLUDEOWNER_NAME = "ExcludeOwner"; - private const string EXCLUDESERVER_NAME = "ExcludeServer"; - private const string BUFFERLAST_NAME = "BufferLast"; - private const string DATALENGTH_NAME = "DataLength"; - private const string VALIDATETARGET_NAME = "ValidateTarget"; - #endregion - - public override bool ImportReferences() - { - Attributes.Initialize(base.Session); - return base.ImportReferences(); - } - - internal bool ProcessLocal(TypeDefinition typeDef, ref uint rpcCount) - { - bool modified = false; - - //All createdRpcs for typeDef. - List typeDefCeatedRpcs = new List(); - List methodDefs = typeDef.Methods.ToList(); - foreach (MethodDefinition md in methodDefs) - { - if (rpcCount >= NetworkBehaviourHelper.MAX_RPC_ALLOWANCE) - { - base.LogError($"{typeDef.FullName} and inherited types exceed {NetworkBehaviourHelper.MAX_RPC_ALLOWANCE} RPC methods. Only {NetworkBehaviourHelper.MAX_RPC_ALLOWANCE} RPC methods are supported per inheritance hierarchy."); - return false; - } - - //Rpcs created for this method. - List createdRpcs = new List(); - List attributeDatas = Attributes.GetRpcAttributes(md); - bool success = true; - foreach (AttributeData ad in attributeDatas) - { - CreatedRpc cr = new CreatedRpc(); - cr.OriginalMethodDef = md; - cr.AttributeData = ad; - cr.MethodHash = rpcCount; - - /* This is a one time check to make sure the rpcType is - * a supported value. Multiple methods beyond this rely on the - * value being supported. Rather than check in each method a - * single check is performed here. */ - if (cr.RpcType != RpcType.Observers && cr.RpcType != RpcType.Server && cr.RpcType != RpcType.Target) - { - base.LogError($"RpcType of {cr.RpcType.ToString()} is unhandled."); - break; - } - - bool created = CreateRpcMethods(attributeDatas, cr); - if (created) - { - modified = true; - - typeDefCeatedRpcs.Add(cr); - createdRpcs.Add(cr); - - if (cr.LogicMethodDef != null && cr.LogicMethodDef.IsVirtual) - _virtualRpcs.Add((cr.LogicMethodDef, md)); - - rpcCount++; - } - else - { - success = false; - } - } - - //If at least one attribute was found and all rpc methods were made. - if (createdRpcs.Count > 0 && success) - RedirectOriginalToWriter(createdRpcs); - } - - if (modified) - { - foreach (CreatedRpc cr in typeDefCeatedRpcs) - { - base.GetClass().CreateRpcDelegate(cr.RunLocally, cr.TypeDef, - cr.ReaderMethodDef, cr.RpcType, cr.MethodHash, - cr.Attribute); - } - return true; - } - else - { - return false; - } - } - - /// - /// Returns the name to use for a RpcMethod. - /// - private string GetRpcMethodName(CreatedRpc cr) - { - return GetRpcMethodName(cr.RpcType, cr.OriginalMethodDef); - } - - /// - /// Returns the name to use for a RpcMethod. - /// - private string GetRpcMethodName(RpcType rpcType, MethodDefinition originalMd) - { - return $"{rpcType}_{GetMethodNameAsParameters(originalMd)}"; - } - - /// - /// Returns the method name with parameter types included within the name. - /// - public static string GetMethodNameAsParameters(MethodDefinition methodDef) - { - StringBuilder sb = new StringBuilder(); - foreach (ParameterDefinition pd in methodDef.Parameters) - sb.Append(pd.ParameterType.FullName); - - return $"{methodDef.Name}_{sb.ToString().GetStableHash32()}"; - } - - /// - /// Redirects base calls for overriden RPCs. - /// - internal void RedirectBaseCalls() - { - foreach ((MethodDefinition logicMd, MethodDefinition originalMd) in _virtualRpcs) - RedirectBaseCall(logicMd, originalMd); - } - - /// - /// Gets number of RPCs by checking for RPC attributes. This does not perform error checking. - /// - /// - /// - internal uint GetRpcCount(TypeDefinition typeDef) - { - uint count = 0; - foreach (MethodDefinition methodDef in typeDef.Methods) - { - foreach (CustomAttribute customAttribute in methodDef.CustomAttributes) - { - RpcType rpcType = base.GetClass().GetRpcAttributeType(customAttribute); - if (rpcType != RpcType.None) - { - count++; - break; - } - } - } - - return count; - } - - /// - /// Creates all methods needed for a RPC. - /// - /// - /// - /// True if successful. - private bool CreateRpcMethods(List datas, CreatedRpc cr) - { - cr.RunLocally = cr.Attribute.GetField(RUNLOCALLY_NAME, false); - bool intentionallyNull; - - List serializedParameters = GetSerializedParamters(cr.RpcType, datas, cr); - - cr.WriterMethodDef = CreateRpcWriterMethod(serializedParameters, datas, cr, out intentionallyNull); - if (!intentionallyNull && cr.WriterMethodDef == null) - return false; - - cr.LogicMethodDef = CreateRpcLogicMethod(datas, cr, out intentionallyNull); - if (!intentionallyNull && cr.LogicMethodDef == null) - return false; - - cr.ReaderMethodDef = CreateRpcReaderMethod(serializedParameters, datas, cr, out intentionallyNull); - if (!intentionallyNull && cr.ReaderMethodDef == null) - return false; - - - return true; - } - - - - /// - /// Creates a writer for a RPC. - /// - /// - /// - /// - private MethodDefinition CreateRpcWriterMethod(List serializedParameters, List datas, CreatedRpc cr, out bool intentionallyNull) - { - intentionallyNull = false; - - - - string methodName = $"{WRITER_PREFIX}{GetRpcMethodName(cr)}"; - /* If method already exist then clear it. This - * can occur when a method needs to be rebuilt due to - * inheritence, and renumbering the RPC method names. */ - MethodDefinition createdMd = cr.TypeDef.GetMethod(methodName); - //If found. - if (createdMd != null) - { - createdMd.Parameters.Clear(); - createdMd.Body.Instructions.Clear(); - } - //Doesn't exist, create it. - else - { - //Create the method body. - createdMd = new MethodDefinition(methodName, - MethodAttributes.Private, - cr.Module.TypeSystem.Void); - cr.TypeDef.Methods.Add(createdMd); - createdMd.Body.InitLocals = true; - } - cr.WriterMethodDef = createdMd; - - bool result; - if (cr.RpcType == RpcType.Server) - result = CreateServerRpcWriterMethod(serializedParameters, cr); - else if (cr.RpcType == RpcType.Target || cr.RpcType == RpcType.Observers) - result = CreateClientRpcWriterMethod(serializedParameters, datas, cr); - else - result = false; - - return (result) ? cr.WriterMethodDef : null; - } - - /// - /// Returns serializable parameters for originalMd. - /// - private List GetSerializedParamters(RpcType rpcType, List attributeDatas, CreatedRpc cr) - { - MethodDefinition originalMd = cr.OriginalMethodDef; - - //RpcTypes for originalMd. - List attributeRpcTypes = attributeDatas.GetRpcTypes(); - - //Parameters to be serialized. - List serializedParameters = new List(); - /* Parameters which won't be serialized, such as channel. - * It's safe to add parameters which are null or - * not used. */ - HashSet nonserializedParameters = new HashSet(); - - //Get channel if it exist, and get target parameter. - ParameterDefinition channelParameterDef = GetChannelParameter(originalMd, rpcType); - - /* RpcType specific parameters. */ - ParameterDefinition targetConnectionParameterDef = null; - if (attributeRpcTypes.Contains(RpcType.Target)) - targetConnectionParameterDef = originalMd.Parameters[0]; - - if (rpcType == RpcType.Server) - { - //The network connection parameter might be added as null, this is okay. - nonserializedParameters.Add(GetNetworkConnectionParameter(originalMd)); - nonserializedParameters.Add(channelParameterDef); - } - else - { - nonserializedParameters.Add(channelParameterDef); - nonserializedParameters.Add(targetConnectionParameterDef); - } - - //Add all parameters which are NOT nonserialized to serializedParameters. - foreach (ParameterDefinition pd in originalMd.Parameters) - { - if (!nonserializedParameters.Contains(pd)) - serializedParameters.Add(pd); - } - - return serializedParameters; - } - - /// - /// Creates Writer method for a TargetRpc. - /// - private bool CreateClientRpcWriterMethod(List serializedParameters, List attributeDatas, CreatedRpc cr) - { - WriterProcessor wp = base.GetClass(); - - MethodDefinition writerMd = cr.WriterMethodDef; - MethodDefinition originalMd = cr.OriginalMethodDef; - - ILProcessor processor = writerMd.Body.GetILProcessor(); - //Add all parameters from the original. - for (int i = 0; i < originalMd.Parameters.Count; i++) - writerMd.Parameters.Add(originalMd.Parameters[i]); - //Get channel if it exist, and get target parameter. - ParameterDefinition channelParameterDef = GetChannelParameter(writerMd, RpcType.None); - - List rpcTypes = attributeDatas.GetRpcTypes(); - - /* RpcType specific parameters. */ - ParameterDefinition targetConnectionParameterDef = null; - if (rpcTypes.Contains(RpcType.Target)) - targetConnectionParameterDef = writerMd.Parameters[0]; - - /* Creates basic ServerRpc and ClientRpc - * conditions such as if requireOwnership ect.. - * or if (!base.isClient) */ - - CreateClientRpcConditionsForServer(writerMd); - - VariableDefinition channelVariableDef = CreateAndPopulateChannelVariable(writerMd, channelParameterDef); - /* Create a local PooledWriter variable. */ - //Default value for data lenght. - int dataLength = -1; - //Go through each attribute and see if a larger data length is specified. - foreach (AttributeData ad in attributeDatas) - { - int dl = ad.Attribute.GetField(DATALENGTH_NAME, -1); - if (dl > dataLength) - dataLength = dl; - } - VariableDefinition pooledWriterVariableDef = wp.CreatePooledWriter(writerMd, dataLength); - //Create all writer.WriteType() calls. - for (int i = 0; i < serializedParameters.Count; i++) - { - MethodReference writeMethodRef = wp.GetOrCreateWriteMethodReference(serializedParameters[i].ParameterType); - if (writeMethodRef == null) - return false; - - wp.CreateWrite(writerMd, pooledWriterVariableDef, serializedParameters[i], writeMethodRef); - } - - /* Call the method on NetworkBehaviour responsible for sending out the rpc. */ - if (cr.RpcType == RpcType.Observers) - processor.Add(CreateSendObserversRpc(writerMd, cr.MethodHash, pooledWriterVariableDef, channelVariableDef, cr.Attribute)); - else if (cr.RpcType == RpcType.Target) - processor.Add(CreateSendTargetRpc(writerMd, cr.MethodHash, pooledWriterVariableDef, channelVariableDef, targetConnectionParameterDef, attributeDatas)); - //Dispose of writer. - processor.Add(base.GetClass().DisposePooledWriter(writerMd, pooledWriterVariableDef)); - //Add end of method. - processor.Emit(OpCodes.Ret); - - return true; - } - - /// - /// Creates Writer method for a ServerRpc. - /// - private bool CreateServerRpcWriterMethod(List serializedParameters, CreatedRpc cr) - { - WriterProcessor wp = base.GetClass(); - - MethodDefinition writerMd = cr.WriterMethodDef; - MethodDefinition originalMd = cr.OriginalMethodDef; - ILProcessor processor = writerMd.Body.GetILProcessor(); - - //Add all parameters from the original. - for (int i = 0; i < originalMd.Parameters.Count; i++) - writerMd.Parameters.Add(originalMd.Parameters[i]); - //Add in channel if it doesnt exist. - ParameterDefinition channelParameterDef = GetChannelParameter(writerMd, RpcType.Server); - - /* Creates basic ServerRpc - * conditions such as if requireOwnership ect.. - * or if (!base.isClient) */ - - CreateServerRpcConditionsForClient(writerMd, cr.Attribute); - - VariableDefinition channelVariableDef = CreateAndPopulateChannelVariable(writerMd, channelParameterDef); - //Create a local PooledWriter variable. - int dataLength = cr.Attribute.GetField(DATALENGTH_NAME, -1); - VariableDefinition pooledWriterVariableDef = wp.CreatePooledWriter(writerMd, dataLength); - //Create all writer.WriteType() calls. - for (int i = 0; i < serializedParameters.Count; i++) - { - MethodReference writeMethodRef = wp.GetOrCreateWriteMethodReference(serializedParameters[i].ParameterType); - if (writeMethodRef == null) - return false; - - wp.CreateWrite(writerMd, pooledWriterVariableDef, serializedParameters[i], writeMethodRef); - } - - //Call the method on NetworkBehaviour responsible for sending out the rpc. - processor.Add(CreateSendServerRpc(writerMd, cr.MethodHash, pooledWriterVariableDef, channelVariableDef)); - //Dispose of writer. - processor.Add(wp.DisposePooledWriter(writerMd, pooledWriterVariableDef)); - //Add end of method. - processor.Emit(OpCodes.Ret); - - return true; - } - - /// - /// Creates a Channel VariableDefinition and populates it with parameterDef value if available, otherwise uses Channel.Reliable. - /// - /// - /// - /// - private VariableDefinition CreateAndPopulateChannelVariable(MethodDefinition methodDef, ParameterDefinition parameterDef) - { - ILProcessor processor = methodDef.Body.GetILProcessor(); - - VariableDefinition localChannelVariableDef = base.GetClass().CreateVariable(methodDef, typeof(Channel)); - if (parameterDef != null) - processor.Emit(OpCodes.Ldarg, parameterDef); - else - processor.Emit(OpCodes.Ldc_I4, (int)Channel.Reliable); - - //Set to local value. - processor.Emit(OpCodes.Stloc, localChannelVariableDef); - return localChannelVariableDef; - } - - - /// - /// Creates a reader for a RPC. - /// - /// - /// - /// - private MethodDefinition CreateRpcReaderMethod(List serializedParameters, List datas, CreatedRpc cr, out bool intentionallyNull) - { - intentionallyNull = false; - - RpcType rpcType = cr.RpcType; - MethodDefinition originalMd = cr.OriginalMethodDef; - TypeDefinition typeDef = cr.TypeDef; - bool runLocally = cr.RunLocally; - MethodDefinition logicMd = cr.LogicMethodDef; - CustomAttribute rpcAttribute = cr.Attribute; - - - - string methodName = $"{READER_PREFIX}{GetRpcMethodName(cr)}"; - /* If method already exist then just return it. This - * can occur when a method needs to be rebuilt due to - * inheritence, and renumbering the RPC method names. - * The reader method however does not need to be rewritten. */ - MethodDefinition createdMd = typeDef.GetMethod(methodName); - //If found. - if (createdMd != null) - { - cr.ReaderMethodDef = createdMd; - return createdMd; - } - else - { - //Create the method body. - createdMd = new MethodDefinition( - methodName, - MethodAttributes.Private, - originalMd.Module.TypeSystem.Void); - typeDef.Methods.Add(createdMd); - createdMd.Body.InitLocals = true; - cr.ReaderMethodDef = createdMd; - } - - if (rpcType == RpcType.Server) - return CreateServerRpcReaderMethod(typeDef, runLocally, originalMd, createdMd, serializedParameters, logicMd, rpcAttribute); - else if (rpcType == RpcType.Target || rpcType == RpcType.Observers) - return CreateClientRpcReaderMethod(serializedParameters, datas, cr); - else - return null; - } - - - /// - /// Creates a reader for ServerRpc. - /// - /// - /// - /// - private MethodDefinition CreateServerRpcReaderMethod(TypeDefinition typeDef, bool runLocally, MethodDefinition originalMd, MethodDefinition createdMd, List serializedParameters, MethodDefinition logicMd, CustomAttribute rpcAttribute) - { - ILProcessor processor = createdMd.Body.GetILProcessor(); - - bool requireOwnership = rpcAttribute.GetField(REQUIREOWNERSHIP_NAME, true); - //Create PooledReader parameter. - ParameterDefinition readerParameterDef = base.GetClass().CreateParameter(createdMd, base.GetClass().PooledReader_TypeRef); - - //Add connection parameter to the read method. Internals pass the connection into this. - ParameterDefinition channelParameterDef = GetOrCreateChannelParameter(createdMd, RpcType.Server); - ParameterDefinition connectionParameterDef = GetOrCreateNetworkConnectionParameter(createdMd); - - /* It's very important to read everything - * from the PooledReader before applying any - * exit logic. Should the method return before - * reading the data then anything after the rpc - * packet will be malformed due to invalid index. */ - VariableDefinition[] readVariableDefs; - List allReadInsts; - CreateRpcReadInstructions(createdMd, readerParameterDef, serializedParameters, out readVariableDefs, out allReadInsts); - - //Read to clear pooledreader. - processor.Add(allReadInsts); - - /* Don't continue if server is not active. - * This can happen if an object is deinitializing - * as a RPC arrives. When separate server and client - * this should not occur but there's a chance as host - * because deinitializations are slightly delayed to support - * the clientHost deinitializing the object as well. */ - base.GetClass().CreateIsServerCheck(createdMd, LoggingType.Off, false, false); - // - CreateServerRpcConditionsForServer(processor, requireOwnership, connectionParameterDef); - - //Block from running twice as host. - if (runLocally) - { - //The connection calling is always passed into the reader method as the last parameter. - ParameterDefinition ncPd = createdMd.Parameters[createdMd.Parameters.Count - 1]; - Instruction afterConnectionRet = processor.Create(OpCodes.Nop); - processor.Emit(OpCodes.Ldarg, ncPd); - MethodReference isLocalClientMr = base.GetClass().NetworkConnection_GetIsLocalClient_MethodRef; - processor.Emit(isLocalClientMr.GetCallOpCode(base.Session), isLocalClientMr); - processor.Emit(OpCodes.Brfalse_S, afterConnectionRet); - processor.Emit(OpCodes.Ret); - processor.Append(afterConnectionRet); - } - - //this.Logic - processor.Emit(OpCodes.Ldarg_0); - //Add each read variable as an argument. - foreach (VariableDefinition vd in readVariableDefs) - processor.Emit(OpCodes.Ldloc, vd); - - /* Pass in channel and connection if original - * method supports them. */ - ParameterDefinition originalChannelParameterDef = GetChannelParameter(originalMd, RpcType.Server); - ParameterDefinition originalConnectionParameterDef = GetNetworkConnectionParameter(originalMd); - if (originalChannelParameterDef != null) - processor.Emit(OpCodes.Ldarg, channelParameterDef); - if (originalConnectionParameterDef != null) - processor.Emit(OpCodes.Ldarg, connectionParameterDef); - //Call __Logic method. - processor.Emit(OpCodes.Call, logicMd); - processor.Emit(OpCodes.Ret); - - return createdMd; - } - - /// - /// Creates a reader for ObserversRpc. - /// - /// - /// - /// - private MethodDefinition CreateClientRpcReaderMethod(List serializedParameters, List attributeDatas, CreatedRpc cr) - { - MethodDefinition originalMd = cr.OriginalMethodDef; - MethodDefinition createdMd = cr.ReaderMethodDef; - RpcType rpcType = cr.RpcType; - CustomAttribute rpcAttribute = cr.Attribute; - bool runLocally = cr.RunLocally; - - ILProcessor processor = createdMd.Body.GetILProcessor(); - - //Create PooledReader parameter. - ParameterDefinition readerParameterDef = base.GetClass().CreateParameter(createdMd, base.GetClass().PooledReader_TypeRef); - ParameterDefinition channelParameterDef = GetOrCreateChannelParameter(createdMd, rpcType); - /* It's very important to read everything - * from the PooledReader before applying any - * exit logic. Should the method return before - * reading the data then anything after the rpc - * packet will be malformed due to invalid index. */ - VariableDefinition[] readVariableDefs; - List allReadInsts; - CreateRpcReadInstructions(createdMd, readerParameterDef, serializedParameters, out readVariableDefs, out allReadInsts); - //Read instructions even if not to include owner. - processor.Add(allReadInsts); - - /* Don't continue if client is not active. - * This can happen if an object is deinitializing - * as a RPC arrives. When separate server and client - * this should not occur but there's a chance as host - * because deinitializations are slightly delayed to support - * the clientHost deinitializing the object as well. */ - base.GetClass().CreateIsClientCheck(createdMd, LoggingType.Off, false, false); - - //Block from running twice as host. - if (runLocally) - processor.Add(CreateIsHostBlock(createdMd)); - - processor.Emit(OpCodes.Ldarg_0); //this. - /* TargetRpc passes in localconnection - * as receiver for connection. */ - if (rpcType == RpcType.Target) - { - processor.Emit(OpCodes.Ldarg_0); //this. - processor.Emit(OpCodes.Call, base.GetClass().LocalConnection_MethodRef); - } - else - { - //If this method uses target/observerRpc combined then load null for the connection. - RpcType allRpcTypes = attributeDatas.GetCombinedRpcType(); - if (allRpcTypes == (RpcType.Observers | RpcType.Target)) - processor.Emit(OpCodes.Ldnull); - } - //Add each read variable as an argument. - foreach (VariableDefinition vd in readVariableDefs) - processor.Emit(OpCodes.Ldloc, vd); - //Channel. - ParameterDefinition originalChannelParameterDef = GetChannelParameter(originalMd, rpcType); - if (originalChannelParameterDef != null) - processor.Emit(OpCodes.Ldarg, channelParameterDef); - //Call __Logic method. - processor.Emit(OpCodes.Call, cr.LogicMethodDef); - processor.Emit(OpCodes.Ret); - - return createdMd; - } - - - /// - /// Appends a block to the method if running as host. - /// - /// - private List CreateIsHostBlock(MethodDefinition md) - { - List ints = new List(); - ILProcessor processor = md.Body.GetILProcessor(); - - Instruction endIfInst = processor.Create(OpCodes.Nop); - ints.Add(processor.Create(OpCodes.Ldarg_0)); - ints.Add(processor.Create(OpCodes.Call, base.GetClass().IsHost_MethodRef)); - ints.Add(processor.Create(OpCodes.Brfalse_S, endIfInst)); - ints.Add(processor.Create(OpCodes.Ret)); - ints.Add(endIfInst); - - return ints; - } - - /// - /// Gets the optional NetworkConnection parameter for ServerRpc, if it exists. - /// - /// - /// - private ParameterDefinition GetNetworkConnectionParameter(MethodDefinition methodDef) - { - - ParameterDefinition result = methodDef.GetEndParameter(0); - //Is null, not networkconnection, or doesn't have default. - if (result == null || !result.Is(typeof(NetworkConnection)) || !result.HasDefault) - return null; - - return result; - } - - /// - /// Creates a NetworkConnection parameter if it's not the last or second to last parameter. - /// - /// - private ParameterDefinition GetOrCreateNetworkConnectionParameter(MethodDefinition methodDef) - { - ParameterDefinition result = GetNetworkConnectionParameter(methodDef); - if (result == null) - return base.GetClass().CreateParameter(methodDef, typeof(NetworkConnection), "conn"); - else - return result; - } - - /// - /// Returns the Channel parameter if it exist. - /// - /// - private ParameterDefinition GetChannelParameter(MethodDefinition methodDef, RpcType rpcType) - { - ParameterDefinition result = null; - ParameterDefinition pd = methodDef.GetEndParameter(0); - if (pd != null) - { - //Last parameter is channel. - if (pd.Is(typeof(Channel))) - { - result = pd; - } - /* Only other end parameter may be networkconnection. - * This can only be checked if a ServerRpc. */ - else if (rpcType == RpcType.Server) - { - //If last parameter is networkconnection and its default then can check second to last. - if (pd.Is(typeof(NetworkConnection)) && pd.HasDefault) - { - pd = methodDef.GetEndParameter(1); - if (pd != null && pd.Is(typeof(Channel))) - result = pd; - } - } - else - { - result = null; - } - } - - return result; - } - - /// - /// Creates a channel parameter if missing. - /// - /// - private ParameterDefinition GetOrCreateChannelParameter(MethodDefinition methodDef, RpcType rpcType) - { - ParameterDefinition result = GetChannelParameter(methodDef, rpcType); - //Add channel parameter if not included. - if (result == null) - { - ParameterDefinition connParameter = GetNetworkConnectionParameter(methodDef); - //If the connection parameter is specified then channel has to go before it. - if (connParameter != null) - return base.GetClass().CreateParameter(methodDef, typeof(Channel), "channel", ParameterAttributes.None, connParameter.Index); - //Not specified, add channel at end. - else - return base.GetClass().CreateParameter(methodDef, typeof(Channel), "channel"); - } - else - { - return result; - } - } - - /// - /// Creates a read for every writtenParameters and outputs variables read into, and instructions. - /// - /// - /// - /// - /// - /// - /// - private void CreateRpcReadInstructions(MethodDefinition methodDef, ParameterDefinition readerParameterDef, List serializedParameters, out VariableDefinition[] readVariableDefs, out List allReadInsts) - { - /* It's very important to read everything - * from the PooledReader before applying any - * exit logic. Should the method return before - * reading the data then anything after the rpc - * packet will be malformed due to invalid index. */ - readVariableDefs = new VariableDefinition[serializedParameters.Count]; - allReadInsts = new List(); - - //True if last parameter is a connection and a server rpc. - for (int i = 0; i < serializedParameters.Count; i++) - { - //Get read instructions and insert it before the return. - List insts = base.GetClass().CreateRead(methodDef, readerParameterDef, serializedParameters[i].ParameterType, out readVariableDefs[i]); - allReadInsts.AddRange(insts); - } - - } - /// - /// Creates conditions that clients must pass to send a ServerRpc. - /// - /// - /// - private void CreateServerRpcConditionsForClient(MethodDefinition methodDef, CustomAttribute rpcAttribute) - { - bool requireOwnership = rpcAttribute.GetField(REQUIREOWNERSHIP_NAME, true); - //If (!base.IsOwner); - if (requireOwnership) - base.GetClass().CreateLocalClientIsOwnerCheck(methodDef, LoggingType.Warning, false, false, true); - //If (!base.IsClient) - base.GetClass().CreateIsClientCheck(methodDef, LoggingType.Warning, false, true); - } - - /// - /// Creates conditions that server must pass to process a ServerRpc. - /// - /// - /// - /// Ret instruction. - private Instruction CreateServerRpcConditionsForServer(ILProcessor createdProcessor, bool requireOwnership, ParameterDefinition connectionParametereDef) - { - /* Don't need to check if server on receiving end. - * Next compare connection with owner. */ - //If (!base.CompareOwner); - if (requireOwnership) - return base.GetClass().CreateRemoteClientIsOwnerCheck(createdProcessor, connectionParametereDef); - else - return null; - } - - /// - /// Creates conditions that server must pass to process a ClientRpc. - /// - /// - private void CreateClientRpcConditionsForServer(MethodDefinition methodDef) - { - //If (!base.IsServer) - base.GetClass().CreateIsServerCheck(methodDef, LoggingType.Warning, false, false); - } - - /// - /// Creates a method containing the logic which will run when receiving the Rpc. - /// - /// - /// - private MethodDefinition CreateRpcLogicMethod(List datas, CreatedRpc cr, out bool intentionallyNull) - { - intentionallyNull = false; - - RpcType rpcType = cr.RpcType; - TypeDefinition typeDef = cr.TypeDef; - MethodDefinition originalMd = cr.OriginalMethodDef; - - - - //Methodname for logic methods do not use prefixes because there can be only one. - string methodName = $"{LOGIC_PREFIX}{GetMethodNameAsParameters(originalMd)}"; - /* If method already exist then just return it. This - * can occur when a method needs to be rebuilt due to - * inheritence, and renumbering the RPC method names. - * The logic method however does not need to be rewritten. */ - MethodDefinition logicMd = base.GetClass().CopyIntoNewMethod(originalMd, methodName, out _); - - cr.LogicMethodDef = logicMd; - return logicMd; - } - - /// - /// Finds and fixes call to base methods within remote calls - /// For example, changes `base.CmdDoSomething` to `base.UserCode_CmdDoSomething` within `this.UserCode_CmdDoSomething` - /// - /// - /// - private void RedirectBaseCall(MethodDefinition createdMethodDef, MethodDefinition originalMethodDef) - { - //All logic RPCs end with the logic suffix. - if (!createdMethodDef.Name.StartsWith(LOGIC_PREFIX)) - return; - //Not virtual, no need to check. - if (!createdMethodDef.IsVirtual) - return; - - foreach (Instruction instruction in createdMethodDef.Body.Instructions) - { - // if call to base.RpcDoSomething within this.RpcDoSOmething. - if (base.GetClass().IsCallToMethod(instruction, out MethodDefinition calledMethod) && calledMethod.Name == originalMethodDef.Name) - { - MethodReference baseLogicMd = createdMethodDef.DeclaringType.GetMethodDefinitionInAnyBase(base.Session, createdMethodDef.Name); - if (baseLogicMd == null) - { - base.LogError($"Could not find base method for {createdMethodDef.Name}."); - return; - } - - instruction.Operand = base.ImportReference(baseLogicMd); - } - } - } - - - /// - /// Redirects calls from the original Rpc method to the writer method. - /// - private void RedirectOriginalToWriter(List createdRpcs) - { - /* If there are multiple attributes/createdRpcs they will - * share the same originalMd so it's fine to take the first - * entry. */ - MethodDefinition originalMd = createdRpcs[0].OriginalMethodDef; - - - - ILProcessor processor = originalMd.Body.GetILProcessor(); - originalMd.Body.Instructions.Clear(); - - //If only one rpc type. - if (createdRpcs.Count == 1) - { - processor.Emit(OpCodes.Ldarg_0); //this. - //Parameters. - foreach (ParameterDefinition pd in originalMd.Parameters) - processor.Emit(OpCodes.Ldarg, pd); - - //Call method. - MethodReference writerMr = base.ImportReference(createdRpcs[0].WriterMethodDef); - processor.Emit(OpCodes.Call, writerMr); - - AddRunLocally(createdRpcs[0]); - } - //More than one which means it's an observer/targetRpc combo. - else - { - CreatedRpc observersRpc = createdRpcs.GetCreatedRpc(RpcType.Observers); - MethodReference observerWriterMr = base.ImportReference(observersRpc.WriterMethodDef); - - CreatedRpc targetRpc = createdRpcs.GetCreatedRpc(RpcType.Target); - MethodReference targetWriterMr = base.ImportReference(targetRpc.WriterMethodDef); - - Instruction targetRpcInst = processor.Create(OpCodes.Nop); - Instruction afterTargetRpcInst = processor.Create(OpCodes.Nop); - /* if (targetConn == null) - * WriteObserverRpc - * else - * WriteTargetRpc */ - processor.Emit(OpCodes.Ldarg, originalMd.Parameters[0]); - processor.Emit(OpCodes.Brtrue_S, targetRpcInst); - //Insert parameters. - processor.Emit(OpCodes.Ldarg_0); - foreach (ParameterDefinition pd in originalMd.Parameters) - processor.Emit(OpCodes.Ldarg, pd); - processor.Emit(OpCodes.Call, observerWriterMr); - AddRunLocally(observersRpc); - //else (target). - processor.Emit(OpCodes.Br_S, afterTargetRpcInst); - processor.Append(targetRpcInst); - //Insert parameters. - processor.Emit(OpCodes.Ldarg_0); - foreach (ParameterDefinition pd in originalMd.Parameters) - processor.Emit(OpCodes.Ldarg, pd); - processor.Emit(OpCodes.Call, targetWriterMr); - AddRunLocally(targetRpc); - processor.Append(afterTargetRpcInst); - } - - //Adds run locally logic if needed. - void AddRunLocally(CreatedRpc cRpc) - { - //Runlocally. - if (cRpc.RunLocally) - { - processor.Emit(OpCodes.Ldarg_0); //this. - //Parameters. - foreach (ParameterDefinition pd in originalMd.Parameters) - processor.Emit(OpCodes.Ldarg, pd); - processor.Emit(OpCodes.Call, cRpc.LogicMethodDef); - } - - } - - processor.Emit(OpCodes.Ret); - } - - - #region CreateSend - /// - /// Creates a call to SendServerRpc on NetworkBehaviour. - /// - /// - /// - private List CreateSendServerRpc(MethodDefinition methodDef, uint methodHash, VariableDefinition writerVariableDef, VariableDefinition channelVariableDef) - { - List insts = new List(); - ILProcessor processor = methodDef.Body.GetILProcessor(); - - insts.AddRange(CreateSendRpcCommon(processor, methodHash, writerVariableDef, channelVariableDef)); - //Call NetworkBehaviour. - insts.Add(processor.Create(OpCodes.Call, base.GetClass().SendServerRpc_MethodRef)); - - return insts; - } - - /// - /// Creates a call to SendObserversRpc on NetworkBehaviour. - /// - private List CreateSendObserversRpc(MethodDefinition methodDef, uint methodHash, VariableDefinition writerVariableDef, VariableDefinition channelVariableDef, CustomAttribute rpcAttribute) - { - List insts = new List(); - ILProcessor processor = methodDef.Body.GetILProcessor(); - - insts.AddRange(CreateSendRpcCommon(processor, methodHash, writerVariableDef, channelVariableDef)); - //Also add if buffered. - bool bufferLast = rpcAttribute.GetField(BUFFERLAST_NAME, false); - bool excludeOwner = rpcAttribute.GetField(EXCLUDEOWNER_NAME, false); - bool excludeServer = rpcAttribute.GetField(EXCLUDESERVER_NAME, false); - - //Warn user if any values are byref. - bool usedByref = false; - foreach (ParameterDefinition item in methodDef.Parameters) - { - if (item.IsIn) - { - usedByref = true; - break; - } - } - if (usedByref) - base.LogWarning($"Method {methodDef.FullName} takes an argument by reference. While this is supported, using BufferLast in addition to by reference arguements will buffer the value as it was serialized, not as it is when sending buffered."); - - insts.Add(processor.Create(OpCodes.Ldc_I4, bufferLast.ToInt())); - insts.Add(processor.Create(OpCodes.Ldc_I4, excludeServer.ToInt())); - insts.Add(processor.Create(OpCodes.Ldc_I4, excludeOwner.ToInt())); - //Call NetworkBehaviour. - insts.Add(processor.Create(OpCodes.Call, base.GetClass().SendObserversRpc_MethodRef)); - - return insts; - } - /// - /// Creates a call to SendTargetRpc on NetworkBehaviour. - /// - private List CreateSendTargetRpc(MethodDefinition methodDef, uint methodHash, VariableDefinition writerVariableDef, VariableDefinition channelVariableDef, ParameterDefinition targetConnectionParameterDef, List attributeDatas) - { - List insts = new List(); - ILProcessor processor = methodDef.Body.GetILProcessor(); - - CustomAttribute rpcAttribute = attributeDatas.GetAttribute(base.Session, RpcType.Target); - bool validateTarget = rpcAttribute.GetField(VALIDATETARGET_NAME, true); - bool excludeServer = rpcAttribute.GetField(EXCLUDESERVER_NAME, false); - - insts.AddRange(CreateSendRpcCommon(processor, methodHash, writerVariableDef, channelVariableDef)); - //Reference to NetworkConnection that RPC is going to. - insts.Add(processor.Create(OpCodes.Ldarg, targetConnectionParameterDef)); - //Exclude server from rpc. - insts.Add(processor.Create(OpCodes.Ldc_I4, excludeServer.ToInt())); - //Validate target receiving the rpc. - insts.Add(processor.Create(OpCodes.Ldc_I4, validateTarget.ToInt())); - //Call NetworkBehaviour. - insts.Add(processor.Create(OpCodes.Call, base.GetClass().SendTargetRpc_MethodRef)); - - return insts; - } - - /// - /// Writes common properties that all SendRpc methods use. - /// - private List CreateSendRpcCommon(ILProcessor processor, uint methodHash, VariableDefinition writerVariableDef, VariableDefinition channelVariableDef) - { - List insts = new List(); - - insts.Add(processor.Create(OpCodes.Ldarg_0)); // argument: this - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)methodHash)); - //reference to PooledWriter. - insts.Add(processor.Create(OpCodes.Ldloc, writerVariableDef)); - //reference to Channel. - insts.Add(processor.Create(OpCodes.Ldloc, channelVariableDef)); - - return insts; - } - #endregion - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Processing/Rpc/RpcProcessor.cs.meta b/Assets/FishNet/CodeGenerating/Processing/Rpc/RpcProcessor.cs.meta deleted file mode 100644 index e87895d..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Rpc/RpcProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4d4adb5891ee44f4397cd07ac2df0ce0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/Typed.meta b/Assets/FishNet/CodeGenerating/Processing/Typed.meta deleted file mode 100644 index 8481191..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Typed.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 1c24efb514a41fb41b4eb883a5f51fb5 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/Typed/ProcessedSync.cs b/Assets/FishNet/CodeGenerating/Processing/Typed/ProcessedSync.cs deleted file mode 100644 index 5cc1130..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Typed/ProcessedSync.cs +++ /dev/null @@ -1,24 +0,0 @@ -using MonoFN.Cecil; - -namespace FishNet.CodeGenerating.Processing -{ - - public class ProcessedSync - { - public FieldReference OriginalFieldRef; - public FieldReference GeneratedFieldRef; - public MethodReference SetMethodRef; - public MethodReference GetMethodRef; - - public ProcessedSync(FieldReference originalFieldRef,FieldReference generatedFieldRef, MethodReference setMethodRef, MethodReference getMethodRef) - { - OriginalFieldRef = originalFieldRef; - GeneratedFieldRef = generatedFieldRef; - SetMethodRef = setMethodRef; - GetMethodRef = getMethodRef; - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Processing/Typed/ProcessedSync.cs.meta b/Assets/FishNet/CodeGenerating/Processing/Typed/ProcessedSync.cs.meta deleted file mode 100644 index 1d82e02..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/Typed/ProcessedSync.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c0dc2fea60bfe1341b04e7165251d36f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Processing/WriterProcessor.cs b/Assets/FishNet/CodeGenerating/Processing/WriterProcessor.cs deleted file mode 100644 index 38d662b..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/WriterProcessor.cs +++ /dev/null @@ -1,1158 +0,0 @@ -using FishNet.CodeGenerating.Extension; -using FishNet.CodeGenerating.Helping.Extension; -using FishNet.CodeGenerating.ILCore; -using FishNet.Object; -using FishNet.Serializing; -using FishNet.Utility.Performance; -using MonoFN.Cecil; -using MonoFN.Cecil.Cil; -using MonoFN.Cecil.Rocks; -using System; -using System.Collections.Generic; -using SR = System.Reflection; -using UnityDebug = UnityEngine.Debug; - -namespace FishNet.CodeGenerating.Helping -{ - - internal class WriterProcessor : CodegenBase - { - #region Reflection references. - public readonly Dictionary InstancedWriterMethods = new Dictionary(); - public readonly Dictionary StaticWriterMethods = new Dictionary(); - public HashSet AutoPackedMethods = new HashSet(new TypeReferenceComparer()); - - public TypeDefinition GeneratedWriterClassTypeDef; - public MethodDefinition GeneratedWriterOnLoadMethodDef; - #endregion - - #region Misc. - /// - /// TypeReferences which have already had delegates made for. - /// - private HashSet _delegatedTypes = new HashSet(); - #endregion - - #region Const. - /// - /// Namespace to use for generated serializers and delegates. - /// - public const string GENERATED_WRITER_NAMESPACE = "FishNet.Serializing.Generated"; - /// - /// Name to use for generated serializers class. - /// - public const string GENERATED_WRITERS_CLASS_NAME = "GeneratedWriters___Internal"; - /// - /// Attributes to use for generated serializers class. - /// - public const TypeAttributes GENERATED_TYPE_ATTRIBUTES = (TypeAttributes.BeforeFieldInit | TypeAttributes.Class | TypeAttributes.AnsiClass | - TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.Abstract | TypeAttributes.Sealed); - /// - /// Name to use for InitializeOnce method. - /// - public const string INITIALIZEONCE_METHOD_NAME = "InitializeOnce"; - /// - /// Attributes to use for InitializeOnce method within generated serializer classes. - /// - public const MethodAttributes INITIALIZEONCE_METHOD_ATTRIBUTES = (MethodAttributes.Static | MethodAttributes.Private | MethodAttributes.HideBySig); - /// - /// Attritbutes to use for generated serializers. - /// - public const MethodAttributes GENERATED_METHOD_ATTRIBUTES = (MethodAttributes.Static | MethodAttributes.Public | MethodAttributes.HideBySig); - /// - /// Prefix all built-in and user created write methods should begin with. - /// - internal const string WRITE_PREFIX = "Write"; - /// - /// Prefix all built-in and user created write methods should begin with. - /// - internal const string GENERATED_WRITE_PREFIX = "Write___"; - /// - /// Types to exclude from being scanned for auto serialization. - /// - public static readonly System.Type[] EXCLUDED_AUTO_SERIALIZER_TYPES = new System.Type[] - { - typeof(NetworkBehaviour) - }; - /// - /// Types within assemblies which begin with these prefixes will not have serializers created for them. - /// - public static readonly string[] EXCLUDED_ASSEMBLY_PREFIXES = new string[] - { - "UnityEngine." - }; - #endregion - - public override bool ImportReferences() => true; - - /// - /// Processes data. To be used after everything else has called ImportReferences. - /// - /// - public bool Process() - { - GeneralHelper gh = base.GetClass(); - - CreateGeneratedClassData(); - FindInstancedWriters(); - CreateInstancedWriterExtensions(); - - //Creates class for generated writers, and init on load method. - void CreateGeneratedClassData() - { - GeneratedWriterClassTypeDef = gh.GetOrCreateClass(out _, GENERATED_TYPE_ATTRIBUTES, GENERATED_WRITERS_CLASS_NAME, null, WriterProcessor.GENERATED_WRITER_NAMESPACE); - /* If constructor isn't set then try to get or create it - * and also add it to methods if were created. */ - GeneratedWriterOnLoadMethodDef = gh.GetOrCreateMethod(GeneratedWriterClassTypeDef, out _, INITIALIZEONCE_METHOD_ATTRIBUTES, INITIALIZEONCE_METHOD_NAME, base.Module.TypeSystem.Void); - ILProcessor pp = GeneratedWriterOnLoadMethodDef.Body.GetILProcessor(); - pp.Emit(OpCodes.Ret); - gh.CreateRuntimeInitializeOnLoadMethodAttribute(GeneratedWriterOnLoadMethodDef); - } - - //Finds all instanced writers and autopack types. - void FindInstancedWriters() - { - Type pooledWriterType = typeof(PooledWriter); - foreach (SR.MethodInfo methodInfo in pooledWriterType.GetMethods()) - { - if (IsSpecialWriteMethod(methodInfo)) - continue; - bool autoPackMethod; - if (IsIgnoredWriteMethod(methodInfo, out autoPackMethod)) - continue; - - MethodReference methodRef = base.ImportReference(methodInfo); - /* TypeReference for the first parameter in the write method. - * The first parameter will always be the type written. */ - TypeReference typeRef = base.ImportReference(methodRef.Parameters[0].ParameterType); - /* If here all checks pass. */ - AddWriterMethod(typeRef, methodRef, true, true); - if (autoPackMethod) - AutoPackedMethods.Add(typeRef); - } - } - - return true; - } - - /// - /// Returns if a MethodInfo is considered a special write method. - /// Special write methods have declared references within this class, and will not have extensions made for them. - /// - public bool IsSpecialWriteMethod(SR.MethodInfo methodInfo) - { - /* Special methods. */ - if (methodInfo.Name == nameof(PooledWriter.Dispose)) - return true; - else if (methodInfo.Name == nameof(PooledWriter.WritePackedWhole)) - return true; - else if (methodInfo.Name == nameof(PooledWriter.WriteDictionary)) - return true; - else if (methodInfo.Name == nameof(PooledWriter.WriteList)) - return true; - - return false; - } - - /// - /// Returns if a write method should be ignored. - /// - public bool IsIgnoredWriteMethod(SR.MethodInfo methodInfo, out bool autoPackMethod) - { - autoPackMethod = false; - - if (base.GetClass().CodegenExclude(methodInfo)) - return true; - //Not long enough to be a write method. - else if (methodInfo.Name.Length < WRITE_PREFIX.Length) - return true; - //Method name doesn't start with writePrefix. - else if (methodInfo.Name.Substring(0, WRITE_PREFIX.Length) != WRITE_PREFIX) - return true; - - SR.ParameterInfo[] parameterInfos = methodInfo.GetParameters(); - /* No parameters or more than 2 parameters. Most Write methods - * will have only 1 parameter but some will have 2 if - * there is a pack option. */ - if (parameterInfos.Length < 1 || parameterInfos.Length > 2) - return true; - /* If two parameters make sure the second parameter - * is a pack parameter. */ - if (parameterInfos.Length == 2) - { - autoPackMethod = (parameterInfos[1].ParameterType == typeof(AutoPackType)); - if (!autoPackMethod) - return true; - } - - return false; - } - - - /// - /// Creates writer extension methods for built-in writers. - /// - private void CreateInstancedWriterExtensions() - { - //return; - if (!FishNetILPP.IsFishNetAssembly(base.Session)) - return; - - GeneralHelper gh = base.GetClass(); - WriterProcessor gwh = base.GetClass(); - - //List staticReaders = new List(); - foreach (KeyValuePair item in InstancedWriterMethods) - { - MethodReference instancedWriteMr = item.Value; - if (instancedWriteMr.HasGenericParameters) - continue; - - TypeReference valueTr = instancedWriteMr.Parameters[0].ParameterType; - - MethodDefinition md = new MethodDefinition($"InstancedExtension___{instancedWriteMr.Name}", - WriterProcessor.GENERATED_METHOD_ATTRIBUTES, - base.Module.TypeSystem.Void); - - //Add extension parameter. - ParameterDefinition writerPd = gh.CreateParameter(md, typeof(Writer), "writer"); - //Add parameters needed by instanced writer. - List otherPds = md.CreateParameters(base.Session, instancedWriteMr); - gh.MakeExtensionMethod(md); - // - gwh.GeneratedWriterClassTypeDef.Methods.Add(md); - - ILProcessor processor = md.Body.GetILProcessor(); - //Load writer. - processor.Emit(OpCodes.Ldarg, writerPd); - //Load args. - foreach (ParameterDefinition pd in otherPds) - processor.Emit(OpCodes.Ldarg, pd); - //Call instanced. - processor.Emit(instancedWriteMr.GetCallOpCode(base.Session), instancedWriteMr); - processor.Emit(OpCodes.Ret); - AddWriterMethod(valueTr, md, false, true); - } - - } - - /// - /// Adds typeRef, methodDef to Instanced or Static write methods. - /// - public void AddWriterMethod(TypeReference typeRef, MethodReference methodRef, bool instanced, bool useAdd) - { - Dictionary dict = (instanced) ? - InstancedWriterMethods : StaticWriterMethods; - string fullName = typeRef.GetFullnameWithoutBrackets(); - if (useAdd) - dict.Add(fullName, methodRef); - else - dict[fullName] = methodRef; - } - - /// - /// Removes typeRef from Instanced or Static write methods. - /// - internal void RemoveWriterMethod(TypeReference typeRef, bool instanced) - { - Dictionary dict = (instanced) ? - InstancedWriterMethods : StaticWriterMethods; - - dict.Remove(typeRef.FullName); - } - - /// - /// Returns if typeRef supports auto packing. - /// - public bool IsAutoPackedType(TypeReference typeRef) - { - return AutoPackedMethods.Contains(typeRef); - } - - - /// - /// Creates Write delegates for known static methods. - /// - public void CreateStaticMethodDelegates() - { - foreach (KeyValuePair item in StaticWriterMethods) - base.GetClass().CreateStaticMethodWriteDelegate(item.Value); - } - - /// - /// Creates a Write delegate for writeMethodRef and places it within the generated reader/writer constructor. - /// - /// - private void CreateStaticMethodWriteDelegate(MethodReference writeMr) - { - GeneralHelper gh = base.GetClass(); - WriterImports wi = base.GetClass(); - - //Check if ret already exist, if so remove it; ret will be added on again in this method. - if (GeneratedWriterOnLoadMethodDef.Body.Instructions.Count != 0) - { - int lastIndex = (GeneratedWriterOnLoadMethodDef.Body.Instructions.Count - 1); - if (GeneratedWriterOnLoadMethodDef.Body.Instructions[lastIndex].OpCode == OpCodes.Ret) - GeneratedWriterOnLoadMethodDef.Body.Instructions.RemoveAt(lastIndex); - } - - ILProcessor processor = GeneratedWriterOnLoadMethodDef.Body.GetILProcessor(); - TypeReference dataTypeRef; - dataTypeRef = writeMr.Parameters[1].ParameterType; - - //Check if writer already exist. - if (_delegatedTypes.Contains(dataTypeRef)) - { - base.LogError($"Generic write already created for {dataTypeRef.FullName}."); - return; - } - else - { - _delegatedTypes.Add(dataTypeRef); - } - - /* Create a Action delegate. - * May also be Action delegate - * for packed types. */ - processor.Emit(OpCodes.Ldnull); - processor.Emit(OpCodes.Ldftn, writeMr); - - GenericInstanceType actionGenericInstance; - MethodReference actionConstructorInstanceMethodRef; - bool isAutoPacked = base.GetClass().IsAutoPackedType(dataTypeRef); - - //Generate for auto pack type. - if (isAutoPacked) - { - actionGenericInstance = gh.ActionT3_TypeRef.MakeGenericInstanceType(wi.WriterTypeRef, dataTypeRef, base.GetClass().AutoPackTypeRef); - actionConstructorInstanceMethodRef = gh.ActionT3Constructor_MethodRef.MakeHostInstanceGeneric(base.Session, actionGenericInstance); - } - //Generate for normal type. - else - { - actionGenericInstance = gh.ActionT2_TypeRef.MakeGenericInstanceType(wi.WriterTypeRef, dataTypeRef); - actionConstructorInstanceMethodRef = gh.ActionT2Constructor_MethodRef.MakeHostInstanceGeneric(base.Session, actionGenericInstance); - } - - processor.Emit(OpCodes.Newobj, actionConstructorInstanceMethodRef); - //Call delegate to GenericWriter.Write - GenericInstanceType genericInstance = wi.GenericWriterTypeRef.MakeGenericInstanceType(dataTypeRef); - MethodReference genericrWriteMethodRef = (isAutoPacked) ? - wi.WriteAutoPackGetSetMethodRef.MakeHostInstanceGeneric(base.Session, genericInstance) : - wi.WriteGetSetMethodRef.MakeHostInstanceGeneric(base.Session, genericInstance); - processor.Emit(OpCodes.Call, genericrWriteMethodRef); - - processor.Emit(OpCodes.Ret); - } - - - - /// - /// Returns if typeRef has a serializer. - /// - /// - /// - internal bool HasSerializer(TypeReference typeRef, bool createMissing) - { - bool result = (GetInstancedWriteMethodReference(typeRef) != null) || - (GetStaticWriteMethodReference(typeRef) != null); - - if (!result && createMissing) - { - if (!base.GetClass().HasNonSerializableAttribute(typeRef.CachedResolve(base.Session))) - { - MethodReference methodRef = CreateWriter(typeRef); - result = (methodRef != null); - } - } - - return result; - } - - - #region GetWriterMethodReference. - /// - /// Returns the MethodReference for typeRef. - /// - /// - /// - internal MethodReference GetInstancedWriteMethodReference(TypeReference typeRef) - { - string fullName = typeRef.GetFullnameWithoutBrackets(); - InstancedWriterMethods.TryGetValue(fullName, out MethodReference methodRef); - return methodRef; - } - /// - /// Returns the MethodReference for typeRef. - /// - /// - /// - internal MethodReference GetStaticWriteMethodReference(TypeReference typeRef) - { - string fullName = typeRef.GetFullnameWithoutBrackets(); - StaticWriterMethods.TryGetValue(fullName, out MethodReference methodRef); - return methodRef; - } - - /// - /// Returns the MethodReference for typeRef favoring instanced or static. - /// - /// - /// - /// - internal MethodReference GetWriteMethodReference(TypeReference typeRef) - { - bool favorInstanced = false; - - MethodReference result; - if (favorInstanced) - { - result = GetInstancedWriteMethodReference(typeRef); - if (result == null) - result = GetStaticWriteMethodReference(typeRef); - } - else - { - result = GetStaticWriteMethodReference(typeRef); - if (result == null) - result = GetInstancedWriteMethodReference(typeRef); - } - - return result; - } - /// - /// Gets the write MethodRef for typeRef, or tries to create it if not present. - /// - /// - /// - internal MethodReference GetOrCreateWriteMethodReference(TypeReference typeRef) - { -#pragma warning disable CS0219 - bool favorInstanced = false; -#pragma warning restore CS0219 - //Try to get existing writer, if not present make one. - MethodReference writeMethodRef = GetWriteMethodReference(typeRef); - if (writeMethodRef == null) - writeMethodRef = CreateWriter(typeRef); - - //If still null then return could not be generated. - if (writeMethodRef == null) - { - base.LogError($"Could not create serializer for {typeRef.FullName}."); - } - //Otherwise, check if generic and create writes for generic pararameters. - else if (typeRef.IsGenericInstance) - { - GenericInstanceType git = (GenericInstanceType)typeRef; - foreach (TypeReference item in git.GenericArguments) - { - MethodReference result = GetOrCreateWriteMethodReference(item); - if (result == null) - { - base.LogError($"Could not create serializer for {item.FullName}."); - return null; - } - } - } - - return writeMethodRef; - } - #endregion - - - /// - /// Creates a PooledWriter within the body/ and returns its variable index. - /// EG: PooledWriter writer = WriterPool.GetWriter(); - /// - internal VariableDefinition CreatePooledWriter(MethodDefinition methodDef, int length) - { - VariableDefinition resultVd; - List insts = CreatePooledWriter(methodDef, length, out resultVd); - - ILProcessor processor = methodDef.Body.GetILProcessor(); - processor.Add(insts); - return resultVd; - } - /// - /// Creates a PooledWriter within the body/ and returns its variable index. - /// EG: PooledWriter writer = WriterPool.GetWriter(); - /// - /// - /// - /// - internal List CreatePooledWriter(MethodDefinition methodDef, int length, out VariableDefinition resultVd) - { - WriterImports wi = base.GetClass(); - - List insts = new List(); - ILProcessor processor = methodDef.Body.GetILProcessor(); - - resultVd = base.GetClass().CreateVariable(methodDef, wi.PooledWriter_TypeRef); - //If length is specified then pass in length. - if (length > 0) - { - insts.Add(processor.Create(OpCodes.Ldc_I4, length)); - insts.Add(processor.Create(OpCodes.Call, wi.WriterPool_GetWriterLength_MethodRef)); - } - //Use parameter-less method if no length. - else - { - insts.Add(processor.Create(OpCodes.Call, wi.WriterPool_GetWriter_MethodRef)); - } - //Set value to variable definition. - insts.Add(processor.Create(OpCodes.Stloc, resultVd)); - return insts; - } - - - /// - /// Calls Dispose on a PooledWriter. - /// EG: writer.Dispose(); - /// - /// - /// - internal List DisposePooledWriter(MethodDefinition methodDef, VariableDefinition writerDefinition) - { - WriterImports wi = base.GetClass(); - - List insts = new List(); - ILProcessor processor = methodDef.Body.GetILProcessor(); - - insts.Add(processor.Create(OpCodes.Ldloc, writerDefinition)); - insts.Add(processor.Create(wi.PooledWriter_Dispose_MethodRef.GetCallOpCode(base.Session), wi.PooledWriter_Dispose_MethodRef)); - - return insts; - } - - - /// - /// Creates a null check on the second argument using a boolean. - /// - internal void CreateRetOnNull(ILProcessor processor, ParameterDefinition writerParameterDef, ParameterDefinition checkedParameterDef, bool useBool) - { - Instruction endIf = processor.Create(OpCodes.Nop); - //If (value) jmp to endIf. - processor.Emit(OpCodes.Ldarg, checkedParameterDef); - processor.Emit(OpCodes.Brtrue, endIf); - //writer.WriteBool / writer.WritePackedWhole - if (useBool) - CreateWriteBool(processor, writerParameterDef, true); - else - CreateWritePackedWhole(processor, writerParameterDef, -1); - //Exit method. - processor.Emit(OpCodes.Ret); - //End of if check. - processor.Append(endIf); - } - - #region CreateWritePackWhole - /// - /// Creates a call to WritePackWhole with value. - /// - /// - /// - internal void CreateWritePackedWhole(ILProcessor processor, ParameterDefinition writerParameterDef, int value) - { - WriterImports wi = base.GetClass(); - - //Create local int and set it to value. - VariableDefinition intVariableDef = base.GetClass().CreateVariable(processor.Body.Method, typeof(int)); - base.GetClass().SetVariableDefinitionFromInt(processor, intVariableDef, value); - //Writer. - processor.Emit(OpCodes.Ldarg, writerParameterDef); - //Writer.WritePackedWhole(value). - processor.Emit(OpCodes.Ldloc, intVariableDef); - processor.Emit(OpCodes.Conv_U8); - processor.Emit(wi.Writer_WritePackedWhole_MethodRef.GetCallOpCode(base.Session), wi.Writer_WritePackedWhole_MethodRef); - } - /// - /// Creates a call to WritePackWhole with value. - /// - /// - /// - internal void CreateWritePackedWhole(ILProcessor processor, ParameterDefinition writerParameterDef, VariableDefinition value) - { - WriterImports wi = base.GetClass(); - - //Writer. - processor.Emit(OpCodes.Ldarg, writerParameterDef); - //Writer.WritePackedWhole(value). - processor.Emit(OpCodes.Ldloc, value); - processor.Emit(OpCodes.Conv_U8); - processor.Emit(wi.Writer_WritePackedWhole_MethodRef.GetCallOpCode(base.Session), wi.Writer_WritePackedWhole_MethodRef); - } - #endregion - - /// - /// Creates a call to WriteBoolean with value. - /// - /// - /// - /// - internal void CreateWriteBool(ILProcessor processor, ParameterDefinition writerParameterDef, bool value) - { - MethodReference writeBoolMethodRef = GetWriteMethodReference(base.GetClass().GetTypeReference(typeof(bool))); - processor.Emit(OpCodes.Ldarg, writerParameterDef); - int intValue = (value) ? 1 : 0; - processor.Emit(OpCodes.Ldc_I4, intValue); - processor.Emit(writeBoolMethodRef.GetCallOpCode(base.Session), writeBoolMethodRef); - } - - /// - /// Creates a Write call on a PooledWriter variable for parameterDef. - /// EG: writer.WriteBool(xxxxx); - /// - internal List CreateWriteInstructions(MethodDefinition methodDef, object pooledWriterDef, ParameterDefinition valueParameterDef, MethodReference writeMr) - { - List insts = new List(); - ILProcessor processor = methodDef.Body.GetILProcessor(); - - if (writeMr != null) - { - if (pooledWriterDef is VariableDefinition) - { - insts.Add(processor.Create(OpCodes.Ldloc, (VariableDefinition)pooledWriterDef)); - } - else if (pooledWriterDef is ParameterDefinition) - { - insts.Add(processor.Create(OpCodes.Ldarg, (ParameterDefinition)pooledWriterDef)); - } - else - { - base.LogError($"{pooledWriterDef.GetType().FullName} is not a valid writerDef. Type must be VariableDefinition or ParameterDefinition."); - return new List(); - } - insts.Add(processor.Create(OpCodes.Ldarg, valueParameterDef)); - //If an auto pack method then insert default value. - if (AutoPackedMethods.Contains(valueParameterDef.ParameterType)) - { - AutoPackType packType = base.GetClass().GetDefaultAutoPackType(valueParameterDef.ParameterType); - insts.Add(processor.Create(OpCodes.Ldc_I4, (int)packType)); - } - - TypeReference valueTr = valueParameterDef.ParameterType; - /* If generic then find write class for - * data type. Currently we only support one generic - * for this. */ - if (valueTr.IsGenericInstance) - { - GenericInstanceType git = (GenericInstanceType)valueTr; - TypeReference genericTr = git.GenericArguments[0]; - writeMr = writeMr.GetMethodReference(base.Session, genericTr); - } - - insts.Add(processor.Create(OpCodes.Call, writeMr)); - return insts; - } - else - { - base.LogError($"Writer not found for {valueParameterDef.ParameterType.FullName}."); - return new List(); - } - } - /// - /// Creates a Write call on a PooledWriter variable for parameterDef. - /// EG: writer.WriteBool(xxxxx); - /// - internal void CreateWrite(MethodDefinition methodDef, object writerDef, ParameterDefinition valuePd, MethodReference writeMr) - { - List insts = CreateWriteInstructions(methodDef, writerDef, valuePd, writeMr); - ILProcessor processor = methodDef.Body.GetILProcessor(); - processor.Add(insts); - } - /// - /// Creates a Write call to a writer. - /// EG: StaticClass.WriteBool(xxxxx); - /// - /// - /// - internal void CreateWrite(MethodDefinition writerMd, ParameterDefinition valuePd, FieldDefinition fieldDef, MethodReference writeMr) - { - if (writeMr != null) - { - ILProcessor processor = writerMd.Body.GetILProcessor(); - ParameterDefinition writerPd = writerMd.Parameters[0]; - - /* If generic then find write class for - * data type. Currently we only support one generic - * for this. */ - if (fieldDef.FieldType.IsGenericInstance) - { - GenericInstanceType git = (GenericInstanceType)fieldDef.FieldType; - TypeReference genericTr = git.GenericArguments[0]; - writeMr = writeMr.GetMethodReference(base.Session, genericTr); - } - - FieldReference fieldRef = base.GetClass().GetFieldReference(fieldDef); - processor.Emit(OpCodes.Ldarg, writerPd); - processor.Emit(OpCodes.Ldarg, valuePd); - processor.Emit(OpCodes.Ldfld, fieldRef); - //If an auto pack method then insert default value. - if (AutoPackedMethods.Contains(fieldDef.FieldType)) - { - AutoPackType packType = base.GetClass().GetDefaultAutoPackType(fieldDef.FieldType); - processor.Emit(OpCodes.Ldc_I4, (int)packType); - } - processor.Emit(OpCodes.Call, writeMr); - } - else - { - base.LogError($"Writer not found for {fieldDef.FieldType.FullName}."); - } - } - - /// - /// Creates a Write call to a writer. - /// EG: StaticClass.WriteBool(xxxxx); - /// - /// - /// - internal void CreateWrite(MethodDefinition writerMd, ParameterDefinition valuePd, MethodReference getMr, MethodReference writeMr) - { - TypeReference returnTr = base.ImportReference(getMr.ReturnType); - - if (writeMr != null) - { - ILProcessor processor = writerMd.Body.GetILProcessor(); - ParameterDefinition writerPd = writerMd.Parameters[0]; - - /* If generic then find write class for - * data type. Currently we only support one generic - * for this. */ - if (returnTr.IsGenericInstance) - { - GenericInstanceType git = (GenericInstanceType)returnTr; - TypeReference genericTr = git.GenericArguments[0]; - writeMr = writeMr.GetMethodReference(base.Session, genericTr); - } - - processor.Emit(OpCodes.Ldarg, writerPd); - OpCode ldArgOC0 = (valuePd.ParameterType.IsValueType) ? OpCodes.Ldarga : OpCodes.Ldarg; - processor.Emit(ldArgOC0, valuePd); - processor.Emit(OpCodes.Call, getMr); - //If an auto pack method then insert default value. - if (AutoPackedMethods.Contains(returnTr)) - { - AutoPackType packType = base.GetClass().GetDefaultAutoPackType(returnTr); - processor.Emit(OpCodes.Ldc_I4, (int)packType); - } - processor.Emit(OpCodes.Call, writeMr); - } - else - { - base.LogError($"Writer not found for {returnTr.FullName}."); - } - } - - - - #region TypeReference writer generators. - - /// - /// Generates a writer for objectTypeReference if one does not already exist. - /// - /// - /// - internal MethodReference CreateWriter(TypeReference objectTr) - { - MethodReference methodRefResult = null; - TypeDefinition objectTd; - SerializerType serializerType = base.GetClass().GetSerializerType(objectTr, true, out objectTd); - if (serializerType != SerializerType.Invalid) - { - //Array. - if (serializerType == SerializerType.Array) - methodRefResult = CreateArrayWriterMethodReference(objectTr); - //Enum. - else if (serializerType == SerializerType.Enum) - methodRefResult = CreateEnumWriterMethodDefinition(objectTr); - //Dictionary, List, ListCache - else if (serializerType == SerializerType.Dictionary - || serializerType == SerializerType.List - || serializerType == SerializerType.ListCache) - methodRefResult = CreateGenericCollectionWriterMethodReference(objectTr, serializerType); - //NetworkBehaviour. - else if (serializerType == SerializerType.NetworkBehaviour) - methodRefResult = CreateNetworkBehaviourWriterMethodReference(objectTd); - //Nullable type. - else if (serializerType == SerializerType.Nullable) - methodRefResult = CreateNullableWriterMethodReference(objectTr, objectTd); - //Class or struct. - else if (serializerType == SerializerType.ClassOrStruct) - methodRefResult = CreateClassOrStructWriterMethodDefinition(objectTr); - } - - //If was not created. - if (methodRefResult == null) - RemoveFromStaticWriters(objectTr); - - return methodRefResult; - } - - /// - /// Removes from static writers. - /// - private void RemoveFromStaticWriters(TypeReference tr) - { - base.GetClass().RemoveWriterMethod(tr, false); - } - /// - /// Adds to static writers. - /// - private void AddToStaticWriters(TypeReference tr, MethodReference mr) - { - base.GetClass().AddWriterMethod(tr, mr.CachedResolve(base.Session), false, true); - } - - /// - /// Adds a write for a NetworkBehaviour class type to WriterMethods. - /// - /// - private MethodReference CreateNetworkBehaviourWriterMethodReference(TypeReference objectTr) - { - ObjectHelper oh = base.GetClass(); - - objectTr = base.ImportReference(objectTr.Resolve()); - //All NetworkBehaviour types will simply WriteNetworkBehaviour/ReadNetworkBehaviour. - //Create generated reader/writer class. This class holds all generated reader/writers. - base.GetClass().GetOrCreateClass(out _, GENERATED_TYPE_ATTRIBUTES, GENERATED_WRITERS_CLASS_NAME, null); - - MethodDefinition createdWriterMd = CreateStaticWriterStubMethodDefinition(objectTr); - AddToStaticWriters(objectTr, createdWriterMd); - - ILProcessor processor = createdWriterMd.Body.GetILProcessor(); - - MethodReference writeMethodRef = base.GetClass().GetOrCreateWriteMethodReference(oh.NetworkBehaviour_TypeRef); - //Get parameters for method. - ParameterDefinition writerParameterDef = createdWriterMd.Parameters[0]; - ParameterDefinition classParameterDef = createdWriterMd.Parameters[1]; - - //Load parameters as arguments. - processor.Emit(OpCodes.Ldarg, writerParameterDef); - processor.Emit(OpCodes.Ldarg, classParameterDef); - //writer.WriteNetworkBehaviour(arg1); - processor.Emit(OpCodes.Call, writeMethodRef); - - processor.Emit(OpCodes.Ret); - - return base.ImportReference(createdWriterMd); - } - - /// - /// Gets the length of a collection and writes the value to a variable. - /// - private void CreateCollectionLength(ILProcessor processor, ParameterDefinition collectionParameterDef, VariableDefinition storeVariableDef) - { - processor.Emit(OpCodes.Ldarg, collectionParameterDef); - processor.Emit(OpCodes.Ldlen); - processor.Emit(OpCodes.Conv_I4); - processor.Emit(OpCodes.Stloc, storeVariableDef); - } - - - /// - /// Creates a writer for a class or struct of objectTypeRef. - /// - /// - /// - private MethodReference CreateNullableWriterMethodReference(TypeReference objectTr, TypeDefinition objectTd) - { - WriterProcessor wh = base.GetClass(); - - GenericInstanceType objectGit = objectTr as GenericInstanceType; - TypeReference valueTr = objectGit.GenericArguments[0]; - - //Get the writer for the value. - MethodReference valueWriterMr = wh.GetOrCreateWriteMethodReference(valueTr); - if (valueWriterMr == null) - return null; - - - MethodDefinition tmpMd; - tmpMd = objectTd.GetMethod("get_Value"); - MethodReference genericGetValueMr = tmpMd.MakeHostInstanceGeneric(base.Session, objectGit); - tmpMd = objectTd.GetMethod("get_HasValue"); - MethodReference genericHasValueMr = tmpMd.MakeHostInstanceGeneric(base.Session, objectGit); - - /* Stubs generate Method(Writer writer, T value). */ - MethodDefinition createdWriterMd = CreateStaticWriterStubMethodDefinition(objectTr); - AddToStaticWriters(objectTr, createdWriterMd); - - ILProcessor processor = createdWriterMd.Body.GetILProcessor(); - - //Value parameter. - ParameterDefinition valuePd = createdWriterMd.Parameters[1]; - ParameterDefinition writerPd = createdWriterMd.Parameters[0]; - - //Have to write a new ret on null because nullables use hasValue for null checks. - Instruction afterNullRetInst = processor.Create(OpCodes.Nop); - processor.Emit(OpCodes.Ldarga, valuePd); - processor.Emit(OpCodes.Call, genericHasValueMr); - processor.Emit(OpCodes.Brtrue_S, afterNullRetInst); - wh.CreateWriteBool(processor, writerPd, true); - processor.Emit(OpCodes.Ret); - processor.Append(afterNullRetInst); - - //Code will only execute here and below if not null. - wh.CreateWriteBool(processor, writerPd, false); - - processor.Emit(OpCodes.Ldarg, writerPd); - processor.Emit(OpCodes.Ldarga, valuePd); - processor.Emit(OpCodes.Call, genericGetValueMr); - //If an auto pack method then insert default value. - if (wh.IsAutoPackedType(valueTr)) - { - AutoPackType packType = base.GetClass().GetDefaultAutoPackType(valueTr); - processor.Emit(OpCodes.Ldc_I4, (int)packType); - } - processor.Emit(OpCodes.Call, valueWriterMr); - - processor.Emit(OpCodes.Ret); - return base.ImportReference(createdWriterMd); - } - - - /// - /// Creates a writer for a class or struct of objectTypeRef. - /// - /// - /// - private MethodReference CreateClassOrStructWriterMethodDefinition(TypeReference objectTr) - { - WriterProcessor wh = base.GetClass(); - - /*Stubs generate Method(Writer writer, T value). */ - MethodDefinition createdWriterMd = CreateStaticWriterStubMethodDefinition(objectTr); - AddToStaticWriters(objectTr, createdWriterMd); - ILProcessor processor = createdWriterMd.Body.GetILProcessor(); - - //If not a value type then add a null check. - if (!objectTr.CachedResolve(base.Session).IsValueType) - { - ParameterDefinition writerPd = createdWriterMd.Parameters[0]; - wh.CreateRetOnNull(processor, writerPd, createdWriterMd.Parameters[1], true); - //Code will only execute here and below if not null. - wh.CreateWriteBool(processor, writerPd, false); - } - - //Write all fields for the class or struct. - ParameterDefinition valueParameterDef = createdWriterMd.Parameters[1]; - if (!WriteFieldsAndProperties(createdWriterMd, valueParameterDef, objectTr)) - return null; - - processor.Emit(OpCodes.Ret); - return base.ImportReference(createdWriterMd); - } - - /// - /// Find all fields in type and write them - /// - /// - /// - /// false if fail - private bool WriteFieldsAndProperties(MethodDefinition generatedWriteMd, ParameterDefinition valuePd, TypeReference objectTr) - { - WriterProcessor wh = base.GetClass(); - - //This probably isn't needed but I'm too afraid to remove it. - if (objectTr.Module != base.Module) - objectTr = base.ImportReference(objectTr.CachedResolve(base.Session)); - - //Fields - foreach (FieldDefinition fieldDef in objectTr.FindAllSerializableFields(base.Session))//, WriterHelper.EXCLUDED_AUTO_SERIALIZER_TYPES)) - { - TypeReference tr; - if (fieldDef.FieldType.IsGenericInstance) - { - GenericInstanceType genericTr = (GenericInstanceType)fieldDef.FieldType; - tr = genericTr.GenericArguments[0]; - } - else - { - tr = fieldDef.FieldType; - } - if (GetWriteMethod(fieldDef.FieldType, out MethodReference writeMr)) - wh.CreateWrite(generatedWriteMd, valuePd, fieldDef, writeMr); - } - - //Properties. - foreach (PropertyDefinition propertyDef in objectTr.FindAllSerializableProperties(base.Session - , WriterProcessor.EXCLUDED_AUTO_SERIALIZER_TYPES, WriterProcessor.EXCLUDED_ASSEMBLY_PREFIXES)) - { - if (GetWriteMethod(propertyDef.PropertyType, out MethodReference writerMr)) - { - MethodReference getMr = base.Module.ImportReference(propertyDef.GetMethod); - wh.CreateWrite(generatedWriteMd, valuePd, getMr, writerMr); - } - } - - //Gets or creates writer method and outputs it. Returns true if method is found or created. - bool GetWriteMethod(TypeReference tr, out MethodReference writeMr) - { - tr = base.ImportReference(tr); - writeMr = wh.GetOrCreateWriteMethodReference(tr); - return (writeMr != null); - } - - return true; - } - - - /// - /// Creates a writer for an enum. - /// - /// - /// - private MethodReference CreateEnumWriterMethodDefinition(TypeReference enumTr) - { - WriterProcessor wh = base.GetClass(); - - MethodDefinition createdWriterMd = CreateStaticWriterStubMethodDefinition(enumTr); - AddToStaticWriters(enumTr, createdWriterMd); - - ILProcessor processor = createdWriterMd.Body.GetILProcessor(); - - //Element type for enum. EG: byte int ect - TypeReference underlyingTypeRef = enumTr.CachedResolve(base.Session).GetEnumUnderlyingTypeReference(); - //Method to write that type. - MethodReference underlyingWriterMethodRef = wh.GetOrCreateWriteMethodReference(underlyingTypeRef); - if (underlyingWriterMethodRef == null) - return null; - - ParameterDefinition writerParameterDef = createdWriterMd.Parameters[0]; - ParameterDefinition valueParameterDef = createdWriterMd.Parameters[1]; - //Push writer and value into call. - processor.Emit(OpCodes.Ldarg, writerParameterDef); - processor.Emit(OpCodes.Ldarg, valueParameterDef); - if (wh.IsAutoPackedType(underlyingTypeRef)) - processor.Emit(OpCodes.Ldc_I4, (int)AutoPackType.Packed); - - //writer.WriteXXX(value) - processor.Emit(OpCodes.Call, underlyingWriterMethodRef); - - processor.Emit(OpCodes.Ret); - return base.ImportReference(createdWriterMd); - } - - /// - /// Calls an instanced writer from a static writer. - /// - private void CallInstancedWriter(MethodDefinition staticWriterMd, MethodReference instancedWriterMr) - { - ParameterDefinition writerPd = staticWriterMd.Parameters[0]; - ParameterDefinition valuePd = staticWriterMd.Parameters[1]; - ILProcessor processor = staticWriterMd.Body.GetILProcessor(); - processor.Emit(OpCodes.Ldarg, writerPd); - processor.Emit(OpCodes.Ldarg, valuePd); - processor.Emit(instancedWriterMr.GetCallOpCode(base.Session), instancedWriterMr); - processor.Emit(OpCodes.Ret); - } - - /// - /// Creates a writer for an array. - /// - private MethodReference CreateArrayWriterMethodReference(TypeReference objectTr) - { - WriterImports wi = base.GetClass(); - TypeReference valueTr = objectTr.GetElementType(); - - //Write not found. - if (GetOrCreateWriteMethodReference(valueTr) == null) - return null; - - MethodDefinition createdMd = CreateStaticWriterStubMethodDefinition(objectTr); - AddToStaticWriters(objectTr, createdMd); - - //Find instanced writer to use. - MethodReference instancedWriteMr = wi.Writer_WriteArray_MethodRef; - //Make generic. - GenericInstanceMethod writeGim = instancedWriteMr.MakeGenericMethod(new TypeReference[] { valueTr }); - CallInstancedWriter(createdMd, writeGim); - - return base.ImportReference(createdMd); - } - - /// - /// Creates a writer for a variety of generic collections. - /// - private MethodReference CreateGenericCollectionWriterMethodReference(TypeReference objectTr, SerializerType st) - { - WriterImports wi = base.GetClass(); - //Make value field generic. - GenericInstanceType genericInstance = (GenericInstanceType)objectTr; - base.ImportReference(genericInstance); - TypeReference valueTr = genericInstance.GenericArguments[0]; - - List genericArguments = new List(); - //Make sure all arguments have writers. - foreach (TypeReference gaTr in genericInstance.GenericArguments) - { - MethodReference mr = GetOrCreateWriteMethodReference(gaTr); - //Writer not found. - if (mr == null) - { - base.LogError($"Writer could not be found or created for type {gaTr.FullName}."); - return null; - } - - genericArguments.Add(gaTr); - } - MethodReference valueWriteMr = GetOrCreateWriteMethodReference(valueTr); - if (valueWriteMr == null) - return null; - - MethodDefinition createdMd = CreateStaticWriterStubMethodDefinition(objectTr); - AddToStaticWriters(objectTr, createdMd); - - //Find instanced writer to use. - MethodReference instancedWriteMr; - if (st == SerializerType.Dictionary) - instancedWriteMr = wi.Writer_WriteDictionary_MethodRef; - else if (st == SerializerType.List) - instancedWriteMr = wi.Writer_WriteList_MethodRef; - else if (st == SerializerType.ListCache) - instancedWriteMr = wi.Writer_WriteListCache_MethodRef; - else - instancedWriteMr = null; - - //Not found. - if (instancedWriteMr == null) - { - base.LogError($"Instanced writer not found for SerializerType {st} on object {objectTr.Name}."); - return null; - } - - //Make generic. - GenericInstanceMethod writeGim = instancedWriteMr.MakeGenericMethod(genericArguments.ToArray()); - CallInstancedWriter(createdMd, writeGim); - - return base.ImportReference(createdMd); - } - - /// - /// Creates a method definition stub for objectTypeRef. - /// - /// - /// - public MethodDefinition CreateStaticWriterStubMethodDefinition(TypeReference objectTypeRef, string nameExtension = WriterProcessor.GENERATED_WRITER_NAMESPACE) - { - string methodName = $"{GENERATED_WRITE_PREFIX}{objectTypeRef.FullName}{nameExtension}"; - // create new writer for this type - TypeDefinition writerTypeDef = base.GetClass().GetOrCreateClass(out _, GENERATED_TYPE_ATTRIBUTES, GENERATED_WRITERS_CLASS_NAME, null); - - MethodDefinition writerMethodDef = writerTypeDef.AddMethod(methodName, - MethodAttributes.Public | - MethodAttributes.Static | - MethodAttributes.HideBySig); - - base.GetClass().CreateParameter(writerMethodDef, base.GetClass().Writer_TypeRef, "writer"); - base.GetClass().CreateParameter(writerMethodDef, objectTypeRef, "value"); - base.GetClass().MakeExtensionMethod(writerMethodDef); - writerMethodDef.Body.InitLocals = true; - - return writerMethodDef; - } - #endregion - - } -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/Processing/WriterProcessor.cs.meta b/Assets/FishNet/CodeGenerating/Processing/WriterProcessor.cs.meta deleted file mode 100644 index 9ba1d8a..0000000 --- a/Assets/FishNet/CodeGenerating/Processing/WriterProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2a4021bd44dc40f47abb494e0a4326f9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/Unity.FishNet.CodeGen.asmdef b/Assets/FishNet/CodeGenerating/Unity.FishNet.CodeGen.asmdef deleted file mode 100644 index 30efa59..0000000 --- a/Assets/FishNet/CodeGenerating/Unity.FishNet.CodeGen.asmdef +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "Unity.FishNet.Codegen", - "references": [ - "FishNet.Runtime", - "FishNet.Codegen.Cecil", - "FishNet.Generated" - ], - "includePlatforms": [ - "Editor" - ], - "excludePlatforms": [], - "allowUnsafeCode": true, - "overrideReferences": true, - "precompiledReferences": [], - "autoReferenced": false, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4.meta deleted file mode 100644 index ec9a868..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 7f482f18100f20045bd2188d839d9217 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Directory.Build.props b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Directory.Build.props deleted file mode 100644 index ee63f7a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Directory.Build.props +++ /dev/null @@ -1,30 +0,0 @@ - - - false - false - false - Debug;Release - true - true - $(MSBuildThisFileDirectory)\cecil.snk - $(DefineConstants);NET_CORE - - - - true - - - - - - - - - - - - - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), Mono.Cecil.overrides))\Mono.Cecil.overrides - - - diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/LICENSE.txt b/Assets/FishNet/CodeGenerating/cecil-0.11.4/LICENSE.txt deleted file mode 100644 index afd0ae6..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -Copyright (c) 2008 - 2015 Jb Evain -Copyright (c) 2008 - 2011 Novell, Inc. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil.meta deleted file mode 100644 index c287230..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 952f0fa3545cde844afce313f2b2f3b9 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Code.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Code.cs deleted file mode 100644 index ce5c6e0..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Code.cs +++ /dev/null @@ -1,234 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil.Cil { - - public enum Code { - Nop, - Break, - Ldarg_0, - Ldarg_1, - Ldarg_2, - Ldarg_3, - Ldloc_0, - Ldloc_1, - Ldloc_2, - Ldloc_3, - Stloc_0, - Stloc_1, - Stloc_2, - Stloc_3, - Ldarg_S, - Ldarga_S, - Starg_S, - Ldloc_S, - Ldloca_S, - Stloc_S, - Ldnull, - Ldc_I4_M1, - Ldc_I4_0, - Ldc_I4_1, - Ldc_I4_2, - Ldc_I4_3, - Ldc_I4_4, - Ldc_I4_5, - Ldc_I4_6, - Ldc_I4_7, - Ldc_I4_8, - Ldc_I4_S, - Ldc_I4, - Ldc_I8, - Ldc_R4, - Ldc_R8, - Dup, - Pop, - Jmp, - Call, - Calli, - Ret, - Br_S, - Brfalse_S, - Brtrue_S, - Beq_S, - Bge_S, - Bgt_S, - Ble_S, - Blt_S, - Bne_Un_S, - Bge_Un_S, - Bgt_Un_S, - Ble_Un_S, - Blt_Un_S, - Br, - Brfalse, - Brtrue, - Beq, - Bge, - Bgt, - Ble, - Blt, - Bne_Un, - Bge_Un, - Bgt_Un, - Ble_Un, - Blt_Un, - Switch, - Ldind_I1, - Ldind_U1, - Ldind_I2, - Ldind_U2, - Ldind_I4, - Ldind_U4, - Ldind_I8, - Ldind_I, - Ldind_R4, - Ldind_R8, - Ldind_Ref, - Stind_Ref, - Stind_I1, - Stind_I2, - Stind_I4, - Stind_I8, - Stind_R4, - Stind_R8, - Add, - Sub, - Mul, - Div, - Div_Un, - Rem, - Rem_Un, - And, - Or, - Xor, - Shl, - Shr, - Shr_Un, - Neg, - Not, - Conv_I1, - Conv_I2, - Conv_I4, - Conv_I8, - Conv_R4, - Conv_R8, - Conv_U4, - Conv_U8, - Callvirt, - Cpobj, - Ldobj, - Ldstr, - Newobj, - Castclass, - Isinst, - Conv_R_Un, - Unbox, - Throw, - Ldfld, - Ldflda, - Stfld, - Ldsfld, - Ldsflda, - Stsfld, - Stobj, - Conv_Ovf_I1_Un, - Conv_Ovf_I2_Un, - Conv_Ovf_I4_Un, - Conv_Ovf_I8_Un, - Conv_Ovf_U1_Un, - Conv_Ovf_U2_Un, - Conv_Ovf_U4_Un, - Conv_Ovf_U8_Un, - Conv_Ovf_I_Un, - Conv_Ovf_U_Un, - Box, - Newarr, - Ldlen, - Ldelema, - Ldelem_I1, - Ldelem_U1, - Ldelem_I2, - Ldelem_U2, - Ldelem_I4, - Ldelem_U4, - Ldelem_I8, - Ldelem_I, - Ldelem_R4, - Ldelem_R8, - Ldelem_Ref, - Stelem_I, - Stelem_I1, - Stelem_I2, - Stelem_I4, - Stelem_I8, - Stelem_R4, - Stelem_R8, - Stelem_Ref, - Ldelem_Any, - Stelem_Any, - Unbox_Any, - Conv_Ovf_I1, - Conv_Ovf_U1, - Conv_Ovf_I2, - Conv_Ovf_U2, - Conv_Ovf_I4, - Conv_Ovf_U4, - Conv_Ovf_I8, - Conv_Ovf_U8, - Refanyval, - Ckfinite, - Mkrefany, - Ldtoken, - Conv_U2, - Conv_U1, - Conv_I, - Conv_Ovf_I, - Conv_Ovf_U, - Add_Ovf, - Add_Ovf_Un, - Mul_Ovf, - Mul_Ovf_Un, - Sub_Ovf, - Sub_Ovf_Un, - Endfinally, - Leave, - Leave_S, - Stind_I, - Conv_U, - Arglist, - Ceq, - Cgt, - Cgt_Un, - Clt, - Clt_Un, - Ldftn, - Ldvirtftn, - Ldarg, - Ldarga, - Starg, - Ldloc, - Ldloca, - Stloc, - Localloc, - Endfilter, - Unaligned, - Volatile, - Tail, - Initobj, - Constrained, - Cpblk, - Initblk, - No, - Rethrow, - Sizeof, - Refanytype, - Readonly, - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Code.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Code.cs.meta deleted file mode 100644 index 087491a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Code.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2619210c5ef352b4aac70d8e5fab7a43 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeReader.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeReader.cs deleted file mode 100644 index 206b49a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeReader.cs +++ /dev/null @@ -1,663 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.PE; -using MonoFN.Collections.Generic; -using System; - -namespace MonoFN.Cecil.Cil { - - sealed class CodeReader : BinaryStreamReader { - - readonly internal MetadataReader reader; - - int start; - - MethodDefinition method; - MethodBody body; - - int Offset { - get { return Position - start; } - } - - public CodeReader (MetadataReader reader) - : base (reader.image.Stream.value) - { - this.reader = reader; - } - - public int MoveTo (MethodDefinition method) - { - this.method = method; - this.reader.context = method; - var position = this.Position; - this.Position = (int)reader.image.ResolveVirtualAddress ((uint)method.RVA); - return position; - } - - public void MoveBackTo (int position) - { - this.reader.context = null; - this.Position = position; - } - - public MethodBody ReadMethodBody (MethodDefinition method) - { - var position = MoveTo (method); - this.body = new MethodBody (method); - - ReadMethodBody (); - - MoveBackTo (position); - return this.body; - } - - public int ReadCodeSize (MethodDefinition method) - { - var position = MoveTo (method); - - var code_size = ReadCodeSize (); - - MoveBackTo (position); - return code_size; - } - - int ReadCodeSize () - { - var flags = ReadByte (); - switch (flags & 0x3) { - case 0x2: // tiny - return flags >> 2; - case 0x3: // fat - Advance (-1 + 2 + 2); // go back, 2 bytes flags, 2 bytes stack size - return (int)ReadUInt32 (); - default: - throw new InvalidOperationException (); - } - } - - void ReadMethodBody () - { - var flags = ReadByte (); - switch (flags & 0x3) { - case 0x2: // tiny - body.code_size = flags >> 2; - body.MaxStackSize = 8; - ReadCode (); - break; - case 0x3: // fat - Advance (-1); - ReadFatMethod (); - break; - default: - throw new InvalidOperationException (); - } - - var symbol_reader = reader.module.symbol_reader; - - if (symbol_reader != null && method.debug_info == null) - method.debug_info = symbol_reader.Read (method); - - if (method.debug_info != null) - ReadDebugInfo (); - } - - void ReadFatMethod () - { - var flags = ReadUInt16 (); - body.max_stack_size = ReadUInt16 (); - body.code_size = (int)ReadUInt32 (); - body.local_var_token = new MetadataToken (ReadUInt32 ()); - body.init_locals = (flags & 0x10) != 0; - - if (body.local_var_token.RID != 0) - body.variables = ReadVariables (body.local_var_token); - - ReadCode (); - - if ((flags & 0x8) != 0) - ReadSection (); - } - - public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token) - { - var position = reader.position; - var variables = reader.ReadVariables (local_var_token, method); - reader.position = position; - - return variables; - } - - void ReadCode () - { - start = Position; - var code_size = body.code_size; - - if (code_size < 0 || Length <= (uint)(code_size + Position)) - code_size = 0; - - var end = start + code_size; - var instructions = body.instructions = new InstructionCollection (method, (code_size + 1) / 2); - - while (Position < end) { - var offset = Position - start; - var opcode = ReadOpCode (); - var current = new Instruction (offset, opcode); - - if (opcode.OperandType != OperandType.InlineNone) - current.operand = ReadOperand (current); - - instructions.Add (current); - } - - ResolveBranches (instructions); - } - - OpCode ReadOpCode () - { - var il_opcode = ReadByte (); - return il_opcode != 0xfe - ? OpCodes.OneByteOpCode [il_opcode] - : OpCodes.TwoBytesOpCode [ReadByte ()]; - } - - object ReadOperand (Instruction instruction) - { - switch (instruction.opcode.OperandType) { - case OperandType.InlineSwitch: - var length = ReadInt32 (); - var base_offset = Offset + (4 * length); - var branches = new int [length]; - for (int i = 0; i < length; i++) - branches [i] = base_offset + ReadInt32 (); - return branches; - case OperandType.ShortInlineBrTarget: - return ReadSByte () + Offset; - case OperandType.InlineBrTarget: - return ReadInt32 () + Offset; - case OperandType.ShortInlineI: - if (instruction.opcode == OpCodes.Ldc_I4_S) - return ReadSByte (); - - return ReadByte (); - case OperandType.InlineI: - return ReadInt32 (); - case OperandType.ShortInlineR: - return ReadSingle (); - case OperandType.InlineR: - return ReadDouble (); - case OperandType.InlineI8: - return ReadInt64 (); - case OperandType.ShortInlineVar: - return GetVariable (ReadByte ()); - case OperandType.InlineVar: - return GetVariable (ReadUInt16 ()); - case OperandType.ShortInlineArg: - return GetParameter (ReadByte ()); - case OperandType.InlineArg: - return GetParameter (ReadUInt16 ()); - case OperandType.InlineSig: - return GetCallSite (ReadToken ()); - case OperandType.InlineString: - return GetString (ReadToken ()); - case OperandType.InlineTok: - case OperandType.InlineType: - case OperandType.InlineMethod: - case OperandType.InlineField: - return reader.LookupToken (ReadToken ()); - default: - throw new NotSupportedException (); - } - } - - public string GetString (MetadataToken token) - { - return reader.image.UserStringHeap.Read (token.RID); - } - - public ParameterDefinition GetParameter (int index) - { - return body.GetParameter (index); - } - - public VariableDefinition GetVariable (int index) - { - return body.GetVariable (index); - } - - public CallSite GetCallSite (MetadataToken token) - { - return reader.ReadCallSite (token); - } - - void ResolveBranches (Collection instructions) - { - var items = instructions.items; - var size = instructions.size; - - for (int i = 0; i < size; i++) { - var instruction = items [i]; - switch (instruction.opcode.OperandType) { - case OperandType.ShortInlineBrTarget: - case OperandType.InlineBrTarget: - instruction.operand = GetInstruction ((int)instruction.operand); - break; - case OperandType.InlineSwitch: - var offsets = (int [])instruction.operand; - var branches = new Instruction [offsets.Length]; - for (int j = 0; j < offsets.Length; j++) - branches [j] = GetInstruction (offsets [j]); - - instruction.operand = branches; - break; - } - } - } - - Instruction GetInstruction (int offset) - { - return GetInstruction (body.Instructions, offset); - } - - static Instruction GetInstruction (Collection instructions, int offset) - { - var size = instructions.size; - var items = instructions.items; - if (offset < 0 || offset > items [size - 1].offset) - return null; - - int min = 0; - int max = size - 1; - while (min <= max) { - int mid = min + ((max - min) / 2); - var instruction = items [mid]; - var instruction_offset = instruction.offset; - - if (offset == instruction_offset) - return instruction; - - if (offset < instruction_offset) - max = mid - 1; - else - min = mid + 1; - } - - return null; - } - - void ReadSection () - { - Align (4); - - const byte fat_format = 0x40; - const byte more_sects = 0x80; - - var flags = ReadByte (); - if ((flags & fat_format) == 0) - ReadSmallSection (); - else - ReadFatSection (); - - if ((flags & more_sects) != 0) - ReadSection (); - } - - void ReadSmallSection () - { - var count = ReadByte () / 12; - Advance (2); - - ReadExceptionHandlers ( - count, - () => (int)ReadUInt16 (), - () => (int)ReadByte ()); - } - - void ReadFatSection () - { - Advance (-1); - var count = (ReadInt32 () >> 8) / 24; - - ReadExceptionHandlers ( - count, - ReadInt32, - ReadInt32); - } - - // inline ? - void ReadExceptionHandlers (int count, Func read_entry, Func read_length) - { - for (int i = 0; i < count; i++) { - var handler = new ExceptionHandler ( - (ExceptionHandlerType)(read_entry () & 0x7)); - - handler.TryStart = GetInstruction (read_entry ()); - handler.TryEnd = GetInstruction (handler.TryStart.Offset + read_length ()); - - handler.HandlerStart = GetInstruction (read_entry ()); - handler.HandlerEnd = GetInstruction (handler.HandlerStart.Offset + read_length ()); - - ReadExceptionHandlerSpecific (handler); - - this.body.ExceptionHandlers.Add (handler); - } - } - - void ReadExceptionHandlerSpecific (ExceptionHandler handler) - { - switch (handler.HandlerType) { - case ExceptionHandlerType.Catch: - handler.CatchType = (TypeReference)reader.LookupToken (ReadToken ()); - break; - case ExceptionHandlerType.Filter: - handler.FilterStart = GetInstruction (ReadInt32 ()); - break; - default: - Advance (4); - break; - } - } - - public MetadataToken ReadToken () - { - return new MetadataToken (ReadUInt32 ()); - } - - void ReadDebugInfo () - { - if (method.debug_info.sequence_points != null) - ReadSequencePoints (); - - if (method.debug_info.scope != null) - ReadScope (method.debug_info.scope); - - if (method.custom_infos != null) - ReadCustomDebugInformations (method); - } - - void ReadCustomDebugInformations (MethodDefinition method) - { - var custom_infos = method.custom_infos; - - for (int i = 0; i < custom_infos.Count; i++) { - var state_machine_scope = custom_infos [i] as StateMachineScopeDebugInformation; - if (state_machine_scope != null) - ReadStateMachineScope (state_machine_scope); - - var async_method = custom_infos [i] as AsyncMethodBodyDebugInformation; - if (async_method != null) - ReadAsyncMethodBody (async_method); - } - } - - void ReadAsyncMethodBody (AsyncMethodBodyDebugInformation async_method) - { - if (async_method.catch_handler.Offset > -1) - async_method.catch_handler = new InstructionOffset (GetInstruction (async_method.catch_handler.Offset)); - - if (!async_method.yields.IsNullOrEmpty ()) - for (int i = 0; i < async_method.yields.Count; i++) - async_method.yields [i] = new InstructionOffset (GetInstruction (async_method.yields [i].Offset)); - - if (!async_method.resumes.IsNullOrEmpty ()) - for (int i = 0; i < async_method.resumes.Count; i++) - async_method.resumes [i] = new InstructionOffset (GetInstruction (async_method.resumes [i].Offset)); - } - - void ReadStateMachineScope (StateMachineScopeDebugInformation state_machine_scope) - { - if (state_machine_scope.scopes.IsNullOrEmpty ()) - return; - - foreach (var scope in state_machine_scope.scopes) { - scope.start = new InstructionOffset (GetInstruction (scope.start.Offset)); - - var end_instruction = GetInstruction (scope.end.Offset); - scope.end = end_instruction == null - ? new InstructionOffset () - : new InstructionOffset (end_instruction); - } - } - - void ReadSequencePoints () - { - var symbol = method.debug_info; - - for (int i = 0; i < symbol.sequence_points.Count; i++) { - var sequence_point = symbol.sequence_points [i]; - var instruction = GetInstruction (sequence_point.Offset); - if (instruction != null) - sequence_point.offset = new InstructionOffset (instruction); - } - } - - void ReadScopes (Collection scopes) - { - for (int i = 0; i < scopes.Count; i++) - ReadScope (scopes [i]); - } - - void ReadScope (ScopeDebugInformation scope) - { - var start_instruction = GetInstruction (scope.Start.Offset); - if (start_instruction != null) - scope.Start = new InstructionOffset (start_instruction); - - var end_instruction = GetInstruction (scope.End.Offset); - scope.End = end_instruction != null - ? new InstructionOffset (end_instruction) - : new InstructionOffset (); - - if (!scope.variables.IsNullOrEmpty ()) { - for (int i = 0; i < scope.variables.Count; i++) { - var variable_info = scope.variables [i]; - var variable = GetVariable (variable_info.Index); - if (variable != null) - variable_info.index = new VariableIndex (variable); - } - } - - if (!scope.scopes.IsNullOrEmpty ()) - ReadScopes (scope.scopes); - } - - public ByteBuffer PatchRawMethodBody (MethodDefinition method, CodeWriter writer, out int code_size, out MetadataToken local_var_token) - { - var position = MoveTo (method); - - var buffer = new ByteBuffer (); - - var flags = ReadByte (); - - switch (flags & 0x3) { - case 0x2: // tiny - buffer.WriteByte (flags); - local_var_token = MetadataToken.Zero; - code_size = flags >> 2; - PatchRawCode (buffer, code_size, writer); - break; - case 0x3: // fat - Advance (-1); - PatchRawFatMethod (buffer, writer, out code_size, out local_var_token); - break; - default: - throw new NotSupportedException (); - } - - MoveBackTo (position); - - return buffer; - } - - void PatchRawFatMethod (ByteBuffer buffer, CodeWriter writer, out int code_size, out MetadataToken local_var_token) - { - var flags = ReadUInt16 (); - buffer.WriteUInt16 (flags); - buffer.WriteUInt16 (ReadUInt16 ()); - code_size = ReadInt32 (); - buffer.WriteInt32 (code_size); - local_var_token = ReadToken (); - - if (local_var_token.RID > 0) { - var variables = ReadVariables (local_var_token); - buffer.WriteUInt32 (variables != null - ? writer.GetStandAloneSignature (variables).ToUInt32 () - : 0); - } else - buffer.WriteUInt32 (0); - - PatchRawCode (buffer, code_size, writer); - - if ((flags & 0x8) != 0) - PatchRawSection (buffer, writer.metadata); - } - - void PatchRawCode (ByteBuffer buffer, int code_size, CodeWriter writer) - { - var metadata = writer.metadata; - buffer.WriteBytes (ReadBytes (code_size)); - var end = buffer.position; - buffer.position -= code_size; - - while (buffer.position < end) { - OpCode opcode; - var il_opcode = buffer.ReadByte (); - if (il_opcode != 0xfe) { - opcode = OpCodes.OneByteOpCode [il_opcode]; - } else { - var il_opcode2 = buffer.ReadByte (); - opcode = OpCodes.TwoBytesOpCode [il_opcode2]; - } - - switch (opcode.OperandType) { - case OperandType.ShortInlineI: - case OperandType.ShortInlineBrTarget: - case OperandType.ShortInlineVar: - case OperandType.ShortInlineArg: - buffer.position += 1; - break; - case OperandType.InlineVar: - case OperandType.InlineArg: - buffer.position += 2; - break; - case OperandType.InlineBrTarget: - case OperandType.ShortInlineR: - case OperandType.InlineI: - buffer.position += 4; - break; - case OperandType.InlineI8: - case OperandType.InlineR: - buffer.position += 8; - break; - case OperandType.InlineSwitch: - var length = buffer.ReadInt32 (); - buffer.position += length * 4; - break; - case OperandType.InlineString: - var @string = GetString (new MetadataToken (buffer.ReadUInt32 ())); - buffer.position -= 4; - buffer.WriteUInt32 ( - new MetadataToken ( - TokenType.String, - metadata.user_string_heap.GetStringIndex (@string)).ToUInt32 ()); - break; - case OperandType.InlineSig: - var call_site = GetCallSite (new MetadataToken (buffer.ReadUInt32 ())); - buffer.position -= 4; - buffer.WriteUInt32 (writer.GetStandAloneSignature (call_site).ToUInt32 ()); - break; - case OperandType.InlineTok: - case OperandType.InlineType: - case OperandType.InlineMethod: - case OperandType.InlineField: - var provider = reader.LookupToken (new MetadataToken (buffer.ReadUInt32 ())); - buffer.position -= 4; - buffer.WriteUInt32 (metadata.LookupToken (provider).ToUInt32 ()); - break; - } - } - } - - void PatchRawSection (ByteBuffer buffer, MetadataBuilder metadata) - { - var position = Position; - Align (4); - buffer.WriteBytes (Position - position); - - const byte fat_format = 0x40; - const byte more_sects = 0x80; - - var flags = ReadByte (); - if ((flags & fat_format) == 0) { - buffer.WriteByte (flags); - PatchRawSmallSection (buffer, metadata); - } else - PatchRawFatSection (buffer, metadata); - - if ((flags & more_sects) != 0) - PatchRawSection (buffer, metadata); - } - - void PatchRawSmallSection (ByteBuffer buffer, MetadataBuilder metadata) - { - var length = ReadByte (); - buffer.WriteByte (length); - Advance (2); - - buffer.WriteUInt16 (0); - - var count = length / 12; - - PatchRawExceptionHandlers (buffer, metadata, count, false); - } - - void PatchRawFatSection (ByteBuffer buffer, MetadataBuilder metadata) - { - Advance (-1); - var length = ReadInt32 (); - buffer.WriteInt32 (length); - - var count = (length >> 8) / 24; - - PatchRawExceptionHandlers (buffer, metadata, count, true); - } - - void PatchRawExceptionHandlers (ByteBuffer buffer, MetadataBuilder metadata, int count, bool fat_entry) - { - const int fat_entry_size = 16; - const int small_entry_size = 6; - - for (int i = 0; i < count; i++) { - ExceptionHandlerType handler_type; - if (fat_entry) { - var type = ReadUInt32 (); - handler_type = (ExceptionHandlerType)(type & 0x7); - buffer.WriteUInt32 (type); - } else { - var type = ReadUInt16 (); - handler_type = (ExceptionHandlerType)(type & 0x7); - buffer.WriteUInt16 (type); - } - - buffer.WriteBytes (ReadBytes (fat_entry ? fat_entry_size : small_entry_size)); - - switch (handler_type) { - case ExceptionHandlerType.Catch: - var exception = reader.LookupToken (ReadToken ()); - buffer.WriteUInt32 (metadata.LookupToken (exception).ToUInt32 ()); - break; - default: - buffer.WriteUInt32 (ReadUInt32 ()); - break; - } - } - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeReader.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeReader.cs.meta deleted file mode 100644 index 4bf35a7..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeReader.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 451f6a2407c53554f9a16eeb62d806ce -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeWriter.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeWriter.cs deleted file mode 100644 index e7126e8..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeWriter.cs +++ /dev/null @@ -1,651 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Metadata; -using MonoFN.Cecil.PE; -using MonoFN.Collections.Generic; -using System; -using System.Collections.Generic; -using RVA = System.UInt32; - -namespace MonoFN.Cecil.Cil { - - sealed class CodeWriter : ByteBuffer { - - readonly RVA code_base; - internal readonly MetadataBuilder metadata; - readonly Dictionary standalone_signatures; - readonly Dictionary tiny_method_bodies; - - MethodBody body; - - public CodeWriter (MetadataBuilder metadata) - : base (0) - { - this.code_base = metadata.text_map.GetNextRVA (TextSegment.CLIHeader); - this.metadata = metadata; - this.standalone_signatures = new Dictionary (); - this.tiny_method_bodies = new Dictionary (new ByteBufferEqualityComparer ()); - } - - public RVA WriteMethodBody (MethodDefinition method) - { - RVA rva; - - if (IsUnresolved (method)) { - if (method.rva == 0) - return 0; - - rva = WriteUnresolvedMethodBody (method); - } else { - if (IsEmptyMethodBody (method.Body)) - return 0; - - rva = WriteResolvedMethodBody (method); - } - - return rva; - } - - static bool IsEmptyMethodBody (MethodBody body) - { - return body.instructions.IsNullOrEmpty () - && body.variables.IsNullOrEmpty (); - } - - static bool IsUnresolved (MethodDefinition method) - { - return method.HasBody && method.HasImage && method.body == null; - } - - RVA WriteUnresolvedMethodBody (MethodDefinition method) - { - var code_reader = metadata.module.reader.code; - - int code_size; - MetadataToken local_var_token; - var raw_body = code_reader.PatchRawMethodBody (method, this, out code_size, out local_var_token); - var fat_header = (raw_body.buffer [0] & 0x3) == 0x3; - if (fat_header) - Align (4); - - var rva = BeginMethod (); - - if (fat_header || !GetOrMapTinyMethodBody (raw_body, ref rva)) { - WriteBytes (raw_body); - } - - if (method.debug_info == null) - return rva; - - var symbol_writer = metadata.symbol_writer; - if (symbol_writer != null) { - method.debug_info.code_size = code_size; - method.debug_info.local_var_token = local_var_token; - symbol_writer.Write (method.debug_info); - } - - return rva; - } - - RVA WriteResolvedMethodBody (MethodDefinition method) - { - RVA rva; - - body = method.Body; - ComputeHeader (); - if (RequiresFatHeader ()) { - Align (4); - rva = BeginMethod (); - WriteFatHeader (); - WriteInstructions (); - - if (body.HasExceptionHandlers) - WriteExceptionHandlers (); - } else { - rva = BeginMethod (); - WriteByte ((byte)(0x2 | (body.CodeSize << 2))); // tiny - WriteInstructions (); - - var start_position = (int)(rva - code_base); - var body_size = position - start_position; - var body_bytes = new byte [body_size]; - - Array.Copy (buffer, start_position, body_bytes, 0, body_size); - - if (GetOrMapTinyMethodBody (new ByteBuffer (body_bytes), ref rva)) - position = start_position; - } - - var symbol_writer = metadata.symbol_writer; - if (symbol_writer != null && method.debug_info != null) { - method.debug_info.code_size = body.CodeSize; - method.debug_info.local_var_token = body.local_var_token; - symbol_writer.Write (method.debug_info); - } - - return rva; - } - - bool GetOrMapTinyMethodBody (ByteBuffer body, ref RVA rva) - { - RVA existing_rva; - if (tiny_method_bodies.TryGetValue (body, out existing_rva)) { - rva = existing_rva; - return true; - } - - tiny_method_bodies.Add (body, rva); - return false; - } - - void WriteFatHeader () - { - var body = this.body; - byte flags = 0x3; // fat - if (body.InitLocals) - flags |= 0x10; // init locals - if (body.HasExceptionHandlers) - flags |= 0x8; // more sections - - WriteByte (flags); - WriteByte (0x30); - WriteInt16 ((short)body.max_stack_size); - WriteInt32 (body.code_size); - body.local_var_token = body.HasVariables - ? GetStandAloneSignature (body.Variables) - : MetadataToken.Zero; - WriteMetadataToken (body.local_var_token); - } - - void WriteInstructions () - { - var instructions = body.Instructions; - var items = instructions.items; - var size = instructions.size; - - for (int i = 0; i < size; i++) { - var instruction = items [i]; - WriteOpCode (instruction.opcode); - WriteOperand (instruction); - } - } - - void WriteOpCode (OpCode opcode) - { - if (opcode.Size == 1) { - WriteByte (opcode.Op2); - } else { - WriteByte (opcode.Op1); - WriteByte (opcode.Op2); - } - } - - void WriteOperand (Instruction instruction) - { - var opcode = instruction.opcode; - var operand_type = opcode.OperandType; - if (operand_type == OperandType.InlineNone) - return; - - var operand = instruction.operand; - if (operand == null && !(operand_type == OperandType.InlineBrTarget || operand_type == OperandType.ShortInlineBrTarget)) { - throw new ArgumentException (); - } - - switch (operand_type) { - case OperandType.InlineSwitch: { - var targets = (Instruction [])operand; - WriteInt32 (targets.Length); - var diff = instruction.Offset + opcode.Size + (4 * (targets.Length + 1)); - for (int i = 0; i < targets.Length; i++) - WriteInt32 (GetTargetOffset (targets [i]) - diff); - break; - } - case OperandType.ShortInlineBrTarget: { - var target = (Instruction)operand; - var offset = target != null ? GetTargetOffset (target) : body.code_size; - WriteSByte ((sbyte)(offset - (instruction.Offset + opcode.Size + 1))); - break; - } - case OperandType.InlineBrTarget: { - var target = (Instruction)operand; - var offset = target != null ? GetTargetOffset (target) : body.code_size; - WriteInt32 (offset - (instruction.Offset + opcode.Size + 4)); - break; - } - case OperandType.ShortInlineVar: - WriteByte ((byte)GetVariableIndex ((VariableDefinition)operand)); - break; - case OperandType.ShortInlineArg: - WriteByte ((byte)GetParameterIndex ((ParameterDefinition)operand)); - break; - case OperandType.InlineVar: - WriteInt16 ((short)GetVariableIndex ((VariableDefinition)operand)); - break; - case OperandType.InlineArg: - WriteInt16 ((short)GetParameterIndex ((ParameterDefinition)operand)); - break; - case OperandType.InlineSig: - WriteMetadataToken (GetStandAloneSignature ((CallSite)operand)); - break; - case OperandType.ShortInlineI: - if (opcode == OpCodes.Ldc_I4_S) - WriteSByte ((sbyte)operand); - else - WriteByte ((byte)operand); - break; - case OperandType.InlineI: - WriteInt32 ((int)operand); - break; - case OperandType.InlineI8: - WriteInt64 ((long)operand); - break; - case OperandType.ShortInlineR: - WriteSingle ((float)operand); - break; - case OperandType.InlineR: - WriteDouble ((double)operand); - break; - case OperandType.InlineString: - WriteMetadataToken ( - new MetadataToken ( - TokenType.String, - GetUserStringIndex ((string)operand))); - break; - case OperandType.InlineType: - case OperandType.InlineField: - case OperandType.InlineMethod: - case OperandType.InlineTok: - WriteMetadataToken (metadata.LookupToken ((IMetadataTokenProvider)operand)); - break; - default: - throw new ArgumentException (); - } - } - - int GetTargetOffset (Instruction instruction) - { - if (instruction == null) { - var last = body.instructions [body.instructions.size - 1]; - return last.offset + last.GetSize (); - } - - return instruction.offset; - } - - uint GetUserStringIndex (string @string) - { - if (@string == null) - return 0; - - return metadata.user_string_heap.GetStringIndex (@string); - } - - static int GetVariableIndex (VariableDefinition variable) - { - return variable.Index; - } - - int GetParameterIndex (ParameterDefinition parameter) - { - if (body.method.HasThis) { - if (parameter == body.this_parameter) - return 0; - - return parameter.Index + 1; - } - - return parameter.Index; - } - - bool RequiresFatHeader () - { - var body = this.body; - return body.CodeSize >= 64 - || body.InitLocals - || body.HasVariables - || body.HasExceptionHandlers - || body.MaxStackSize > 8; - } - - void ComputeHeader () - { - int offset = 0; - var instructions = body.instructions; - var items = instructions.items; - var count = instructions.size; - var stack_size = 0; - var max_stack = 0; - Dictionary stack_sizes = null; - - if (body.HasExceptionHandlers) - ComputeExceptionHandlerStackSize (ref stack_sizes); - - for (int i = 0; i < count; i++) { - var instruction = items [i]; - instruction.offset = offset; - offset += instruction.GetSize (); - - ComputeStackSize (instruction, ref stack_sizes, ref stack_size, ref max_stack); - } - - body.code_size = offset; - body.max_stack_size = max_stack; - } - - void ComputeExceptionHandlerStackSize (ref Dictionary stack_sizes) - { - var exception_handlers = body.ExceptionHandlers; - - for (int i = 0; i < exception_handlers.Count; i++) { - var exception_handler = exception_handlers [i]; - - switch (exception_handler.HandlerType) { - case ExceptionHandlerType.Catch: - AddExceptionStackSize (exception_handler.HandlerStart, ref stack_sizes); - break; - case ExceptionHandlerType.Filter: - AddExceptionStackSize (exception_handler.FilterStart, ref stack_sizes); - AddExceptionStackSize (exception_handler.HandlerStart, ref stack_sizes); - break; - } - } - } - - static void AddExceptionStackSize (Instruction handler_start, ref Dictionary stack_sizes) - { - if (handler_start == null) - return; - - if (stack_sizes == null) - stack_sizes = new Dictionary (); - - stack_sizes [handler_start] = 1; - } - - static void ComputeStackSize (Instruction instruction, ref Dictionary stack_sizes, ref int stack_size, ref int max_stack) - { - int computed_size; - if (stack_sizes != null && stack_sizes.TryGetValue (instruction, out computed_size)) - stack_size = computed_size; - - max_stack = System.Math.Max (max_stack, stack_size); - ComputeStackDelta (instruction, ref stack_size); - max_stack = System.Math.Max (max_stack, stack_size); - - CopyBranchStackSize (instruction, ref stack_sizes, stack_size); - ComputeStackSize (instruction, ref stack_size); - } - - static void CopyBranchStackSize (Instruction instruction, ref Dictionary stack_sizes, int stack_size) - { - if (stack_size == 0) - return; - - switch (instruction.opcode.OperandType) { - case OperandType.ShortInlineBrTarget: - case OperandType.InlineBrTarget: - CopyBranchStackSize (ref stack_sizes, (Instruction)instruction.operand, stack_size); - break; - case OperandType.InlineSwitch: - var targets = (Instruction [])instruction.operand; - for (int i = 0; i < targets.Length; i++) - CopyBranchStackSize (ref stack_sizes, targets [i], stack_size); - break; - } - } - - static void CopyBranchStackSize (ref Dictionary stack_sizes, Instruction target, int stack_size) - { - if (stack_sizes == null) - stack_sizes = new Dictionary (); - - int branch_stack_size = stack_size; - - int computed_size; - if (stack_sizes.TryGetValue (target, out computed_size)) - branch_stack_size = System.Math.Max (branch_stack_size, computed_size); - - stack_sizes [target] = branch_stack_size; - } - - static void ComputeStackSize (Instruction instruction, ref int stack_size) - { - switch (instruction.opcode.FlowControl) { - case FlowControl.Branch: - case FlowControl.Throw: - case FlowControl.Return: - stack_size = 0; - break; - } - } - - static void ComputeStackDelta (Instruction instruction, ref int stack_size) - { - switch (instruction.opcode.FlowControl) { - case FlowControl.Call: { - var method = (IMethodSignature)instruction.operand; - // pop 'this' argument - if (method.HasImplicitThis () && instruction.opcode.Code != Code.Newobj) - stack_size--; - // pop normal arguments - if (method.HasParameters) - stack_size -= method.Parameters.Count; - // pop function pointer - if (instruction.opcode.Code == Code.Calli) - stack_size--; - // push return value - if (method.ReturnType.etype != ElementType.Void || instruction.opcode.Code == Code.Newobj) - stack_size++; - break; - } - default: - ComputePopDelta (instruction.opcode.StackBehaviourPop, ref stack_size); - ComputePushDelta (instruction.opcode.StackBehaviourPush, ref stack_size); - break; - } - } - - static void ComputePopDelta (StackBehaviour pop_behavior, ref int stack_size) - { - switch (pop_behavior) { - case StackBehaviour.Popi: - case StackBehaviour.Popref: - case StackBehaviour.Pop1: - stack_size--; - break; - case StackBehaviour.Pop1_pop1: - case StackBehaviour.Popi_pop1: - case StackBehaviour.Popi_popi: - case StackBehaviour.Popi_popi8: - case StackBehaviour.Popi_popr4: - case StackBehaviour.Popi_popr8: - case StackBehaviour.Popref_pop1: - case StackBehaviour.Popref_popi: - stack_size -= 2; - break; - case StackBehaviour.Popi_popi_popi: - case StackBehaviour.Popref_popi_popi: - case StackBehaviour.Popref_popi_popi8: - case StackBehaviour.Popref_popi_popr4: - case StackBehaviour.Popref_popi_popr8: - case StackBehaviour.Popref_popi_popref: - stack_size -= 3; - break; - case StackBehaviour.PopAll: - stack_size = 0; - break; - } - } - - static void ComputePushDelta (StackBehaviour push_behaviour, ref int stack_size) - { - switch (push_behaviour) { - case StackBehaviour.Push1: - case StackBehaviour.Pushi: - case StackBehaviour.Pushi8: - case StackBehaviour.Pushr4: - case StackBehaviour.Pushr8: - case StackBehaviour.Pushref: - stack_size++; - break; - case StackBehaviour.Push1_push1: - stack_size += 2; - break; - } - } - - void WriteExceptionHandlers () - { - Align (4); - - var handlers = body.ExceptionHandlers; - - if (handlers.Count < 0x15 && !RequiresFatSection (handlers)) - WriteSmallSection (handlers); - else - WriteFatSection (handlers); - } - - static bool RequiresFatSection (Collection handlers) - { - for (int i = 0; i < handlers.Count; i++) { - var handler = handlers [i]; - - if (IsFatRange (handler.TryStart, handler.TryEnd)) - return true; - - if (IsFatRange (handler.HandlerStart, handler.HandlerEnd)) - return true; - - if (handler.HandlerType == ExceptionHandlerType.Filter - && IsFatRange (handler.FilterStart, handler.HandlerStart)) - return true; - } - - return false; - } - - static bool IsFatRange (Instruction start, Instruction end) - { - if (start == null) - throw new ArgumentException (); - - if (end == null) - return true; - - return end.Offset - start.Offset > 255 || start.Offset > 65535; - } - - void WriteSmallSection (Collection handlers) - { - const byte eh_table = 0x1; - - WriteByte (eh_table); - WriteByte ((byte)(handlers.Count * 12 + 4)); - WriteBytes (2); - - WriteExceptionHandlers ( - handlers, - i => WriteUInt16 ((ushort)i), - i => WriteByte ((byte)i)); - } - - void WriteFatSection (Collection handlers) - { - const byte eh_table = 0x1; - const byte fat_format = 0x40; - - WriteByte (eh_table | fat_format); - - int size = handlers.Count * 24 + 4; - WriteByte ((byte)(size & 0xff)); - WriteByte ((byte)((size >> 8) & 0xff)); - WriteByte ((byte)((size >> 16) & 0xff)); - - WriteExceptionHandlers (handlers, WriteInt32, WriteInt32); - } - - void WriteExceptionHandlers (Collection handlers, Action write_entry, Action write_length) - { - for (int i = 0; i < handlers.Count; i++) { - var handler = handlers [i]; - - write_entry ((int)handler.HandlerType); - - write_entry (handler.TryStart.Offset); - write_length (GetTargetOffset (handler.TryEnd) - handler.TryStart.Offset); - - write_entry (handler.HandlerStart.Offset); - write_length (GetTargetOffset (handler.HandlerEnd) - handler.HandlerStart.Offset); - - WriteExceptionHandlerSpecific (handler); - } - } - - void WriteExceptionHandlerSpecific (ExceptionHandler handler) - { - switch (handler.HandlerType) { - case ExceptionHandlerType.Catch: - WriteMetadataToken (metadata.LookupToken (handler.CatchType)); - break; - case ExceptionHandlerType.Filter: - WriteInt32 (handler.FilterStart.Offset); - break; - default: - WriteInt32 (0); - break; - } - } - - public MetadataToken GetStandAloneSignature (Collection variables) - { - var signature = metadata.GetLocalVariableBlobIndex (variables); - - return GetStandAloneSignatureToken (signature); - } - - public MetadataToken GetStandAloneSignature (CallSite call_site) - { - var signature = metadata.GetCallSiteBlobIndex (call_site); - var token = GetStandAloneSignatureToken (signature); - call_site.MetadataToken = token; - return token; - } - - MetadataToken GetStandAloneSignatureToken (uint signature) - { - MetadataToken token; - if (standalone_signatures.TryGetValue (signature, out token)) - return token; - - token = new MetadataToken (TokenType.Signature, metadata.AddStandAloneSignature (signature)); - standalone_signatures.Add (signature, token); - return token; - } - - RVA BeginMethod () - { - return (RVA)(code_base + position); - } - - void WriteMetadataToken (MetadataToken token) - { - WriteUInt32 (token.ToUInt32 ()); - } - - void Align (int align) - { - align--; - WriteBytes (((position + align) & ~align) - position); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeWriter.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeWriter.cs.meta deleted file mode 100644 index e4cccca..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/CodeWriter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 278f89c983a1bc6429c65a1d49dff091 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Document.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Document.cs deleted file mode 100644 index ce30188..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Document.cs +++ /dev/null @@ -1,123 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil.Cil { - - public enum DocumentType { - Other, - Text, - } - - public enum DocumentHashAlgorithm { - None, - MD5, - SHA1, - SHA256, - } - - public enum DocumentLanguage { - Other, - C, - Cpp, - CSharp, - Basic, - Java, - Cobol, - Pascal, - Cil, - JScript, - Smc, - MCpp, - FSharp, - } - - public enum DocumentLanguageVendor { - Other, - Microsoft, - } - - public sealed class Document : DebugInformation { - - string url; - - Guid type; - Guid hash_algorithm; - Guid language; - Guid language_vendor; - - byte [] hash; - byte [] embedded_source; - - public string Url { - get { return url; } - set { url = value; } - } - - public DocumentType Type { - get { return type.ToType (); } - set { type = value.ToGuid (); } - } - - public Guid TypeGuid { - get { return type; } - set { type = value; } - } - - public DocumentHashAlgorithm HashAlgorithm { - get { return hash_algorithm.ToHashAlgorithm (); } - set { hash_algorithm = value.ToGuid (); } - } - - public Guid HashAlgorithmGuid { - get { return hash_algorithm; } - set { hash_algorithm = value; } - } - - public DocumentLanguage Language { - get { return language.ToLanguage (); } - set { language = value.ToGuid (); } - } - - public Guid LanguageGuid { - get { return language; } - set { language = value; } - } - - public DocumentLanguageVendor LanguageVendor { - get { return language_vendor.ToVendor (); } - set { language_vendor = value.ToGuid (); } - } - - public Guid LanguageVendorGuid { - get { return language_vendor; } - set { language_vendor = value; } - } - - public byte [] Hash { - get { return hash; } - set { hash = value; } - } - - public byte [] EmbeddedSource { - get { return embedded_source; } - set { embedded_source = value; } - } - - public Document (string url) - { - this.url = url; - this.hash = Empty.Array; - this.embedded_source = Empty.Array; - this.token = new MetadataToken (TokenType.Document); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Document.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Document.cs.meta deleted file mode 100644 index 2a3915d..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Document.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 86b3083301304a341b6059ea8c29be7a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ExceptionHandler.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ExceptionHandler.cs deleted file mode 100644 index c017553..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ExceptionHandler.cs +++ /dev/null @@ -1,71 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil.Cil { - - public enum ExceptionHandlerType { - Catch = 0, - Filter = 1, - Finally = 2, - Fault = 4, - } - - public sealed class ExceptionHandler { - - Instruction try_start; - Instruction try_end; - Instruction filter_start; - Instruction handler_start; - Instruction handler_end; - - TypeReference catch_type; - ExceptionHandlerType handler_type; - - public Instruction TryStart { - get { return try_start; } - set { try_start = value; } - } - - public Instruction TryEnd { - get { return try_end; } - set { try_end = value; } - } - - public Instruction FilterStart { - get { return filter_start; } - set { filter_start = value; } - } - - public Instruction HandlerStart { - get { return handler_start; } - set { handler_start = value; } - } - - public Instruction HandlerEnd { - get { return handler_end; } - set { handler_end = value; } - } - - public TypeReference CatchType { - get { return catch_type; } - set { catch_type = value; } - } - - public ExceptionHandlerType HandlerType { - get { return handler_type; } - set { handler_type = value; } - } - - public ExceptionHandler (ExceptionHandlerType handlerType) - { - this.handler_type = handlerType; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ExceptionHandler.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ExceptionHandler.cs.meta deleted file mode 100644 index f26784f..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ExceptionHandler.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: eb17bcae1a67ec344b65d6ed78ffb704 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ILProcessor.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ILProcessor.cs deleted file mode 100644 index 48944a2..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ILProcessor.cs +++ /dev/null @@ -1,291 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; - -namespace MonoFN.Cecil.Cil { - - public sealed class ILProcessor { - - readonly MethodBody body; - readonly Collection instructions; - - public MethodBody Body { - get { return body; } - } - - internal ILProcessor (MethodBody body) - { - this.body = body; - this.instructions = body.Instructions; - } - - public Instruction Create (OpCode opcode) - { - return Instruction.Create (opcode); - } - - public Instruction Create (OpCode opcode, TypeReference type) - { - return Instruction.Create (opcode, type); - } - - public Instruction Create (OpCode opcode, CallSite site) - { - return Instruction.Create (opcode, site); - } - - public Instruction Create (OpCode opcode, MethodReference method) - { - return Instruction.Create (opcode, method); - } - - public Instruction Create (OpCode opcode, FieldReference field) - { - return Instruction.Create (opcode, field); - } - - public Instruction Create (OpCode opcode, string value) - { - return Instruction.Create (opcode, value); - } - - public Instruction Create (OpCode opcode, sbyte value) - { - return Instruction.Create (opcode, value); - } - - public Instruction Create (OpCode opcode, byte value) - { - if (opcode.OperandType == OperandType.ShortInlineVar) - return Instruction.Create (opcode, body.Variables [value]); - - if (opcode.OperandType == OperandType.ShortInlineArg) - return Instruction.Create (opcode, body.GetParameter (value)); - - return Instruction.Create (opcode, value); - } - - public Instruction Create (OpCode opcode, int value) - { - if (opcode.OperandType == OperandType.InlineVar) - return Instruction.Create (opcode, body.Variables [value]); - - if (opcode.OperandType == OperandType.InlineArg) - return Instruction.Create (opcode, body.GetParameter (value)); - - return Instruction.Create (opcode, value); - } - - public Instruction Create (OpCode opcode, long value) - { - return Instruction.Create (opcode, value); - } - - public Instruction Create (OpCode opcode, float value) - { - return Instruction.Create (opcode, value); - } - - public Instruction Create (OpCode opcode, double value) - { - return Instruction.Create (opcode, value); - } - - public Instruction Create (OpCode opcode, Instruction target) - { - return Instruction.Create (opcode, target); - } - - public Instruction Create (OpCode opcode, Instruction [] targets) - { - return Instruction.Create (opcode, targets); - } - - public Instruction Create (OpCode opcode, VariableDefinition variable) - { - return Instruction.Create (opcode, variable); - } - - public Instruction Create (OpCode opcode, ParameterDefinition parameter) - { - return Instruction.Create (opcode, parameter); - } - - public void Emit (OpCode opcode) - { - Append (Create (opcode)); - } - - public void Emit (OpCode opcode, TypeReference type) - { - Append (Create (opcode, type)); - } - - public void Emit (OpCode opcode, MethodReference method) - { - Append (Create (opcode, method)); - } - - public void Emit (OpCode opcode, CallSite site) - { - Append (Create (opcode, site)); - } - - public void Emit (OpCode opcode, FieldReference field) - { - Append (Create (opcode, field)); - } - - public void Emit (OpCode opcode, string value) - { - Append (Create (opcode, value)); - } - - public void Emit (OpCode opcode, byte value) - { - Append (Create (opcode, value)); - } - - public void Emit (OpCode opcode, sbyte value) - { - Append (Create (opcode, value)); - } - - public void Emit (OpCode opcode, int value) - { - Append (Create (opcode, value)); - } - - public void Emit (OpCode opcode, long value) - { - Append (Create (opcode, value)); - } - - public void Emit (OpCode opcode, float value) - { - Append (Create (opcode, value)); - } - - public void Emit (OpCode opcode, double value) - { - Append (Create (opcode, value)); - } - - public void Emit (OpCode opcode, Instruction target) - { - Append (Create (opcode, target)); - } - - public void Emit (OpCode opcode, Instruction [] targets) - { - Append (Create (opcode, targets)); - } - - public void Emit (OpCode opcode, VariableDefinition variable) - { - Append (Create (opcode, variable)); - } - - public void Emit (OpCode opcode, ParameterDefinition parameter) - { - Append (Create (opcode, parameter)); - } - - public void InsertBefore (Instruction target, Instruction instruction) - { - if (target == null) - throw new ArgumentNullException ("target"); - if (instruction == null) - throw new ArgumentNullException ("instruction"); - - var index = instructions.IndexOf (target); - if (index == -1) - throw new ArgumentOutOfRangeException ("target"); - - instructions.Insert (index, instruction); - } - - public void InsertAfter (Instruction target, Instruction instruction) - { - if (target == null) - throw new ArgumentNullException ("target"); - if (instruction == null) - throw new ArgumentNullException ("instruction"); - - var index = instructions.IndexOf (target); - if (index == -1) - throw new ArgumentOutOfRangeException ("target"); - - instructions.Insert (index + 1, instruction); - } - - public void InsertAfter (int index, Instruction instruction) - { - if (index < 0 || index >= instructions.Count) - throw new ArgumentOutOfRangeException ("index"); - if (instruction == null) - throw new ArgumentNullException ("instruction"); - - instructions.Insert (index + 1, instruction); - } - - public void Append (Instruction instruction) - { - if (instruction == null) - throw new ArgumentNullException ("instruction"); - - instructions.Add (instruction); - } - - public void Replace (Instruction target, Instruction instruction) - { - if (target == null) - throw new ArgumentNullException ("target"); - if (instruction == null) - throw new ArgumentNullException ("instruction"); - - InsertAfter (target, instruction); - Remove (target); - } - - public void Replace (int index, Instruction instruction) - { - if (instruction == null) - throw new ArgumentNullException ("instruction"); - - InsertAfter (index, instruction); - RemoveAt (index); - } - - public void Remove (Instruction instruction) - { - if (instruction == null) - throw new ArgumentNullException ("instruction"); - - if (!instructions.Remove (instruction)) - throw new ArgumentOutOfRangeException ("instruction"); - } - - public void RemoveAt (int index) - { - if (index < 0 || index >= instructions.Count) - throw new ArgumentOutOfRangeException ("index"); - - instructions.RemoveAt (index); - } - - public void Clear () - { - instructions.Clear (); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ILProcessor.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ILProcessor.cs.meta deleted file mode 100644 index 5964570..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/ILProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 26902ea42064c624d82727d9ef9a8f5e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Instruction.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Instruction.cs deleted file mode 100644 index 93afafe..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Instruction.cs +++ /dev/null @@ -1,296 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; -using System.Text; - -namespace MonoFN.Cecil.Cil { - - public sealed class Instruction { - - internal int offset; - internal OpCode opcode; - internal object operand; - - internal Instruction previous; - internal Instruction next; - - public int Offset { - get { return offset; } - set { offset = value; } - } - - public OpCode OpCode { - get { return opcode; } - set { opcode = value; } - } - - public object Operand { - get { return operand; } - set { operand = value; } - } - - public Instruction Previous { - get { return previous; } - set { previous = value; } - } - - public Instruction Next { - get { return next; } - set { next = value; } - } - - internal Instruction (int offset, OpCode opCode) - { - this.offset = offset; - this.opcode = opCode; - } - - internal Instruction (OpCode opcode, object operand) - { - this.opcode = opcode; - this.operand = operand; - } - - public int GetSize () - { - int size = opcode.Size; - - switch (opcode.OperandType) { - case OperandType.InlineSwitch: - return size + (1 + ((Instruction [])operand).Length) * 4; - case OperandType.InlineI8: - case OperandType.InlineR: - return size + 8; - case OperandType.InlineBrTarget: - case OperandType.InlineField: - case OperandType.InlineI: - case OperandType.InlineMethod: - case OperandType.InlineString: - case OperandType.InlineTok: - case OperandType.InlineType: - case OperandType.ShortInlineR: - case OperandType.InlineSig: - return size + 4; - case OperandType.InlineArg: - case OperandType.InlineVar: - return size + 2; - case OperandType.ShortInlineBrTarget: - case OperandType.ShortInlineI: - case OperandType.ShortInlineArg: - case OperandType.ShortInlineVar: - return size + 1; - default: - return size; - } - } - - public override string ToString () - { - var instruction = new StringBuilder (); - - AppendLabel (instruction, this); - instruction.Append (':'); - instruction.Append (' '); - instruction.Append (opcode.Name); - - if (operand == null) - return instruction.ToString (); - - instruction.Append (' '); - - switch (opcode.OperandType) { - case OperandType.ShortInlineBrTarget: - case OperandType.InlineBrTarget: - AppendLabel (instruction, (Instruction)operand); - break; - case OperandType.InlineSwitch: - var labels = (Instruction [])operand; - for (int i = 0; i < labels.Length; i++) { - if (i > 0) - instruction.Append (','); - - AppendLabel (instruction, labels [i]); - } - break; - case OperandType.InlineString: - instruction.Append ('\"'); - instruction.Append (operand); - instruction.Append ('\"'); - break; - default: - instruction.Append (operand); - break; - } - - return instruction.ToString (); - } - - static void AppendLabel (StringBuilder builder, Instruction instruction) - { - builder.Append ("IL_"); - builder.Append (instruction.offset.ToString ("x4")); - } - - public static Instruction Create (OpCode opcode) - { - if (opcode.OperandType != OperandType.InlineNone) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, null); - } - - public static Instruction Create (OpCode opcode, TypeReference type) - { - if (type == null) - throw new ArgumentNullException ("type"); - if (opcode.OperandType != OperandType.InlineType && - opcode.OperandType != OperandType.InlineTok) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, type); - } - - public static Instruction Create (OpCode opcode, CallSite site) - { - if (site == null) - throw new ArgumentNullException ("site"); - if (opcode.Code != Code.Calli) - throw new ArgumentException ("code"); - - return new Instruction (opcode, site); - } - - public static Instruction Create (OpCode opcode, MethodReference method) - { - if (method == null) - throw new ArgumentNullException ("method"); - if (opcode.OperandType != OperandType.InlineMethod && - opcode.OperandType != OperandType.InlineTok) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, method); - } - - public static Instruction Create (OpCode opcode, FieldReference field) - { - if (field == null) - throw new ArgumentNullException ("field"); - if (opcode.OperandType != OperandType.InlineField && - opcode.OperandType != OperandType.InlineTok) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, field); - } - - public static Instruction Create (OpCode opcode, string value) - { - if (value == null) - throw new ArgumentNullException ("value"); - if (opcode.OperandType != OperandType.InlineString) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, value); - } - - public static Instruction Create (OpCode opcode, sbyte value) - { - if (opcode.OperandType != OperandType.ShortInlineI && - opcode != OpCodes.Ldc_I4_S) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, value); - } - - public static Instruction Create (OpCode opcode, byte value) - { - if (opcode.OperandType != OperandType.ShortInlineI || - opcode == OpCodes.Ldc_I4_S) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, value); - } - - public static Instruction Create (OpCode opcode, int value) - { - if (opcode.OperandType != OperandType.InlineI) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, value); - } - - public static Instruction Create (OpCode opcode, long value) - { - if (opcode.OperandType != OperandType.InlineI8) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, value); - } - - public static Instruction Create (OpCode opcode, float value) - { - if (opcode.OperandType != OperandType.ShortInlineR) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, value); - } - - public static Instruction Create (OpCode opcode, double value) - { - if (opcode.OperandType != OperandType.InlineR) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, value); - } - - public static Instruction Create (OpCode opcode, Instruction target) - { - if (target == null) - throw new ArgumentNullException ("target"); - if (opcode.OperandType != OperandType.InlineBrTarget && - opcode.OperandType != OperandType.ShortInlineBrTarget) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, target); - } - - public static Instruction Create (OpCode opcode, Instruction [] targets) - { - if (targets == null) - throw new ArgumentNullException ("targets"); - if (opcode.OperandType != OperandType.InlineSwitch) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, targets); - } - - public static Instruction Create (OpCode opcode, VariableDefinition variable) - { - if (variable == null) - throw new ArgumentNullException ("variable"); - if (opcode.OperandType != OperandType.ShortInlineVar && - opcode.OperandType != OperandType.InlineVar) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, variable); - } - - public static Instruction Create (OpCode opcode, ParameterDefinition parameter) - { - if (parameter == null) - throw new ArgumentNullException ("parameter"); - if (opcode.OperandType != OperandType.ShortInlineArg && - opcode.OperandType != OperandType.InlineArg) - throw new ArgumentException ("opcode"); - - return new Instruction (opcode, parameter); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Instruction.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Instruction.cs.meta deleted file mode 100644 index fc5ea61..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Instruction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2d1536adbd2ca174abbd624473e722c3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/MethodBody.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/MethodBody.cs deleted file mode 100644 index 9a49f12..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/MethodBody.cs +++ /dev/null @@ -1,426 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; -using System.Threading; - -namespace MonoFN.Cecil.Cil { - - public sealed class MethodBody { - - readonly internal MethodDefinition method; - - internal ParameterDefinition this_parameter; - internal int max_stack_size; - internal int code_size; - internal bool init_locals; - internal MetadataToken local_var_token; - - internal Collection instructions; - internal Collection exceptions; - internal Collection variables; - - public MethodDefinition Method { - get { return method; } - } - - public int MaxStackSize { - get { return max_stack_size; } - set { max_stack_size = value; } - } - - public int CodeSize { - get { return code_size; } - } - - public bool InitLocals { - get { return init_locals; } - set { init_locals = value; } - } - - public MetadataToken LocalVarToken { - get { return local_var_token; } - set { local_var_token = value; } - } - - public Collection Instructions { - get { - if (instructions == null) - Interlocked.CompareExchange (ref instructions, new InstructionCollection (method), null); - - return instructions; - } - } - - public bool HasExceptionHandlers { - get { return !exceptions.IsNullOrEmpty (); } - } - - public Collection ExceptionHandlers { - get { - if (exceptions == null) - Interlocked.CompareExchange (ref exceptions, new Collection (), null); - - return exceptions; - } - } - - public bool HasVariables { - get { return !variables.IsNullOrEmpty (); } - } - - public Collection Variables { - get { - if (variables == null) - Interlocked.CompareExchange (ref variables, new VariableDefinitionCollection (this.method), null); - - return variables; - } - } - - public ParameterDefinition ThisParameter { - get { - if (method == null || method.DeclaringType == null) - throw new NotSupportedException (); - - if (!method.HasThis) - return null; - - if (this_parameter == null) - Interlocked.CompareExchange (ref this_parameter, CreateThisParameter (method), null); - - return this_parameter; - } - } - - static ParameterDefinition CreateThisParameter (MethodDefinition method) - { - var parameter_type = method.DeclaringType as TypeReference; - - if (parameter_type.HasGenericParameters) { - var instance = new GenericInstanceType (parameter_type, parameter_type.GenericParameters.Count); - for (int i = 0; i < parameter_type.GenericParameters.Count; i++) - instance.GenericArguments.Add (parameter_type.GenericParameters [i]); - - parameter_type = instance; - - } - - if (parameter_type.IsValueType || parameter_type.IsPrimitive) - parameter_type = new ByReferenceType (parameter_type); - - return new ParameterDefinition (parameter_type, method); - } - - public MethodBody (MethodDefinition method) - { - this.method = method; - } - - public ILProcessor GetILProcessor () - { - return new ILProcessor (this); - } - } - - sealed class VariableDefinitionCollection : Collection { - - readonly MethodDefinition method; - - internal VariableDefinitionCollection (MethodDefinition method) - { - this.method = method; - } - - internal VariableDefinitionCollection (MethodDefinition method, int capacity) - : base (capacity) - { - this.method = method; - } - - protected override void OnAdd (VariableDefinition item, int index) - { - item.index = index; - } - - protected override void OnInsert (VariableDefinition item, int index) - { - item.index = index; - UpdateVariableIndices (index, 1); - } - - protected override void OnSet (VariableDefinition item, int index) - { - item.index = index; - } - - protected override void OnRemove (VariableDefinition item, int index) - { - UpdateVariableIndices (index + 1, -1, item); - item.index = -1; - } - - void UpdateVariableIndices (int startIndex, int offset, VariableDefinition variableToRemove = null) - { - for (int i = startIndex; i < size; i++) - items [i].index = i + offset; - - var debug_info = method == null ? null : method.debug_info; - if (debug_info == null || debug_info.Scope == null) - return; - - foreach (var scope in debug_info.GetScopes ()) { - if (!scope.HasVariables) - continue; - - var variables = scope.Variables; - int variableDebugInfoIndexToRemove = -1; - for (int i = 0; i < variables.Count; i++) { - var variable = variables [i]; - - // If a variable is being removed detect if it has debug info counterpart, if so remove that as well. - // Note that the debug info can be either resolved (has direct reference to the VariableDefinition) - // or unresolved (has only the number index of the variable) - this needs to handle both cases. - if (variableToRemove != null && - ((variable.index.IsResolved && variable.index.ResolvedVariable == variableToRemove) || - (!variable.index.IsResolved && variable.Index == variableToRemove.Index))) { - variableDebugInfoIndexToRemove = i; - continue; - } - - // For unresolved debug info updates indeces to keep them pointing to the same variable. - if (!variable.index.IsResolved && variable.Index >= startIndex) { - variable.index = new VariableIndex (variable.Index + offset); - } - } - - if (variableDebugInfoIndexToRemove >= 0) - variables.RemoveAt (variableDebugInfoIndexToRemove); - } - } - } - - class InstructionCollection : Collection { - - readonly MethodDefinition method; - - internal InstructionCollection (MethodDefinition method) - { - this.method = method; - } - - internal InstructionCollection (MethodDefinition method, int capacity) - : base (capacity) - { - this.method = method; - } - - protected override void OnAdd (Instruction item, int index) - { - if (index == 0) - return; - - var previous = items [index - 1]; - previous.next = item; - item.previous = previous; - } - - protected override void OnInsert (Instruction item, int index) - { - int startOffset = 0; - if (size != 0) { - var current = items [index]; - if (current == null) { - var last = items [index - 1]; - last.next = item; - item.previous = last; - return; - } - - startOffset = current.Offset; - - var previous = current.previous; - if (previous != null) { - previous.next = item; - item.previous = previous; - } - - current.previous = item; - item.next = current; - } - - UpdateLocalScopes (null, null); - } - - protected override void OnSet (Instruction item, int index) - { - var current = items [index]; - - item.previous = current.previous; - item.next = current.next; - - current.previous = null; - current.next = null; - - UpdateLocalScopes (item, current); - } - - protected override void OnRemove (Instruction item, int index) - { - var previous = item.previous; - if (previous != null) - previous.next = item.next; - - var next = item.next; - if (next != null) - next.previous = item.previous; - - RemoveSequencePoint (item); - UpdateLocalScopes (item, next ?? previous); - - item.previous = null; - item.next = null; - } - - void RemoveSequencePoint (Instruction instruction) - { - var debug_info = method.debug_info; - if (debug_info == null || !debug_info.HasSequencePoints) - return; - - var sequence_points = debug_info.sequence_points; - for (int i = 0; i < sequence_points.Count; i++) { - if (sequence_points [i].Offset == instruction.offset) { - sequence_points.RemoveAt (i); - return; - } - } - } - - void UpdateLocalScopes (Instruction removedInstruction, Instruction existingInstruction) - { - var debug_info = method.debug_info; - if (debug_info == null) - return; - - // Local scopes store start/end pair of "instruction offsets". Instruction offset can be either resolved, in which case it - // has a reference to Instruction, or unresolved in which case it stores numerical offset (instruction offset in the body). - // Typically local scopes loaded from PE/PDB files will be resolved, but it's not a requirement. - // Each instruction has its own offset, which is populated on load, but never updated (this would be pretty expensive to do). - // Instructions created during the editting will typically have offset 0 (so incorrect). - // Local scopes created during editing will also likely be resolved (so no numerical offsets). - // So while local scopes which are unresolved are relatively rare if they appear, manipulating them based - // on the offsets allone is pretty hard (since we can't rely on correct offsets of instructions). - // On the other hand resolved local scopes are easy to maintain, since they point to instructions and thus inserting - // instructions is basically a no-op and removing instructions is as easy as changing the pointer. - // For this reason the algorithm here is: - // - First make sure that all instruction offsets are resolved - if not - resolve them - // - First time this will be relatively expensinve as it will walk the entire method body to convert offsets to instruction pointers - // Almost all local scopes are stored in the "right" order (sequentially per start offsets), so the code uses a simple one-item - // cache instruction<->offset to avoid walking instructions multiple times (that would only happen for scopes which are out of order). - // - Subsequent calls should be cheap as it will only walk all local scopes without doing anything - // - If there was an edit on local scope which makes some of them unresolved, the cost is proportional - // - Then update as necessary by manipulaitng instruction references alone - - InstructionOffsetCache cache = new InstructionOffsetCache () { - Offset = 0, - Index = 0, - Instruction = items [0] - }; - - UpdateLocalScope (debug_info.Scope, removedInstruction, existingInstruction, ref cache); - } - - void UpdateLocalScope (ScopeDebugInformation scope, Instruction removedInstruction, Instruction existingInstruction, ref InstructionOffsetCache cache) - { - if (scope == null) - return; - - if (!scope.Start.IsResolved) - scope.Start = ResolveInstructionOffset (scope.Start, ref cache); - - if (!scope.Start.IsEndOfMethod && scope.Start.ResolvedInstruction == removedInstruction) - scope.Start = new InstructionOffset (existingInstruction); - - if (scope.HasScopes) { - foreach (var subScope in scope.Scopes) - UpdateLocalScope (subScope, removedInstruction, existingInstruction, ref cache); - } - - if (!scope.End.IsResolved) - scope.End = ResolveInstructionOffset (scope.End, ref cache); - - if (!scope.End.IsEndOfMethod && scope.End.ResolvedInstruction == removedInstruction) - scope.End = new InstructionOffset (existingInstruction); - } - - struct InstructionOffsetCache { - public int Offset; - public int Index; - public Instruction Instruction; - } - - InstructionOffset ResolveInstructionOffset (InstructionOffset inputOffset, ref InstructionOffsetCache cache) - { - if (inputOffset.IsResolved) - return inputOffset; - - int offset = inputOffset.Offset; - - if (cache.Offset == offset) - return new InstructionOffset (cache.Instruction); - - if (cache.Offset > offset) { - // This should be rare - we're resolving offset pointing to a place before the current cache position - // resolve by walking the instructions from start and don't cache the result. - int size = 0; - for (int i = 0; i < items.Length; i++) { - if (size == offset) - return new InstructionOffset (items [i]); - - if (size > offset) - return new InstructionOffset (items [i - 1]); - - size += items [i].GetSize (); - } - - // Offset is larger than the size of the body - so it points after the end - return new InstructionOffset (); - } else { - // The offset points after the current cache position - so continue counting and update the cache - int size = cache.Offset; - for (int i = cache.Index; i < items.Length; i++) { - cache.Index = i; - cache.Offset = size; - - var item = items [i]; - - // Allow for trailing null values in the case of - // instructions.Size < instructions.Capacity - if (item == null) - break; - - cache.Instruction = item; - - if (cache.Offset == offset) - return new InstructionOffset (cache.Instruction); - - if (cache.Offset > offset) - return new InstructionOffset (items [i - 1]); - - size += item.GetSize (); - } - - return new InstructionOffset (); - } - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/MethodBody.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/MethodBody.cs.meta deleted file mode 100644 index 6bfd730..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/MethodBody.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4be4045de2c6a0e428e5910f4e76cfac -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCode.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCode.cs deleted file mode 100644 index 6db5b62..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCode.cs +++ /dev/null @@ -1,439 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil.Cil { - - public enum FlowControl { - Branch, - Break, - Call, - Cond_Branch, - Meta, - Next, - Phi, - Return, - Throw, - } - - public enum OpCodeType { - Annotation, - Macro, - Nternal, - Objmodel, - Prefix, - Primitive, - } - - public enum OperandType { - InlineBrTarget, - InlineField, - InlineI, - InlineI8, - InlineMethod, - InlineNone, - InlinePhi, - InlineR, - InlineSig, - InlineString, - InlineSwitch, - InlineTok, - InlineType, - InlineVar, - InlineArg, - ShortInlineBrTarget, - ShortInlineI, - ShortInlineR, - ShortInlineVar, - ShortInlineArg, - } - - public enum StackBehaviour { - Pop0, - Pop1, - Pop1_pop1, - Popi, - Popi_pop1, - Popi_popi, - Popi_popi8, - Popi_popi_popi, - Popi_popr4, - Popi_popr8, - Popref, - Popref_pop1, - Popref_popi, - Popref_popi_popi, - Popref_popi_popi8, - Popref_popi_popr4, - Popref_popi_popr8, - Popref_popi_popref, - PopAll, - Push0, - Push1, - Push1_push1, - Pushi, - Pushi8, - Pushr4, - Pushr8, - Pushref, - Varpop, - Varpush, - } - - public struct OpCode : IEquatable { - - readonly byte op1; - readonly byte op2; - readonly byte code; - readonly byte flow_control; - readonly byte opcode_type; - readonly byte operand_type; - readonly byte stack_behavior_pop; - readonly byte stack_behavior_push; - - public string Name { - get { return OpCodeNames.names [(int)Code]; } - } - - public int Size { - get { return op1 == 0xff ? 1 : 2; } - } - - public byte Op1 { - get { return op1; } - } - - public byte Op2 { - get { return op2; } - } - - public short Value { - get { return op1 == 0xff ? op2 : (short)((op1 << 8) | op2); } - } - - public Code Code { - get { return (Code)code; } - } - - public FlowControl FlowControl { - get { return (FlowControl)flow_control; } - } - - public OpCodeType OpCodeType { - get { return (OpCodeType)opcode_type; } - } - - public OperandType OperandType { - get { return (OperandType)operand_type; } - } - - public StackBehaviour StackBehaviourPop { - get { return (StackBehaviour)stack_behavior_pop; } - } - - public StackBehaviour StackBehaviourPush { - get { return (StackBehaviour)stack_behavior_push; } - } - - internal OpCode (int x, int y) - { - this.op1 = (byte)((x >> 0) & 0xff); - this.op2 = (byte)((x >> 8) & 0xff); - this.code = (byte)((x >> 16) & 0xff); - this.flow_control = (byte)((x >> 24) & 0xff); - - this.opcode_type = (byte)((y >> 0) & 0xff); - this.operand_type = (byte)((y >> 8) & 0xff); - this.stack_behavior_pop = (byte)((y >> 16) & 0xff); - this.stack_behavior_push = (byte)((y >> 24) & 0xff); - - if (op1 == 0xff) - OpCodes.OneByteOpCode [op2] = this; - else - OpCodes.TwoBytesOpCode [op2] = this; - } - - public override int GetHashCode () - { - return Value; - } - - public override bool Equals (object obj) - { - if (!(obj is OpCode)) - return false; - - var opcode = (OpCode)obj; - return op1 == opcode.op1 && op2 == opcode.op2; - } - - public bool Equals (OpCode opcode) - { - return op1 == opcode.op1 && op2 == opcode.op2; - } - - public static bool operator == (OpCode one, OpCode other) - { - return one.op1 == other.op1 && one.op2 == other.op2; - } - - public static bool operator != (OpCode one, OpCode other) - { - return one.op1 != other.op1 || one.op2 != other.op2; - } - - public override string ToString () - { - return Name; - } - } - - static class OpCodeNames { - - internal static readonly string [] names; - - static OpCodeNames () - { - var table = new byte [] { - 3, 110, 111, 112, - 5, 98, 114, 101, 97, 107, - 7, 108, 100, 97, 114, 103, 46, 48, - 7, 108, 100, 97, 114, 103, 46, 49, - 7, 108, 100, 97, 114, 103, 46, 50, - 7, 108, 100, 97, 114, 103, 46, 51, - 7, 108, 100, 108, 111, 99, 46, 48, - 7, 108, 100, 108, 111, 99, 46, 49, - 7, 108, 100, 108, 111, 99, 46, 50, - 7, 108, 100, 108, 111, 99, 46, 51, - 7, 115, 116, 108, 111, 99, 46, 48, - 7, 115, 116, 108, 111, 99, 46, 49, - 7, 115, 116, 108, 111, 99, 46, 50, - 7, 115, 116, 108, 111, 99, 46, 51, - 7, 108, 100, 97, 114, 103, 46, 115, - 8, 108, 100, 97, 114, 103, 97, 46, 115, - 7, 115, 116, 97, 114, 103, 46, 115, - 7, 108, 100, 108, 111, 99, 46, 115, - 8, 108, 100, 108, 111, 99, 97, 46, 115, - 7, 115, 116, 108, 111, 99, 46, 115, - 6, 108, 100, 110, 117, 108, 108, - 9, 108, 100, 99, 46, 105, 52, 46, 109, 49, - 8, 108, 100, 99, 46, 105, 52, 46, 48, - 8, 108, 100, 99, 46, 105, 52, 46, 49, - 8, 108, 100, 99, 46, 105, 52, 46, 50, - 8, 108, 100, 99, 46, 105, 52, 46, 51, - 8, 108, 100, 99, 46, 105, 52, 46, 52, - 8, 108, 100, 99, 46, 105, 52, 46, 53, - 8, 108, 100, 99, 46, 105, 52, 46, 54, - 8, 108, 100, 99, 46, 105, 52, 46, 55, - 8, 108, 100, 99, 46, 105, 52, 46, 56, - 8, 108, 100, 99, 46, 105, 52, 46, 115, - 6, 108, 100, 99, 46, 105, 52, - 6, 108, 100, 99, 46, 105, 56, - 6, 108, 100, 99, 46, 114, 52, - 6, 108, 100, 99, 46, 114, 56, - 3, 100, 117, 112, - 3, 112, 111, 112, - 3, 106, 109, 112, - 4, 99, 97, 108, 108, - 5, 99, 97, 108, 108, 105, - 3, 114, 101, 116, - 4, 98, 114, 46, 115, - 9, 98, 114, 102, 97, 108, 115, 101, 46, 115, - 8, 98, 114, 116, 114, 117, 101, 46, 115, - 5, 98, 101, 113, 46, 115, - 5, 98, 103, 101, 46, 115, - 5, 98, 103, 116, 46, 115, - 5, 98, 108, 101, 46, 115, - 5, 98, 108, 116, 46, 115, - 8, 98, 110, 101, 46, 117, 110, 46, 115, - 8, 98, 103, 101, 46, 117, 110, 46, 115, - 8, 98, 103, 116, 46, 117, 110, 46, 115, - 8, 98, 108, 101, 46, 117, 110, 46, 115, - 8, 98, 108, 116, 46, 117, 110, 46, 115, - 2, 98, 114, - 7, 98, 114, 102, 97, 108, 115, 101, - 6, 98, 114, 116, 114, 117, 101, - 3, 98, 101, 113, - 3, 98, 103, 101, - 3, 98, 103, 116, - 3, 98, 108, 101, - 3, 98, 108, 116, - 6, 98, 110, 101, 46, 117, 110, - 6, 98, 103, 101, 46, 117, 110, - 6, 98, 103, 116, 46, 117, 110, - 6, 98, 108, 101, 46, 117, 110, - 6, 98, 108, 116, 46, 117, 110, - 6, 115, 119, 105, 116, 99, 104, - 8, 108, 100, 105, 110, 100, 46, 105, 49, - 8, 108, 100, 105, 110, 100, 46, 117, 49, - 8, 108, 100, 105, 110, 100, 46, 105, 50, - 8, 108, 100, 105, 110, 100, 46, 117, 50, - 8, 108, 100, 105, 110, 100, 46, 105, 52, - 8, 108, 100, 105, 110, 100, 46, 117, 52, - 8, 108, 100, 105, 110, 100, 46, 105, 56, - 7, 108, 100, 105, 110, 100, 46, 105, - 8, 108, 100, 105, 110, 100, 46, 114, 52, - 8, 108, 100, 105, 110, 100, 46, 114, 56, - 9, 108, 100, 105, 110, 100, 46, 114, 101, 102, - 9, 115, 116, 105, 110, 100, 46, 114, 101, 102, - 8, 115, 116, 105, 110, 100, 46, 105, 49, - 8, 115, 116, 105, 110, 100, 46, 105, 50, - 8, 115, 116, 105, 110, 100, 46, 105, 52, - 8, 115, 116, 105, 110, 100, 46, 105, 56, - 8, 115, 116, 105, 110, 100, 46, 114, 52, - 8, 115, 116, 105, 110, 100, 46, 114, 56, - 3, 97, 100, 100, - 3, 115, 117, 98, - 3, 109, 117, 108, - 3, 100, 105, 118, - 6, 100, 105, 118, 46, 117, 110, - 3, 114, 101, 109, - 6, 114, 101, 109, 46, 117, 110, - 3, 97, 110, 100, - 2, 111, 114, - 3, 120, 111, 114, - 3, 115, 104, 108, - 3, 115, 104, 114, - 6, 115, 104, 114, 46, 117, 110, - 3, 110, 101, 103, - 3, 110, 111, 116, - 7, 99, 111, 110, 118, 46, 105, 49, - 7, 99, 111, 110, 118, 46, 105, 50, - 7, 99, 111, 110, 118, 46, 105, 52, - 7, 99, 111, 110, 118, 46, 105, 56, - 7, 99, 111, 110, 118, 46, 114, 52, - 7, 99, 111, 110, 118, 46, 114, 56, - 7, 99, 111, 110, 118, 46, 117, 52, - 7, 99, 111, 110, 118, 46, 117, 56, - 8, 99, 97, 108, 108, 118, 105, 114, 116, - 5, 99, 112, 111, 98, 106, - 5, 108, 100, 111, 98, 106, - 5, 108, 100, 115, 116, 114, - 6, 110, 101, 119, 111, 98, 106, - 9, 99, 97, 115, 116, 99, 108, 97, 115, 115, - 6, 105, 115, 105, 110, 115, 116, - 9, 99, 111, 110, 118, 46, 114, 46, 117, 110, - 5, 117, 110, 98, 111, 120, - 5, 116, 104, 114, 111, 119, - 5, 108, 100, 102, 108, 100, - 6, 108, 100, 102, 108, 100, 97, - 5, 115, 116, 102, 108, 100, - 6, 108, 100, 115, 102, 108, 100, - 7, 108, 100, 115, 102, 108, 100, 97, - 6, 115, 116, 115, 102, 108, 100, - 5, 115, 116, 111, 98, 106, - 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 49, 46, 117, 110, - 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 50, 46, 117, 110, - 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 52, 46, 117, 110, - 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 56, 46, 117, 110, - 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 49, 46, 117, 110, - 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 50, 46, 117, 110, - 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 52, 46, 117, 110, - 14, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 56, 46, 117, 110, - 13, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 46, 117, 110, - 13, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 46, 117, 110, - 3, 98, 111, 120, - 6, 110, 101, 119, 97, 114, 114, - 5, 108, 100, 108, 101, 110, - 7, 108, 100, 101, 108, 101, 109, 97, - 9, 108, 100, 101, 108, 101, 109, 46, 105, 49, - 9, 108, 100, 101, 108, 101, 109, 46, 117, 49, - 9, 108, 100, 101, 108, 101, 109, 46, 105, 50, - 9, 108, 100, 101, 108, 101, 109, 46, 117, 50, - 9, 108, 100, 101, 108, 101, 109, 46, 105, 52, - 9, 108, 100, 101, 108, 101, 109, 46, 117, 52, - 9, 108, 100, 101, 108, 101, 109, 46, 105, 56, - 8, 108, 100, 101, 108, 101, 109, 46, 105, - 9, 108, 100, 101, 108, 101, 109, 46, 114, 52, - 9, 108, 100, 101, 108, 101, 109, 46, 114, 56, - 10, 108, 100, 101, 108, 101, 109, 46, 114, 101, 102, - 8, 115, 116, 101, 108, 101, 109, 46, 105, - 9, 115, 116, 101, 108, 101, 109, 46, 105, 49, - 9, 115, 116, 101, 108, 101, 109, 46, 105, 50, - 9, 115, 116, 101, 108, 101, 109, 46, 105, 52, - 9, 115, 116, 101, 108, 101, 109, 46, 105, 56, - 9, 115, 116, 101, 108, 101, 109, 46, 114, 52, - 9, 115, 116, 101, 108, 101, 109, 46, 114, 56, - 10, 115, 116, 101, 108, 101, 109, 46, 114, 101, 102, - 10, 108, 100, 101, 108, 101, 109, 46, 97, 110, 121, - 10, 115, 116, 101, 108, 101, 109, 46, 97, 110, 121, - 9, 117, 110, 98, 111, 120, 46, 97, 110, 121, - 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 49, - 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 49, - 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 50, - 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 50, - 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 52, - 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 52, - 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, 56, - 11, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, 56, - 9, 114, 101, 102, 97, 110, 121, 118, 97, 108, - 8, 99, 107, 102, 105, 110, 105, 116, 101, - 8, 109, 107, 114, 101, 102, 97, 110, 121, - 7, 108, 100, 116, 111, 107, 101, 110, - 7, 99, 111, 110, 118, 46, 117, 50, - 7, 99, 111, 110, 118, 46, 117, 49, - 6, 99, 111, 110, 118, 46, 105, - 10, 99, 111, 110, 118, 46, 111, 118, 102, 46, 105, - 10, 99, 111, 110, 118, 46, 111, 118, 102, 46, 117, - 7, 97, 100, 100, 46, 111, 118, 102, - 10, 97, 100, 100, 46, 111, 118, 102, 46, 117, 110, - 7, 109, 117, 108, 46, 111, 118, 102, - 10, 109, 117, 108, 46, 111, 118, 102, 46, 117, 110, - 7, 115, 117, 98, 46, 111, 118, 102, - 10, 115, 117, 98, 46, 111, 118, 102, 46, 117, 110, - 10, 101, 110, 100, 102, 105, 110, 97, 108, 108, 121, - 5, 108, 101, 97, 118, 101, - 7, 108, 101, 97, 118, 101, 46, 115, - 7, 115, 116, 105, 110, 100, 46, 105, - 6, 99, 111, 110, 118, 46, 117, - 7, 97, 114, 103, 108, 105, 115, 116, - 3, 99, 101, 113, - 3, 99, 103, 116, - 6, 99, 103, 116, 46, 117, 110, - 3, 99, 108, 116, - 6, 99, 108, 116, 46, 117, 110, - 5, 108, 100, 102, 116, 110, - 9, 108, 100, 118, 105, 114, 116, 102, 116, 110, - 5, 108, 100, 97, 114, 103, - 6, 108, 100, 97, 114, 103, 97, - 5, 115, 116, 97, 114, 103, - 5, 108, 100, 108, 111, 99, - 6, 108, 100, 108, 111, 99, 97, - 5, 115, 116, 108, 111, 99, - 8, 108, 111, 99, 97, 108, 108, 111, 99, - 9, 101, 110, 100, 102, 105, 108, 116, 101, 114, - 10, 117, 110, 97, 108, 105, 103, 110, 101, 100, 46, - 9, 118, 111, 108, 97, 116, 105, 108, 101, 46, - 5, 116, 97, 105, 108, 46, - 7, 105, 110, 105, 116, 111, 98, 106, - 12, 99, 111, 110, 115, 116, 114, 97, 105, 110, 101, 100, 46, - 5, 99, 112, 98, 108, 107, - 7, 105, 110, 105, 116, 98, 108, 107, - 3, 110, 111, 46, - 7, 114, 101, 116, 104, 114, 111, 119, - 6, 115, 105, 122, 101, 111, 102, - 10, 114, 101, 102, 97, 110, 121, 116, 121, 112, 101, - 9, 114, 101, 97, 100, 111, 110, 108, 121, 46, - }; - - names = new string [219]; - - for (int i = 0, p = 0; i < names.Length; i++) { - var buffer = new char [table [p++]]; - - for (int j = 0; j < buffer.Length; j++) - buffer [j] = (char)table [p++]; - - names [i] = new string (buffer); - } - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCode.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCode.cs.meta deleted file mode 100644 index 21d9966..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCode.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5d8b234c106529441912c10b87502175 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCodes.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCodes.cs deleted file mode 100644 index f05d164..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCodes.cs +++ /dev/null @@ -1,894 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil.Cil { - - public static class OpCodes { - - internal static readonly OpCode [] OneByteOpCode = new OpCode [0xe0 + 1]; - internal static readonly OpCode [] TwoBytesOpCode = new OpCode [0x1e + 1]; - - public static readonly OpCode Nop = new OpCode ( - 0xff << 0 | 0x00 << 8 | (byte)Code.Nop << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Break = new OpCode ( - 0xff << 0 | 0x01 << 8 | (byte)Code.Break << 16 | (byte)FlowControl.Break << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Ldarg_0 = new OpCode ( - 0xff << 0 | 0x02 << 8 | (byte)Code.Ldarg_0 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldarg_1 = new OpCode ( - 0xff << 0 | 0x03 << 8 | (byte)Code.Ldarg_1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldarg_2 = new OpCode ( - 0xff << 0 | 0x04 << 8 | (byte)Code.Ldarg_2 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldarg_3 = new OpCode ( - 0xff << 0 | 0x05 << 8 | (byte)Code.Ldarg_3 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldloc_0 = new OpCode ( - 0xff << 0 | 0x06 << 8 | (byte)Code.Ldloc_0 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldloc_1 = new OpCode ( - 0xff << 0 | 0x07 << 8 | (byte)Code.Ldloc_1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldloc_2 = new OpCode ( - 0xff << 0 | 0x08 << 8 | (byte)Code.Ldloc_2 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldloc_3 = new OpCode ( - 0xff << 0 | 0x09 << 8 | (byte)Code.Ldloc_3 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Stloc_0 = new OpCode ( - 0xff << 0 | 0x0a << 8 | (byte)Code.Stloc_0 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stloc_1 = new OpCode ( - 0xff << 0 | 0x0b << 8 | (byte)Code.Stloc_1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stloc_2 = new OpCode ( - 0xff << 0 | 0x0c << 8 | (byte)Code.Stloc_2 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stloc_3 = new OpCode ( - 0xff << 0 | 0x0d << 8 | (byte)Code.Stloc_3 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Ldarg_S = new OpCode ( - 0xff << 0 | 0x0e << 8 | (byte)Code.Ldarg_S << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineArg << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldarga_S = new OpCode ( - 0xff << 0 | 0x0f << 8 | (byte)Code.Ldarga_S << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineArg << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Starg_S = new OpCode ( - 0xff << 0 | 0x10 << 8 | (byte)Code.Starg_S << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineArg << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Ldloc_S = new OpCode ( - 0xff << 0 | 0x11 << 8 | (byte)Code.Ldloc_S << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineVar << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldloca_S = new OpCode ( - 0xff << 0 | 0x12 << 8 | (byte)Code.Ldloca_S << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineVar << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Stloc_S = new OpCode ( - 0xff << 0 | 0x13 << 8 | (byte)Code.Stloc_S << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineVar << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Ldnull = new OpCode ( - 0xff << 0 | 0x14 << 8 | (byte)Code.Ldnull << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushref << 24); - - public static readonly OpCode Ldc_I4_M1 = new OpCode ( - 0xff << 0 | 0x15 << 8 | (byte)Code.Ldc_I4_M1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldc_I4_0 = new OpCode ( - 0xff << 0 | 0x16 << 8 | (byte)Code.Ldc_I4_0 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldc_I4_1 = new OpCode ( - 0xff << 0 | 0x17 << 8 | (byte)Code.Ldc_I4_1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldc_I4_2 = new OpCode ( - 0xff << 0 | 0x18 << 8 | (byte)Code.Ldc_I4_2 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldc_I4_3 = new OpCode ( - 0xff << 0 | 0x19 << 8 | (byte)Code.Ldc_I4_3 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldc_I4_4 = new OpCode ( - 0xff << 0 | 0x1a << 8 | (byte)Code.Ldc_I4_4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldc_I4_5 = new OpCode ( - 0xff << 0 | 0x1b << 8 | (byte)Code.Ldc_I4_5 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldc_I4_6 = new OpCode ( - 0xff << 0 | 0x1c << 8 | (byte)Code.Ldc_I4_6 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldc_I4_7 = new OpCode ( - 0xff << 0 | 0x1d << 8 | (byte)Code.Ldc_I4_7 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldc_I4_8 = new OpCode ( - 0xff << 0 | 0x1e << 8 | (byte)Code.Ldc_I4_8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldc_I4_S = new OpCode ( - 0xff << 0 | 0x1f << 8 | (byte)Code.Ldc_I4_S << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineI << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldc_I4 = new OpCode ( - 0xff << 0 | 0x20 << 8 | (byte)Code.Ldc_I4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineI << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldc_I8 = new OpCode ( - 0xff << 0 | 0x21 << 8 | (byte)Code.Ldc_I8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineI8 << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi8 << 24); - - public static readonly OpCode Ldc_R4 = new OpCode ( - 0xff << 0 | 0x22 << 8 | (byte)Code.Ldc_R4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.ShortInlineR << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushr4 << 24); - - public static readonly OpCode Ldc_R8 = new OpCode ( - 0xff << 0 | 0x23 << 8 | (byte)Code.Ldc_R8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineR << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushr8 << 24); - - public static readonly OpCode Dup = new OpCode ( - 0xff << 0 | 0x25 << 8 | (byte)Code.Dup << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Push1_push1 << 24); - - public static readonly OpCode Pop = new OpCode ( - 0xff << 0 | 0x26 << 8 | (byte)Code.Pop << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Jmp = new OpCode ( - 0xff << 0 | 0x27 << 8 | (byte)Code.Jmp << 16 | (byte)FlowControl.Call << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineMethod << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Call = new OpCode ( - 0xff << 0 | 0x28 << 8 | (byte)Code.Call << 16 | (byte)FlowControl.Call << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineMethod << 8 | (byte)StackBehaviour.Varpop << 16 | (byte)StackBehaviour.Varpush << 24); - - public static readonly OpCode Calli = new OpCode ( - 0xff << 0 | 0x29 << 8 | (byte)Code.Calli << 16 | (byte)FlowControl.Call << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineSig << 8 | (byte)StackBehaviour.Varpop << 16 | (byte)StackBehaviour.Varpush << 24); - - public static readonly OpCode Ret = new OpCode ( - 0xff << 0 | 0x2a << 8 | (byte)Code.Ret << 16 | (byte)FlowControl.Return << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Varpop << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Br_S = new OpCode ( - 0xff << 0 | 0x2b << 8 | (byte)Code.Br_S << 16 | (byte)FlowControl.Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineBrTarget << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Brfalse_S = new OpCode ( - 0xff << 0 | 0x2c << 8 | (byte)Code.Brfalse_S << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineBrTarget << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Brtrue_S = new OpCode ( - 0xff << 0 | 0x2d << 8 | (byte)Code.Brtrue_S << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineBrTarget << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Beq_S = new OpCode ( - 0xff << 0 | 0x2e << 8 | (byte)Code.Beq_S << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Bge_S = new OpCode ( - 0xff << 0 | 0x2f << 8 | (byte)Code.Bge_S << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Bgt_S = new OpCode ( - 0xff << 0 | 0x30 << 8 | (byte)Code.Bgt_S << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Ble_S = new OpCode ( - 0xff << 0 | 0x31 << 8 | (byte)Code.Ble_S << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Blt_S = new OpCode ( - 0xff << 0 | 0x32 << 8 | (byte)Code.Blt_S << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Bne_Un_S = new OpCode ( - 0xff << 0 | 0x33 << 8 | (byte)Code.Bne_Un_S << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Bge_Un_S = new OpCode ( - 0xff << 0 | 0x34 << 8 | (byte)Code.Bge_Un_S << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Bgt_Un_S = new OpCode ( - 0xff << 0 | 0x35 << 8 | (byte)Code.Bgt_Un_S << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Ble_Un_S = new OpCode ( - 0xff << 0 | 0x36 << 8 | (byte)Code.Ble_Un_S << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Blt_Un_S = new OpCode ( - 0xff << 0 | 0x37 << 8 | (byte)Code.Blt_Un_S << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Br = new OpCode ( - 0xff << 0 | 0x38 << 8 | (byte)Code.Br << 16 | (byte)FlowControl.Branch << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineBrTarget << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Brfalse = new OpCode ( - 0xff << 0 | 0x39 << 8 | (byte)Code.Brfalse << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineBrTarget << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Brtrue = new OpCode ( - 0xff << 0 | 0x3a << 8 | (byte)Code.Brtrue << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineBrTarget << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Beq = new OpCode ( - 0xff << 0 | 0x3b << 8 | (byte)Code.Beq << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Bge = new OpCode ( - 0xff << 0 | 0x3c << 8 | (byte)Code.Bge << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Bgt = new OpCode ( - 0xff << 0 | 0x3d << 8 | (byte)Code.Bgt << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Ble = new OpCode ( - 0xff << 0 | 0x3e << 8 | (byte)Code.Ble << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Blt = new OpCode ( - 0xff << 0 | 0x3f << 8 | (byte)Code.Blt << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Bne_Un = new OpCode ( - 0xff << 0 | 0x40 << 8 | (byte)Code.Bne_Un << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Bge_Un = new OpCode ( - 0xff << 0 | 0x41 << 8 | (byte)Code.Bge_Un << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Bgt_Un = new OpCode ( - 0xff << 0 | 0x42 << 8 | (byte)Code.Bgt_Un << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Ble_Un = new OpCode ( - 0xff << 0 | 0x43 << 8 | (byte)Code.Ble_Un << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Blt_Un = new OpCode ( - 0xff << 0 | 0x44 << 8 | (byte)Code.Blt_Un << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.InlineBrTarget << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Switch = new OpCode ( - 0xff << 0 | 0x45 << 8 | (byte)Code.Switch << 16 | (byte)FlowControl.Cond_Branch << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineSwitch << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Ldind_I1 = new OpCode ( - 0xff << 0 | 0x46 << 8 | (byte)Code.Ldind_I1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldind_U1 = new OpCode ( - 0xff << 0 | 0x47 << 8 | (byte)Code.Ldind_U1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldind_I2 = new OpCode ( - 0xff << 0 | 0x48 << 8 | (byte)Code.Ldind_I2 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldind_U2 = new OpCode ( - 0xff << 0 | 0x49 << 8 | (byte)Code.Ldind_U2 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldind_I4 = new OpCode ( - 0xff << 0 | 0x4a << 8 | (byte)Code.Ldind_I4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldind_U4 = new OpCode ( - 0xff << 0 | 0x4b << 8 | (byte)Code.Ldind_U4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldind_I8 = new OpCode ( - 0xff << 0 | 0x4c << 8 | (byte)Code.Ldind_I8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Pushi8 << 24); - - public static readonly OpCode Ldind_I = new OpCode ( - 0xff << 0 | 0x4d << 8 | (byte)Code.Ldind_I << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldind_R4 = new OpCode ( - 0xff << 0 | 0x4e << 8 | (byte)Code.Ldind_R4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Pushr4 << 24); - - public static readonly OpCode Ldind_R8 = new OpCode ( - 0xff << 0 | 0x4f << 8 | (byte)Code.Ldind_R8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Pushr8 << 24); - - public static readonly OpCode Ldind_Ref = new OpCode ( - 0xff << 0 | 0x50 << 8 | (byte)Code.Ldind_Ref << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Pushref << 24); - - public static readonly OpCode Stind_Ref = new OpCode ( - 0xff << 0 | 0x51 << 8 | (byte)Code.Stind_Ref << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi_popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stind_I1 = new OpCode ( - 0xff << 0 | 0x52 << 8 | (byte)Code.Stind_I1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi_popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stind_I2 = new OpCode ( - 0xff << 0 | 0x53 << 8 | (byte)Code.Stind_I2 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi_popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stind_I4 = new OpCode ( - 0xff << 0 | 0x54 << 8 | (byte)Code.Stind_I4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi_popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stind_I8 = new OpCode ( - 0xff << 0 | 0x55 << 8 | (byte)Code.Stind_I8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi_popi8 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stind_R4 = new OpCode ( - 0xff << 0 | 0x56 << 8 | (byte)Code.Stind_R4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi_popr4 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stind_R8 = new OpCode ( - 0xff << 0 | 0x57 << 8 | (byte)Code.Stind_R8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi_popr8 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Add = new OpCode ( - 0xff << 0 | 0x58 << 8 | (byte)Code.Add << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Sub = new OpCode ( - 0xff << 0 | 0x59 << 8 | (byte)Code.Sub << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Mul = new OpCode ( - 0xff << 0 | 0x5a << 8 | (byte)Code.Mul << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Div = new OpCode ( - 0xff << 0 | 0x5b << 8 | (byte)Code.Div << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Div_Un = new OpCode ( - 0xff << 0 | 0x5c << 8 | (byte)Code.Div_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Rem = new OpCode ( - 0xff << 0 | 0x5d << 8 | (byte)Code.Rem << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Rem_Un = new OpCode ( - 0xff << 0 | 0x5e << 8 | (byte)Code.Rem_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode And = new OpCode ( - 0xff << 0 | 0x5f << 8 | (byte)Code.And << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Or = new OpCode ( - 0xff << 0 | 0x60 << 8 | (byte)Code.Or << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Xor = new OpCode ( - 0xff << 0 | 0x61 << 8 | (byte)Code.Xor << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Shl = new OpCode ( - 0xff << 0 | 0x62 << 8 | (byte)Code.Shl << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Shr = new OpCode ( - 0xff << 0 | 0x63 << 8 | (byte)Code.Shr << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Shr_Un = new OpCode ( - 0xff << 0 | 0x64 << 8 | (byte)Code.Shr_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Neg = new OpCode ( - 0xff << 0 | 0x65 << 8 | (byte)Code.Neg << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Not = new OpCode ( - 0xff << 0 | 0x66 << 8 | (byte)Code.Not << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Conv_I1 = new OpCode ( - 0xff << 0 | 0x67 << 8 | (byte)Code.Conv_I1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_I2 = new OpCode ( - 0xff << 0 | 0x68 << 8 | (byte)Code.Conv_I2 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_I4 = new OpCode ( - 0xff << 0 | 0x69 << 8 | (byte)Code.Conv_I4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_I8 = new OpCode ( - 0xff << 0 | 0x6a << 8 | (byte)Code.Conv_I8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi8 << 24); - - public static readonly OpCode Conv_R4 = new OpCode ( - 0xff << 0 | 0x6b << 8 | (byte)Code.Conv_R4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushr4 << 24); - - public static readonly OpCode Conv_R8 = new OpCode ( - 0xff << 0 | 0x6c << 8 | (byte)Code.Conv_R8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushr8 << 24); - - public static readonly OpCode Conv_U4 = new OpCode ( - 0xff << 0 | 0x6d << 8 | (byte)Code.Conv_U4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_U8 = new OpCode ( - 0xff << 0 | 0x6e << 8 | (byte)Code.Conv_U8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi8 << 24); - - public static readonly OpCode Callvirt = new OpCode ( - 0xff << 0 | 0x6f << 8 | (byte)Code.Callvirt << 16 | (byte)FlowControl.Call << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineMethod << 8 | (byte)StackBehaviour.Varpop << 16 | (byte)StackBehaviour.Varpush << 24); - - public static readonly OpCode Cpobj = new OpCode ( - 0xff << 0 | 0x70 << 8 | (byte)Code.Cpobj << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Popi_popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Ldobj = new OpCode ( - 0xff << 0 | 0x71 << 8 | (byte)Code.Ldobj << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldstr = new OpCode ( - 0xff << 0 | 0x72 << 8 | (byte)Code.Ldstr << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineString << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushref << 24); - - public static readonly OpCode Newobj = new OpCode ( - 0xff << 0 | 0x73 << 8 | (byte)Code.Newobj << 16 | (byte)FlowControl.Call << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineMethod << 8 | (byte)StackBehaviour.Varpop << 16 | (byte)StackBehaviour.Pushref << 24); - - public static readonly OpCode Castclass = new OpCode ( - 0xff << 0 | 0x74 << 8 | (byte)Code.Castclass << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Popref << 16 | (byte)StackBehaviour.Pushref << 24); - - public static readonly OpCode Isinst = new OpCode ( - 0xff << 0 | 0x75 << 8 | (byte)Code.Isinst << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Popref << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_R_Un = new OpCode ( - 0xff << 0 | 0x76 << 8 | (byte)Code.Conv_R_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushr8 << 24); - - public static readonly OpCode Unbox = new OpCode ( - 0xff << 0 | 0x79 << 8 | (byte)Code.Unbox << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Popref << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Throw = new OpCode ( - 0xff << 0 | 0x7a << 8 | (byte)Code.Throw << 16 | (byte)FlowControl.Throw << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Ldfld = new OpCode ( - 0xff << 0 | 0x7b << 8 | (byte)Code.Ldfld << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineField << 8 | (byte)StackBehaviour.Popref << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldflda = new OpCode ( - 0xff << 0 | 0x7c << 8 | (byte)Code.Ldflda << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineField << 8 | (byte)StackBehaviour.Popref << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Stfld = new OpCode ( - 0xff << 0 | 0x7d << 8 | (byte)Code.Stfld << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineField << 8 | (byte)StackBehaviour.Popref_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Ldsfld = new OpCode ( - 0xff << 0 | 0x7e << 8 | (byte)Code.Ldsfld << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineField << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldsflda = new OpCode ( - 0xff << 0 | 0x7f << 8 | (byte)Code.Ldsflda << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineField << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Stsfld = new OpCode ( - 0xff << 0 | 0x80 << 8 | (byte)Code.Stsfld << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineField << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stobj = new OpCode ( - 0xff << 0 | 0x81 << 8 | (byte)Code.Stobj << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Popi_pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Conv_Ovf_I1_Un = new OpCode ( - 0xff << 0 | 0x82 << 8 | (byte)Code.Conv_Ovf_I1_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_I2_Un = new OpCode ( - 0xff << 0 | 0x83 << 8 | (byte)Code.Conv_Ovf_I2_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_I4_Un = new OpCode ( - 0xff << 0 | 0x84 << 8 | (byte)Code.Conv_Ovf_I4_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_I8_Un = new OpCode ( - 0xff << 0 | 0x85 << 8 | (byte)Code.Conv_Ovf_I8_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi8 << 24); - - public static readonly OpCode Conv_Ovf_U1_Un = new OpCode ( - 0xff << 0 | 0x86 << 8 | (byte)Code.Conv_Ovf_U1_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_U2_Un = new OpCode ( - 0xff << 0 | 0x87 << 8 | (byte)Code.Conv_Ovf_U2_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_U4_Un = new OpCode ( - 0xff << 0 | 0x88 << 8 | (byte)Code.Conv_Ovf_U4_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_U8_Un = new OpCode ( - 0xff << 0 | 0x89 << 8 | (byte)Code.Conv_Ovf_U8_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi8 << 24); - - public static readonly OpCode Conv_Ovf_I_Un = new OpCode ( - 0xff << 0 | 0x8a << 8 | (byte)Code.Conv_Ovf_I_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_U_Un = new OpCode ( - 0xff << 0 | 0x8b << 8 | (byte)Code.Conv_Ovf_U_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Box = new OpCode ( - 0xff << 0 | 0x8c << 8 | (byte)Code.Box << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushref << 24); - - public static readonly OpCode Newarr = new OpCode ( - 0xff << 0 | 0x8d << 8 | (byte)Code.Newarr << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Pushref << 24); - - public static readonly OpCode Ldlen = new OpCode ( - 0xff << 0 | 0x8e << 8 | (byte)Code.Ldlen << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldelema = new OpCode ( - 0xff << 0 | 0x8f << 8 | (byte)Code.Ldelema << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Popref_popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldelem_I1 = new OpCode ( - 0xff << 0 | 0x90 << 8 | (byte)Code.Ldelem_I1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldelem_U1 = new OpCode ( - 0xff << 0 | 0x91 << 8 | (byte)Code.Ldelem_U1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldelem_I2 = new OpCode ( - 0xff << 0 | 0x92 << 8 | (byte)Code.Ldelem_I2 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldelem_U2 = new OpCode ( - 0xff << 0 | 0x93 << 8 | (byte)Code.Ldelem_U2 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldelem_I4 = new OpCode ( - 0xff << 0 | 0x94 << 8 | (byte)Code.Ldelem_I4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldelem_U4 = new OpCode ( - 0xff << 0 | 0x95 << 8 | (byte)Code.Ldelem_U4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldelem_I8 = new OpCode ( - 0xff << 0 | 0x96 << 8 | (byte)Code.Ldelem_I8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi << 16 | (byte)StackBehaviour.Pushi8 << 24); - - public static readonly OpCode Ldelem_I = new OpCode ( - 0xff << 0 | 0x97 << 8 | (byte)Code.Ldelem_I << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldelem_R4 = new OpCode ( - 0xff << 0 | 0x98 << 8 | (byte)Code.Ldelem_R4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi << 16 | (byte)StackBehaviour.Pushr4 << 24); - - public static readonly OpCode Ldelem_R8 = new OpCode ( - 0xff << 0 | 0x99 << 8 | (byte)Code.Ldelem_R8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi << 16 | (byte)StackBehaviour.Pushr8 << 24); - - public static readonly OpCode Ldelem_Ref = new OpCode ( - 0xff << 0 | 0x9a << 8 | (byte)Code.Ldelem_Ref << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi << 16 | (byte)StackBehaviour.Pushref << 24); - - public static readonly OpCode Stelem_I = new OpCode ( - 0xff << 0 | 0x9b << 8 | (byte)Code.Stelem_I << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi_popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stelem_I1 = new OpCode ( - 0xff << 0 | 0x9c << 8 | (byte)Code.Stelem_I1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi_popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stelem_I2 = new OpCode ( - 0xff << 0 | 0x9d << 8 | (byte)Code.Stelem_I2 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi_popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stelem_I4 = new OpCode ( - 0xff << 0 | 0x9e << 8 | (byte)Code.Stelem_I4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi_popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stelem_I8 = new OpCode ( - 0xff << 0 | 0x9f << 8 | (byte)Code.Stelem_I8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi_popi8 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stelem_R4 = new OpCode ( - 0xff << 0 | 0xa0 << 8 | (byte)Code.Stelem_R4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi_popr4 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stelem_R8 = new OpCode ( - 0xff << 0 | 0xa1 << 8 | (byte)Code.Stelem_R8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi_popr8 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stelem_Ref = new OpCode ( - 0xff << 0 | 0xa2 << 8 | (byte)Code.Stelem_Ref << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popref_popi_popref << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Ldelem_Any = new OpCode ( - 0xff << 0 | 0xa3 << 8 | (byte)Code.Ldelem_Any << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Popref_popi << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Stelem_Any = new OpCode ( - 0xff << 0 | 0xa4 << 8 | (byte)Code.Stelem_Any << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Popref_popi_popref << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Unbox_Any = new OpCode ( - 0xff << 0 | 0xa5 << 8 | (byte)Code.Unbox_Any << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Popref << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Conv_Ovf_I1 = new OpCode ( - 0xff << 0 | 0xb3 << 8 | (byte)Code.Conv_Ovf_I1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_U1 = new OpCode ( - 0xff << 0 | 0xb4 << 8 | (byte)Code.Conv_Ovf_U1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_I2 = new OpCode ( - 0xff << 0 | 0xb5 << 8 | (byte)Code.Conv_Ovf_I2 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_U2 = new OpCode ( - 0xff << 0 | 0xb6 << 8 | (byte)Code.Conv_Ovf_U2 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_I4 = new OpCode ( - 0xff << 0 | 0xb7 << 8 | (byte)Code.Conv_Ovf_I4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_U4 = new OpCode ( - 0xff << 0 | 0xb8 << 8 | (byte)Code.Conv_Ovf_U4 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_I8 = new OpCode ( - 0xff << 0 | 0xb9 << 8 | (byte)Code.Conv_Ovf_I8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi8 << 24); - - public static readonly OpCode Conv_Ovf_U8 = new OpCode ( - 0xff << 0 | 0xba << 8 | (byte)Code.Conv_Ovf_U8 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi8 << 24); - - public static readonly OpCode Refanyval = new OpCode ( - 0xff << 0 | 0xc2 << 8 | (byte)Code.Refanyval << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ckfinite = new OpCode ( - 0xff << 0 | 0xc3 << 8 | (byte)Code.Ckfinite << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushr8 << 24); - - public static readonly OpCode Mkrefany = new OpCode ( - 0xff << 0 | 0xc6 << 8 | (byte)Code.Mkrefany << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldtoken = new OpCode ( - 0xff << 0 | 0xd0 << 8 | (byte)Code.Ldtoken << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineTok << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_U2 = new OpCode ( - 0xff << 0 | 0xd1 << 8 | (byte)Code.Conv_U2 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_U1 = new OpCode ( - 0xff << 0 | 0xd2 << 8 | (byte)Code.Conv_U1 << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_I = new OpCode ( - 0xff << 0 | 0xd3 << 8 | (byte)Code.Conv_I << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_I = new OpCode ( - 0xff << 0 | 0xd4 << 8 | (byte)Code.Conv_Ovf_I << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Conv_Ovf_U = new OpCode ( - 0xff << 0 | 0xd5 << 8 | (byte)Code.Conv_Ovf_U << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Add_Ovf = new OpCode ( - 0xff << 0 | 0xd6 << 8 | (byte)Code.Add_Ovf << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Add_Ovf_Un = new OpCode ( - 0xff << 0 | 0xd7 << 8 | (byte)Code.Add_Ovf_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Mul_Ovf = new OpCode ( - 0xff << 0 | 0xd8 << 8 | (byte)Code.Mul_Ovf << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Mul_Ovf_Un = new OpCode ( - 0xff << 0 | 0xd9 << 8 | (byte)Code.Mul_Ovf_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Sub_Ovf = new OpCode ( - 0xff << 0 | 0xda << 8 | (byte)Code.Sub_Ovf << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Sub_Ovf_Un = new OpCode ( - 0xff << 0 | 0xdb << 8 | (byte)Code.Sub_Ovf_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Endfinally = new OpCode ( - 0xff << 0 | 0xdc << 8 | (byte)Code.Endfinally << 16 | (byte)FlowControl.Return << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Leave = new OpCode ( - 0xff << 0 | 0xdd << 8 | (byte)Code.Leave << 16 | (byte)FlowControl.Branch << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineBrTarget << 8 | (byte)StackBehaviour.PopAll << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Leave_S = new OpCode ( - 0xff << 0 | 0xde << 8 | (byte)Code.Leave_S << 16 | (byte)FlowControl.Branch << 24, - (byte)OpCodeType.Macro << 0 | (byte)OperandType.ShortInlineBrTarget << 8 | (byte)StackBehaviour.PopAll << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Stind_I = new OpCode ( - 0xff << 0 | 0xdf << 8 | (byte)Code.Stind_I << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi_popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Conv_U = new OpCode ( - 0xff << 0 | 0xe0 << 8 | (byte)Code.Conv_U << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Arglist = new OpCode ( - 0xfe << 0 | 0x00 << 8 | (byte)Code.Arglist << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ceq = new OpCode ( - 0xfe << 0 | 0x01 << 8 | (byte)Code.Ceq << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Cgt = new OpCode ( - 0xfe << 0 | 0x02 << 8 | (byte)Code.Cgt << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Cgt_Un = new OpCode ( - 0xfe << 0 | 0x03 << 8 | (byte)Code.Cgt_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Clt = new OpCode ( - 0xfe << 0 | 0x04 << 8 | (byte)Code.Clt << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Clt_Un = new OpCode ( - 0xfe << 0 | 0x05 << 8 | (byte)Code.Clt_Un << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1_pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldftn = new OpCode ( - 0xfe << 0 | 0x06 << 8 | (byte)Code.Ldftn << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineMethod << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldvirtftn = new OpCode ( - 0xfe << 0 | 0x07 << 8 | (byte)Code.Ldvirtftn << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineMethod << 8 | (byte)StackBehaviour.Popref << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Ldarg = new OpCode ( - 0xfe << 0 | 0x09 << 8 | (byte)Code.Ldarg << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineArg << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldarga = new OpCode ( - 0xfe << 0 | 0x0a << 8 | (byte)Code.Ldarga << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineArg << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Starg = new OpCode ( - 0xfe << 0 | 0x0b << 8 | (byte)Code.Starg << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineArg << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Ldloc = new OpCode ( - 0xfe << 0 | 0x0c << 8 | (byte)Code.Ldloc << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineVar << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push1 << 24); - - public static readonly OpCode Ldloca = new OpCode ( - 0xfe << 0 | 0x0d << 8 | (byte)Code.Ldloca << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineVar << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Stloc = new OpCode ( - 0xfe << 0 | 0x0e << 8 | (byte)Code.Stloc << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineVar << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Localloc = new OpCode ( - 0xfe << 0 | 0x0f << 8 | (byte)Code.Localloc << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Endfilter = new OpCode ( - 0xfe << 0 | 0x11 << 8 | (byte)Code.Endfilter << 16 | (byte)FlowControl.Return << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Unaligned = new OpCode ( - 0xfe << 0 | 0x12 << 8 | (byte)Code.Unaligned << 16 | (byte)FlowControl.Meta << 24, - (byte)OpCodeType.Prefix << 0 | (byte)OperandType.ShortInlineI << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Volatile = new OpCode ( - 0xfe << 0 | 0x13 << 8 | (byte)Code.Volatile << 16 | (byte)FlowControl.Meta << 24, - (byte)OpCodeType.Prefix << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Tail = new OpCode ( - 0xfe << 0 | 0x14 << 8 | (byte)Code.Tail << 16 | (byte)FlowControl.Meta << 24, - (byte)OpCodeType.Prefix << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Initobj = new OpCode ( - 0xfe << 0 | 0x15 << 8 | (byte)Code.Initobj << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Constrained = new OpCode ( - 0xfe << 0 | 0x16 << 8 | (byte)Code.Constrained << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Prefix << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Cpblk = new OpCode ( - 0xfe << 0 | 0x17 << 8 | (byte)Code.Cpblk << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi_popi_popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Initblk = new OpCode ( - 0xfe << 0 | 0x18 << 8 | (byte)Code.Initblk << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Popi_popi_popi << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode No = new OpCode ( - 0xfe << 0 | 0x19 << 8 | (byte)Code.No << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Prefix << 0 | (byte)OperandType.ShortInlineI << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Rethrow = new OpCode ( - 0xfe << 0 | 0x1a << 8 | (byte)Code.Rethrow << 16 | (byte)FlowControl.Throw << 24, - (byte)OpCodeType.Objmodel << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push0 << 24); - - public static readonly OpCode Sizeof = new OpCode ( - 0xfe << 0 | 0x1c << 8 | (byte)Code.Sizeof << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineType << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Refanytype = new OpCode ( - 0xfe << 0 | 0x1d << 8 | (byte)Code.Refanytype << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Primitive << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop1 << 16 | (byte)StackBehaviour.Pushi << 24); - - public static readonly OpCode Readonly = new OpCode ( - 0xfe << 0 | 0x1e << 8 | (byte)Code.Readonly << 16 | (byte)FlowControl.Next << 24, - (byte)OpCodeType.Prefix << 0 | (byte)OperandType.InlineNone << 8 | (byte)StackBehaviour.Pop0 << 16 | (byte)StackBehaviour.Push0 << 24); - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCodes.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCodes.cs.meta deleted file mode 100644 index 422968a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/OpCodes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 52c19a62321778c438d2f6b483f18e73 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/PortablePdb.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/PortablePdb.cs deleted file mode 100644 index 64b7ad7..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/PortablePdb.cs +++ /dev/null @@ -1,591 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Metadata; -using MonoFN.Cecil.PE; -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; - -namespace MonoFN.Cecil.Cil { - - public sealed class PortablePdbReaderProvider : ISymbolReaderProvider { - - public ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName) - { - Mixin.CheckModule (module); - Mixin.CheckFileName (fileName); - - var file = File.OpenRead (Mixin.GetPdbFileName (fileName)); - return GetSymbolReader (module, Disposable.Owned (file as Stream), file.Name); - } - - public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream) - { - Mixin.CheckModule (module); - Mixin.CheckStream (symbolStream); - - return GetSymbolReader (module, Disposable.NotOwned (symbolStream), symbolStream.GetFileName ()); - } - - ISymbolReader GetSymbolReader (ModuleDefinition module, Disposable symbolStream, string fileName) - { - return new PortablePdbReader (ImageReader.ReadPortablePdb (symbolStream, fileName), module); - } - } - - public sealed class PortablePdbReader : ISymbolReader { - - readonly Image image; - readonly ModuleDefinition module; - readonly MetadataReader reader; - readonly MetadataReader debug_reader; - - bool IsEmbedded { get { return reader.image == debug_reader.image; } } - - internal PortablePdbReader (Image image, ModuleDefinition module) - { - this.image = image; - this.module = module; - this.reader = module.reader; - this.debug_reader = new MetadataReader (image, module, this.reader); - } - - public ISymbolWriterProvider GetWriterProvider () - { - return new PortablePdbWriterProvider (); - } - - public bool ProcessDebugHeader (ImageDebugHeader header) - { - if (image == module.Image) - return true; - - foreach (var entry in header.Entries) { - if (!IsMatchingEntry (image.PdbHeap, entry)) - continue; - - ReadModule (); - return true; - } - - return false; - } - - static bool IsMatchingEntry (PdbHeap heap, ImageDebugHeaderEntry entry) - { - if (entry.Directory.Type != ImageDebugType.CodeView) - return false; - - var data = entry.Data; - - if (data.Length < 24) - return false; - - var magic = ReadInt32 (data, 0); - if (magic != 0x53445352) - return false; - - var buffer = new byte [16]; - Buffer.BlockCopy (data, 4, buffer, 0, 16); - - var module_guid = new Guid (buffer); - - Buffer.BlockCopy (heap.Id, 0, buffer, 0, 16); - - var pdb_guid = new Guid (buffer); - - return module_guid == pdb_guid; - } - - static int ReadInt32 (byte [] bytes, int start) - { - return (bytes [start] - | (bytes [start + 1] << 8) - | (bytes [start + 2] << 16) - | (bytes [start + 3] << 24)); - } - - void ReadModule () - { - module.custom_infos = debug_reader.GetCustomDebugInformation (module); - } - - public MethodDebugInformation Read (MethodDefinition method) - { - var info = new MethodDebugInformation (method); - ReadSequencePoints (info); - ReadScope (info); - ReadStateMachineKickOffMethod (info); - ReadCustomDebugInformations (info); - return info; - } - - void ReadSequencePoints (MethodDebugInformation method_info) - { - method_info.sequence_points = debug_reader.ReadSequencePoints (method_info.method); - } - - void ReadScope (MethodDebugInformation method_info) - { - method_info.scope = debug_reader.ReadScope (method_info.method); - } - - void ReadStateMachineKickOffMethod (MethodDebugInformation method_info) - { - method_info.kickoff_method = debug_reader.ReadStateMachineKickoffMethod (method_info.method); - } - - void ReadCustomDebugInformations (MethodDebugInformation info) - { - info.method.custom_infos = debug_reader.GetCustomDebugInformation (info.method); - } - - public void Dispose () - { - if (IsEmbedded) - return; - - image.Dispose (); - } - } - - public sealed class EmbeddedPortablePdbReaderProvider : ISymbolReaderProvider { - - public ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName) - { - Mixin.CheckModule (module); - - var header = module.GetDebugHeader (); - var entry = header.GetEmbeddedPortablePdbEntry (); - if (entry == null) - throw new InvalidOperationException (); - - return new EmbeddedPortablePdbReader ( - (PortablePdbReader)new PortablePdbReaderProvider ().GetSymbolReader (module, GetPortablePdbStream (entry))); - } - - static Stream GetPortablePdbStream (ImageDebugHeaderEntry entry) - { - var compressed_stream = new MemoryStream (entry.Data); - var reader = new BinaryStreamReader (compressed_stream); - reader.ReadInt32 (); // signature - var length = reader.ReadInt32 (); - var decompressed_stream = new MemoryStream (length); - - using (var deflate_stream = new DeflateStream (compressed_stream, CompressionMode.Decompress, leaveOpen: true)) - deflate_stream.CopyTo (decompressed_stream); - - return decompressed_stream; - } - - public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream) - { - throw new NotSupportedException (); - } - } - - public sealed class EmbeddedPortablePdbReader : ISymbolReader { - private readonly PortablePdbReader reader; - - internal EmbeddedPortablePdbReader (PortablePdbReader reader) - { - if (reader == null) - throw new ArgumentNullException (); - - this.reader = reader; - } - - public ISymbolWriterProvider GetWriterProvider () - { - return new EmbeddedPortablePdbWriterProvider (); - } - - public bool ProcessDebugHeader (ImageDebugHeader header) - { - return reader.ProcessDebugHeader (header); - } - - public MethodDebugInformation Read (MethodDefinition method) - { - return reader.Read (method); - } - - public void Dispose () - { - reader.Dispose (); - } - } - - public sealed class PortablePdbWriterProvider : ISymbolWriterProvider { - public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName) - { - Mixin.CheckModule (module); - Mixin.CheckFileName (fileName); - - var file = File.OpenWrite (Mixin.GetPdbFileName (fileName)); - return GetSymbolWriter (module, Disposable.Owned (file as Stream)); - } - - public ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream) - { - Mixin.CheckModule (module); - Mixin.CheckStream (symbolStream); - - return GetSymbolWriter (module, Disposable.NotOwned (symbolStream)); - } - - ISymbolWriter GetSymbolWriter (ModuleDefinition module, Disposable stream) - { - var metadata = new MetadataBuilder (module, this); - var writer = ImageWriter.CreateDebugWriter (module, metadata, stream); - - return new PortablePdbWriter (metadata, module, writer); - } - } - - public sealed class PortablePdbWriter : ISymbolWriter { - - readonly MetadataBuilder pdb_metadata; - readonly ModuleDefinition module; - readonly ImageWriter writer; - - MetadataBuilder module_metadata; - - bool IsEmbedded { get { return writer == null; } } - - internal PortablePdbWriter (MetadataBuilder pdb_metadata, ModuleDefinition module) - { - this.pdb_metadata = pdb_metadata; - this.module = module; - - this.module_metadata = module.metadata_builder; - - if (module_metadata != pdb_metadata) - this.pdb_metadata.metadata_builder = this.module_metadata; - - pdb_metadata.AddCustomDebugInformations (module); - } - - internal PortablePdbWriter (MetadataBuilder pdb_metadata, ModuleDefinition module, ImageWriter writer) - : this (pdb_metadata, module) - { - this.writer = writer; - } - - public ISymbolReaderProvider GetReaderProvider () - { - return new PortablePdbReaderProvider (); - } - - public ImageDebugHeader GetDebugHeader () - { - if (IsEmbedded) - return new ImageDebugHeader (); - - var directory = new ImageDebugDirectory () { - MajorVersion = 256, - MinorVersion = 20557, - Type = ImageDebugType.CodeView, - TimeDateStamp = (int)module.timestamp, - }; - - var buffer = new ByteBuffer (); - // RSDS - buffer.WriteUInt32 (0x53445352); - // Module ID - buffer.WriteBytes (module.Mvid.ToByteArray ()); - // PDB Age - buffer.WriteUInt32 (1); - // PDB Path - var fileName = writer.BaseStream.GetFileName (); - if (string.IsNullOrEmpty (fileName)) { - fileName = module.Assembly.Name.Name + ".pdb"; - } - buffer.WriteBytes (System.Text.Encoding.UTF8.GetBytes (fileName)); - buffer.WriteByte (0); - - var data = new byte [buffer.length]; - Buffer.BlockCopy (buffer.buffer, 0, data, 0, buffer.length); - directory.SizeOfData = data.Length; - - return new ImageDebugHeader (new ImageDebugHeaderEntry (directory, data)); - } - - public void Write (MethodDebugInformation info) - { - CheckMethodDebugInformationTable (); - - pdb_metadata.AddMethodDebugInformation (info); - } - - void CheckMethodDebugInformationTable () - { - var mdi = pdb_metadata.table_heap.GetTable (Table.MethodDebugInformation); - if (mdi.length > 0) - return; - - // The MethodDebugInformation table has the same length as the Method table - mdi.rows = new Row [module_metadata.method_rid - 1]; - mdi.length = mdi.rows.Length; - } - - public void Dispose () - { - if (IsEmbedded) - return; - - WritePdbFile (); - } - - void WritePdbFile () - { - WritePdbHeap (); - - WriteTableHeap (); - - writer.BuildMetadataTextMap (); - writer.WriteMetadataHeader (); - writer.WriteMetadata (); - - writer.Flush (); - writer.stream.Dispose (); - } - - void WritePdbHeap () - { - var pdb_heap = pdb_metadata.pdb_heap; - - pdb_heap.WriteBytes (module.Mvid.ToByteArray ()); - pdb_heap.WriteUInt32 (module_metadata.timestamp); - - pdb_heap.WriteUInt32 (module_metadata.entry_point.ToUInt32 ()); - - var table_heap = module_metadata.table_heap; - var tables = table_heap.tables; - - ulong valid = 0; - for (int i = 0; i < tables.Length; i++) { - if (tables [i] == null || tables [i].Length == 0) - continue; - - valid |= (1UL << i); - } - - pdb_heap.WriteUInt64 (valid); - - for (int i = 0; i < tables.Length; i++) { - if (tables [i] == null || tables [i].Length == 0) - continue; - - pdb_heap.WriteUInt32 ((uint)tables [i].Length); - } - } - - void WriteTableHeap () - { - pdb_metadata.table_heap.string_offsets = pdb_metadata.string_heap.WriteStrings (); - pdb_metadata.table_heap.ComputeTableInformations (); - pdb_metadata.table_heap.WriteTableHeap (); - } - } - - public sealed class EmbeddedPortablePdbWriterProvider : ISymbolWriterProvider { - - public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName) - { - Mixin.CheckModule (module); - Mixin.CheckFileName (fileName); - - var stream = new MemoryStream (); - var pdb_writer = (PortablePdbWriter)new PortablePdbWriterProvider ().GetSymbolWriter (module, stream); - return new EmbeddedPortablePdbWriter (stream, pdb_writer); - } - - public ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream) - { - throw new NotSupportedException (); - } - } - - public sealed class EmbeddedPortablePdbWriter : ISymbolWriter { - - readonly Stream stream; - readonly PortablePdbWriter writer; - - internal EmbeddedPortablePdbWriter (Stream stream, PortablePdbWriter writer) - { - this.stream = stream; - this.writer = writer; - } - - public ISymbolReaderProvider GetReaderProvider () - { - return new EmbeddedPortablePdbReaderProvider (); - } - - public ImageDebugHeader GetDebugHeader () - { - writer.Dispose (); - - var directory = new ImageDebugDirectory { - Type = ImageDebugType.EmbeddedPortablePdb, - MajorVersion = 0x0100, - MinorVersion = 0x0100, - }; - - var data = new MemoryStream (); - - var w = new BinaryStreamWriter (data); - w.WriteByte (0x4d); - w.WriteByte (0x50); - w.WriteByte (0x44); - w.WriteByte (0x42); - - w.WriteInt32 ((int)stream.Length); - - stream.Position = 0; - - using (var compress_stream = new DeflateStream (data, CompressionMode.Compress, leaveOpen: true)) - stream.CopyTo (compress_stream); - - directory.SizeOfData = (int)data.Length; - - return new ImageDebugHeader (new [] { - writer.GetDebugHeader ().Entries [0], - new ImageDebugHeaderEntry (directory, data.ToArray ()) - }); - } - - public void Write (MethodDebugInformation info) - { - writer.Write (info); - } - - public void Dispose () - { - } - } - - static class PdbGuidMapping { - - static readonly Dictionary guid_language = new Dictionary (); - static readonly Dictionary language_guid = new Dictionary (); - - static PdbGuidMapping () - { - AddMapping (DocumentLanguage.C, new Guid ("63a08714-fc37-11d2-904c-00c04fa302a1")); - AddMapping (DocumentLanguage.Cpp, new Guid ("3a12d0b7-c26c-11d0-b442-00a0244a1dd2")); - AddMapping (DocumentLanguage.CSharp, new Guid ("3f5162f8-07c6-11d3-9053-00c04fa302a1")); - AddMapping (DocumentLanguage.Basic, new Guid ("3a12d0b8-c26c-11d0-b442-00a0244a1dd2")); - AddMapping (DocumentLanguage.Java, new Guid ("3a12d0b4-c26c-11d0-b442-00a0244a1dd2")); - AddMapping (DocumentLanguage.Cobol, new Guid ("af046cd1-d0e1-11d2-977c-00a0c9b4d50c")); - AddMapping (DocumentLanguage.Pascal, new Guid ("af046cd2-d0e1-11d2-977c-00a0c9b4d50c")); - AddMapping (DocumentLanguage.Cil, new Guid ("af046cd3-d0e1-11d2-977c-00a0c9b4d50c")); - AddMapping (DocumentLanguage.JScript, new Guid ("3a12d0b6-c26c-11d0-b442-00a0244a1dd2")); - AddMapping (DocumentLanguage.Smc, new Guid ("0d9b9f7b-6611-11d3-bd2a-0000f80849bd")); - AddMapping (DocumentLanguage.MCpp, new Guid ("4b35fde8-07c6-11d3-9053-00c04fa302a1")); - AddMapping (DocumentLanguage.FSharp, new Guid ("ab4f38c9-b6e6-43ba-be3b-58080b2ccce3")); - } - - static void AddMapping (DocumentLanguage language, Guid guid) - { - guid_language.Add (guid, language); - language_guid.Add (language, guid); - } - - static readonly Guid type_text = new Guid ("5a869d0b-6611-11d3-bd2a-0000f80849bd"); - - public static DocumentType ToType (this Guid guid) - { - if (guid == type_text) - return DocumentType.Text; - - return DocumentType.Other; - } - - public static Guid ToGuid (this DocumentType type) - { - if (type == DocumentType.Text) - return type_text; - - return new Guid (); - } - - static readonly Guid hash_md5 = new Guid ("406ea660-64cf-4c82-b6f0-42d48172a799"); - static readonly Guid hash_sha1 = new Guid ("ff1816ec-aa5e-4d10-87f7-6f4963833460"); - static readonly Guid hash_sha256 = new Guid ("8829d00f-11b8-4213-878b-770e8597ac16"); - - public static DocumentHashAlgorithm ToHashAlgorithm (this Guid guid) - { - if (guid == hash_md5) - return DocumentHashAlgorithm.MD5; - - if (guid == hash_sha1) - return DocumentHashAlgorithm.SHA1; - - if (guid == hash_sha256) - return DocumentHashAlgorithm.SHA256; - - return DocumentHashAlgorithm.None; - } - - public static Guid ToGuid (this DocumentHashAlgorithm hash_algo) - { - if (hash_algo == DocumentHashAlgorithm.MD5) - return hash_md5; - - if (hash_algo == DocumentHashAlgorithm.SHA1) - return hash_sha1; - - if (hash_algo == DocumentHashAlgorithm.SHA256) - return hash_sha256; - - return new Guid (); - } - - public static DocumentLanguage ToLanguage (this Guid guid) - { - DocumentLanguage language; - if (!guid_language.TryGetValue (guid, out language)) - return DocumentLanguage.Other; - - return language; - } - - public static Guid ToGuid (this DocumentLanguage language) - { - Guid guid; - if (!language_guid.TryGetValue (language, out guid)) - return new Guid (); - - return guid; - } - - static readonly Guid vendor_ms = new Guid ("994b45c4-e6e9-11d2-903f-00c04fa302a1"); - - public static DocumentLanguageVendor ToVendor (this Guid guid) - { - if (guid == vendor_ms) - return DocumentLanguageVendor.Microsoft; - - return DocumentLanguageVendor.Other; - } - - public static Guid ToGuid (this DocumentLanguageVendor vendor) - { - if (vendor == DocumentLanguageVendor.Microsoft) - return vendor_ms; - - return new Guid (); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/PortablePdb.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/PortablePdb.cs.meta deleted file mode 100644 index 8b260c9..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/PortablePdb.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 34e2f5d4b9b9ea542bec15f2d9acc3ed -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/SequencePoint.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/SequencePoint.cs deleted file mode 100644 index 591815a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/SequencePoint.cs +++ /dev/null @@ -1,76 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil.Cil { - - public sealed class SequencePoint { - - internal InstructionOffset offset; - Document document; - - int start_line; - int start_column; - int end_line; - int end_column; - - public int Offset { - get { return offset.Offset; } - } - - public int StartLine { - get { return start_line; } - set { start_line = value; } - } - - public int StartColumn { - get { return start_column; } - set { start_column = value; } - } - - public int EndLine { - get { return end_line; } - set { end_line = value; } - } - - public int EndColumn { - get { return end_column; } - set { end_column = value; } - } - - public bool IsHidden { - get { return start_line == 0xfeefee && start_line == end_line; } - } - - public Document Document { - get { return document; } - set { document = value; } - } - - internal SequencePoint (int offset, Document document) - { - if (document == null) - throw new ArgumentNullException ("document"); - - this.offset = new InstructionOffset (offset); - this.document = document; - } - - public SequencePoint (Instruction instruction, Document document) - { - if (document == null) - throw new ArgumentNullException ("document"); - - this.offset = new InstructionOffset (instruction); - this.document = document; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/SequencePoint.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/SequencePoint.cs.meta deleted file mode 100644 index bac78ab..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/SequencePoint.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 612e6675dca63a84b9e8aaeb3e3b9ec6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Symbols.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Symbols.cs deleted file mode 100644 index 4e75a0c..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Symbols.cs +++ /dev/null @@ -1,1226 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Cil; -using MonoFN.Cecil.PE; -using MonoFN.Collections.Generic; -using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime.InteropServices; -using System.Threading; -using SR = System.Reflection; - -namespace MonoFN.Cecil.Cil { - - [StructLayout (LayoutKind.Sequential)] - public struct ImageDebugDirectory { - public const int Size = 28; - - public int Characteristics; - public int TimeDateStamp; - public short MajorVersion; - public short MinorVersion; - public ImageDebugType Type; - public int SizeOfData; - public int AddressOfRawData; - public int PointerToRawData; - } - - public enum ImageDebugType { - CodeView = 2, - Deterministic = 16, - EmbeddedPortablePdb = 17, - } - - public sealed class ImageDebugHeader { - - readonly ImageDebugHeaderEntry [] entries; - - public bool HasEntries { - get { return !entries.IsNullOrEmpty (); } - } - - public ImageDebugHeaderEntry [] Entries { - get { return entries; } - } - - public ImageDebugHeader (ImageDebugHeaderEntry [] entries) - { - this.entries = entries ?? Empty.Array; - } - - public ImageDebugHeader () - : this (Empty.Array) - { - } - - public ImageDebugHeader (ImageDebugHeaderEntry entry) - : this (new [] { entry }) - { - } - } - - public sealed class ImageDebugHeaderEntry { - - ImageDebugDirectory directory; - readonly byte [] data; - - public ImageDebugDirectory Directory { - get { return directory; } - internal set { directory = value; } - } - - public byte [] Data { - get { return data; } - } - - public ImageDebugHeaderEntry (ImageDebugDirectory directory, byte [] data) - { - this.directory = directory; - this.data = data ?? Empty.Array; - } - } - - public sealed class ScopeDebugInformation : DebugInformation { - - internal InstructionOffset start; - internal InstructionOffset end; - internal ImportDebugInformation import; - internal Collection scopes; - internal Collection variables; - internal Collection constants; - - public InstructionOffset Start { - get { return start; } - set { start = value; } - } - - public InstructionOffset End { - get { return end; } - set { end = value; } - } - - public ImportDebugInformation Import { - get { return import; } - set { import = value; } - } - - public bool HasScopes { - get { return !scopes.IsNullOrEmpty (); } - } - - public Collection Scopes { - get { - if (scopes == null) - Interlocked.CompareExchange (ref scopes, new Collection (), null); - - return scopes; - } - } - - public bool HasVariables { - get { return !variables.IsNullOrEmpty (); } - } - - public Collection Variables { - get { - if (variables == null) - Interlocked.CompareExchange (ref variables, new Collection (), null); - - return variables; - } - } - - public bool HasConstants { - get { return !constants.IsNullOrEmpty (); } - } - - public Collection Constants { - get { - if (constants == null) - Interlocked.CompareExchange (ref constants, new Collection (), null); - - return constants; - } - } - - internal ScopeDebugInformation () - { - this.token = new MetadataToken (TokenType.LocalScope); - } - - public ScopeDebugInformation (Instruction start, Instruction end) - : this () - { - if (start == null) - throw new ArgumentNullException ("start"); - - this.start = new InstructionOffset (start); - - if (end != null) - this.end = new InstructionOffset (end); - } - - public bool TryGetName (VariableDefinition variable, out string name) - { - name = null; - if (variables == null || variables.Count == 0) - return false; - - for (int i = 0; i < variables.Count; i++) { - if (variables [i].Index == variable.Index) { - name = variables [i].Name; - return true; - } - } - - return false; - } - } - - public struct InstructionOffset { - - readonly Instruction instruction; - readonly int? offset; - - public int Offset { - get { - if (instruction != null) - return instruction.Offset; - if (offset.HasValue) - return offset.Value; - - throw new NotSupportedException (); - } - } - - public bool IsEndOfMethod { - get { return instruction == null && !offset.HasValue; } - } - - internal bool IsResolved => instruction != null || !offset.HasValue; - - internal Instruction ResolvedInstruction => instruction; - - public InstructionOffset (Instruction instruction) - { - if (instruction == null) - throw new ArgumentNullException ("instruction"); - - this.instruction = instruction; - this.offset = null; - } - - public InstructionOffset (int offset) - { - this.instruction = null; - this.offset = offset; - } - } - - [Flags] - public enum VariableAttributes : ushort { - None = 0, - DebuggerHidden = 1, - } - - public struct VariableIndex { - readonly VariableDefinition variable; - readonly int? index; - - public int Index { - get { - if (variable != null) - return variable.Index; - if (index.HasValue) - return index.Value; - - throw new NotSupportedException (); - } - } - - internal bool IsResolved => variable != null; - - internal VariableDefinition ResolvedVariable => variable; - - public VariableIndex (VariableDefinition variable) - { - if (variable == null) - throw new ArgumentNullException ("variable"); - - this.variable = variable; - this.index = null; - } - - public VariableIndex (int index) - { - this.variable = null; - this.index = index; - } - } - - public abstract class DebugInformation : ICustomDebugInformationProvider { - - internal MetadataToken token; - internal Collection custom_infos; - - public MetadataToken MetadataToken { - get { return token; } - set { token = value; } - } - - public bool HasCustomDebugInformations { - get { return !custom_infos.IsNullOrEmpty (); } - } - - public Collection CustomDebugInformations { - get { - if (custom_infos == null) - Interlocked.CompareExchange (ref custom_infos, new Collection (), null); - - return custom_infos; - } - } - - internal DebugInformation () - { - } - } - - public sealed class VariableDebugInformation : DebugInformation { - - string name; - ushort attributes; - internal VariableIndex index; - - public int Index { - get { return index.Index; } - } - - public string Name { - get { return name; } - set { name = value; } - } - - public VariableAttributes Attributes { - get { return (VariableAttributes)attributes; } - set { attributes = (ushort)value; } - } - - public bool IsDebuggerHidden { - get { return attributes.GetAttributes ((ushort)VariableAttributes.DebuggerHidden); } - set { attributes = attributes.SetAttributes ((ushort)VariableAttributes.DebuggerHidden, value); } - } - - internal VariableDebugInformation (int index, string name) - { - if (name == null) - throw new ArgumentNullException ("name"); - - this.index = new VariableIndex (index); - this.name = name; - } - - public VariableDebugInformation (VariableDefinition variable, string name) - { - if (variable == null) - throw new ArgumentNullException ("variable"); - if (name == null) - throw new ArgumentNullException ("name"); - - this.index = new VariableIndex (variable); - this.name = name; - this.token = new MetadataToken (TokenType.LocalVariable); - } - } - - public sealed class ConstantDebugInformation : DebugInformation { - - string name; - TypeReference constant_type; - object value; - - public string Name { - get { return name; } - set { name = value; } - } - - public TypeReference ConstantType { - get { return constant_type; } - set { constant_type = value; } - } - - public object Value { - get { return value; } - set { this.value = value; } - } - - public ConstantDebugInformation (string name, TypeReference constant_type, object value) - { - if (name == null) - throw new ArgumentNullException ("name"); - - this.name = name; - this.constant_type = constant_type; - this.value = value; - this.token = new MetadataToken (TokenType.LocalConstant); - } - } - - public enum ImportTargetKind : byte { - ImportNamespace = 1, - ImportNamespaceInAssembly = 2, - ImportType = 3, - ImportXmlNamespaceWithAlias = 4, - ImportAlias = 5, - DefineAssemblyAlias = 6, - DefineNamespaceAlias = 7, - DefineNamespaceInAssemblyAlias = 8, - DefineTypeAlias = 9, - } - - public sealed class ImportTarget { - - internal ImportTargetKind kind; - - internal string @namespace; - internal TypeReference type; - internal AssemblyNameReference reference; - internal string alias; - - public string Namespace { - get { return @namespace; } - set { @namespace = value; } - } - - public TypeReference Type { - get { return type; } - set { type = value; } - } - - public AssemblyNameReference AssemblyReference { - get { return reference; } - set { reference = value; } - } - - public string Alias { - get { return alias; } - set { alias = value; } - } - - public ImportTargetKind Kind { - get { return kind; } - set { kind = value; } - } - - public ImportTarget (ImportTargetKind kind) - { - this.kind = kind; - } - } - - public sealed class ImportDebugInformation : DebugInformation { - - internal ImportDebugInformation parent; - internal Collection targets; - - public bool HasTargets { - get { return !targets.IsNullOrEmpty (); } - } - - public Collection Targets { - get { - if (targets == null) - Interlocked.CompareExchange (ref targets, new Collection (), null); - - return targets; - } - } - - public ImportDebugInformation Parent { - get { return parent; } - set { parent = value; } - } - - public ImportDebugInformation () - { - this.token = new MetadataToken (TokenType.ImportScope); - } - } - - public interface ICustomDebugInformationProvider : IMetadataTokenProvider { - bool HasCustomDebugInformations { get; } - Collection CustomDebugInformations { get; } - } - - public enum CustomDebugInformationKind { - Binary, - StateMachineScope, - DynamicVariable, - DefaultNamespace, - AsyncMethodBody, - EmbeddedSource, - SourceLink, - } - - public abstract class CustomDebugInformation : DebugInformation { - - Guid identifier; - - public Guid Identifier { - get { return identifier; } - } - - public abstract CustomDebugInformationKind Kind { get; } - - internal CustomDebugInformation (Guid identifier) - { - this.identifier = identifier; - this.token = new MetadataToken (TokenType.CustomDebugInformation); - } - } - - public sealed class BinaryCustomDebugInformation : CustomDebugInformation { - - byte [] data; - - public byte [] Data { - get { return data; } - set { data = value; } - } - - public override CustomDebugInformationKind Kind { - get { return CustomDebugInformationKind.Binary; } - } - - public BinaryCustomDebugInformation (Guid identifier, byte [] data) - : base (identifier) - { - this.data = data; - } - } - - public sealed class AsyncMethodBodyDebugInformation : CustomDebugInformation { - - internal InstructionOffset catch_handler; - internal Collection yields; - internal Collection resumes; - internal Collection resume_methods; - - public InstructionOffset CatchHandler { - get { return catch_handler; } - set { catch_handler = value; } - } - - public Collection Yields { - get { - if (yields == null) - Interlocked.CompareExchange (ref yields, new Collection (), null); - - return yields; - } - } - - public Collection Resumes { - get { - if (resumes == null) - Interlocked.CompareExchange (ref resumes, new Collection (), null); - - return resumes; - } - } - - public Collection ResumeMethods { - get { return resume_methods ?? (resume_methods = new Collection ()); } - } - - public override CustomDebugInformationKind Kind { - get { return CustomDebugInformationKind.AsyncMethodBody; } - } - - public static Guid KindIdentifier = new Guid ("{54FD2AC5-E925-401A-9C2A-F94F171072F8}"); - - internal AsyncMethodBodyDebugInformation (int catchHandler) - : base (KindIdentifier) - { - this.catch_handler = new InstructionOffset (catchHandler); - } - - public AsyncMethodBodyDebugInformation (Instruction catchHandler) - : base (KindIdentifier) - { - this.catch_handler = new InstructionOffset (catchHandler); - } - - public AsyncMethodBodyDebugInformation () - : base (KindIdentifier) - { - this.catch_handler = new InstructionOffset (-1); - } - } - - public sealed class StateMachineScope { - - internal InstructionOffset start; - internal InstructionOffset end; - - public InstructionOffset Start { - get { return start; } - set { start = value; } - } - - public InstructionOffset End { - get { return end; } - set { end = value; } - } - - internal StateMachineScope (int start, int end) - { - this.start = new InstructionOffset (start); - this.end = new InstructionOffset (end); - } - - public StateMachineScope (Instruction start, Instruction end) - { - this.start = new InstructionOffset (start); - this.end = end != null ? new InstructionOffset (end) : new InstructionOffset (); - } - } - - public sealed class StateMachineScopeDebugInformation : CustomDebugInformation { - - internal Collection scopes; - - public Collection Scopes { - get { return scopes ?? (scopes = new Collection ()); } - } - - public override CustomDebugInformationKind Kind { - get { return CustomDebugInformationKind.StateMachineScope; } - } - - public static Guid KindIdentifier = new Guid ("{6DA9A61E-F8C7-4874-BE62-68BC5630DF71}"); - - public StateMachineScopeDebugInformation () - : base (KindIdentifier) - { - } - } - - public sealed class EmbeddedSourceDebugInformation : CustomDebugInformation { - - internal uint index; - internal MetadataReader debug_reader; - internal bool resolved; - internal byte [] content; - internal bool compress; - - public byte [] Content { - get { - if (!resolved) - Resolve (); - - return content; - } - set { - content = value; - resolved = true; - } - } - - public bool Compress { - get { - if (!resolved) - Resolve (); - - return compress; - } - set { - compress = value; - resolved = true; - } - } - - public override CustomDebugInformationKind Kind { - get { return CustomDebugInformationKind.EmbeddedSource; } - } - - public static Guid KindIdentifier = new Guid ("{0E8A571B-6926-466E-B4AD-8AB04611F5FE}"); - - internal EmbeddedSourceDebugInformation (uint index, MetadataReader debug_reader) - : base (KindIdentifier) - { - this.index = index; - this.debug_reader = debug_reader; - } - - public EmbeddedSourceDebugInformation (byte [] content, bool compress) - : base (KindIdentifier) - { - this.resolved = true; - this.content = content; - this.compress = compress; - } - - internal byte [] ReadRawEmbeddedSourceDebugInformation () - { - if (debug_reader == null) - throw new InvalidOperationException (); - - return debug_reader.ReadRawEmbeddedSourceDebugInformation (index); - } - - void Resolve () - { - if (resolved) - return; - - if (debug_reader == null) - throw new InvalidOperationException (); - - var row = debug_reader.ReadEmbeddedSourceDebugInformation (index); - content = row.Col1; - compress = row.Col2; - resolved = true; - } - } - - public sealed class SourceLinkDebugInformation : CustomDebugInformation { - - internal string content; - - public string Content { - get { return content; } - set { content = value; } - } - - public override CustomDebugInformationKind Kind { - get { return CustomDebugInformationKind.SourceLink; } - } - - public static Guid KindIdentifier = new Guid ("{CC110556-A091-4D38-9FEC-25AB9A351A6A}"); - - public SourceLinkDebugInformation (string content) - : base (KindIdentifier) - { - this.content = content; - } - } - - public sealed class MethodDebugInformation : DebugInformation { - - internal MethodDefinition method; - internal Collection sequence_points; - internal ScopeDebugInformation scope; - internal MethodDefinition kickoff_method; - internal int code_size; - internal MetadataToken local_var_token; - - public MethodDefinition Method { - get { return method; } - } - - public bool HasSequencePoints { - get { return !sequence_points.IsNullOrEmpty (); } - } - - public Collection SequencePoints { - get { - if (sequence_points == null) - Interlocked.CompareExchange (ref sequence_points, new Collection (), null); - - return sequence_points; - } - } - - public ScopeDebugInformation Scope { - get { return scope; } - set { scope = value; } - } - - public MethodDefinition StateMachineKickOffMethod { - get { return kickoff_method; } - set { kickoff_method = value; } - } - - internal MethodDebugInformation (MethodDefinition method) - { - if (method == null) - throw new ArgumentNullException ("method"); - - this.method = method; - this.token = new MetadataToken (TokenType.MethodDebugInformation, method.MetadataToken.RID); - } - - public SequencePoint GetSequencePoint (Instruction instruction) - { - if (!HasSequencePoints) - return null; - - for (int i = 0; i < sequence_points.Count; i++) - if (sequence_points [i].Offset == instruction.Offset) - return sequence_points [i]; - - return null; - } - - public IDictionary GetSequencePointMapping () - { - var instruction_mapping = new Dictionary (); - if (!HasSequencePoints || !method.HasBody) - return instruction_mapping; - - var offset_mapping = new Dictionary (sequence_points.Count); - - for (int i = 0; i < sequence_points.Count; i++) { - if (!offset_mapping.ContainsKey (sequence_points [i].Offset)) - offset_mapping.Add (sequence_points [i].Offset, sequence_points [i]); - } - - var instructions = method.Body.Instructions; - - for (int i = 0; i < instructions.Count; i++) { - SequencePoint sequence_point; - if (offset_mapping.TryGetValue (instructions [i].Offset, out sequence_point)) - instruction_mapping.Add (instructions [i], sequence_point); - } - - return instruction_mapping; - } - - public IEnumerable GetScopes () - { - if (scope == null) - return Empty.Array; - - return GetScopes (new [] { scope }); - } - - static IEnumerable GetScopes (IList scopes) - { - for (int i = 0; i < scopes.Count; i++) { - var scope = scopes [i]; - - yield return scope; - - if (!scope.HasScopes) - continue; - - foreach (var sub_scope in GetScopes (scope.Scopes)) - yield return sub_scope; - } - } - - public bool TryGetName (VariableDefinition variable, out string name) - { - name = null; - - var has_name = false; - var unique_name = ""; - - foreach (var scope in GetScopes ()) { - string slot_name; - if (!scope.TryGetName (variable, out slot_name)) - continue; - - if (!has_name) { - has_name = true; - unique_name = slot_name; - continue; - } - - if (unique_name != slot_name) - return false; - } - - name = unique_name; - return has_name; - } - } - - public interface ISymbolReader : IDisposable { - - ISymbolWriterProvider GetWriterProvider (); - bool ProcessDebugHeader (ImageDebugHeader header); - MethodDebugInformation Read (MethodDefinition method); - } - - public interface ISymbolReaderProvider { - ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName); - ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream); - } - -#if !NET_CORE - [Serializable] -#endif - public sealed class SymbolsNotFoundException : FileNotFoundException { - - public SymbolsNotFoundException (string message) : base (message) - { - } - -#if !NET_CORE - SymbolsNotFoundException ( - System.Runtime.Serialization.SerializationInfo info, - System.Runtime.Serialization.StreamingContext context) - : base (info, context) - { - } -#endif - } - -#if !NET_CORE - [Serializable] -#endif - public sealed class SymbolsNotMatchingException : InvalidOperationException { - - public SymbolsNotMatchingException (string message) : base (message) - { - } - -#if !NET_CORE - SymbolsNotMatchingException ( - System.Runtime.Serialization.SerializationInfo info, - System.Runtime.Serialization.StreamingContext context) - : base (info, context) - { - } -#endif - } - - public class DefaultSymbolReaderProvider : ISymbolReaderProvider { - - readonly bool throw_if_no_symbol; - - public DefaultSymbolReaderProvider () - : this (throwIfNoSymbol: true) - { - } - - public DefaultSymbolReaderProvider (bool throwIfNoSymbol) - { - throw_if_no_symbol = throwIfNoSymbol; - } - - public ISymbolReader GetSymbolReader (ModuleDefinition module, string fileName) - { - if (module.Image.HasDebugTables ()) - return null; - - if (module.HasDebugHeader) { - var header = module.GetDebugHeader (); - var entry = header.GetEmbeddedPortablePdbEntry (); - if (entry != null) - return new EmbeddedPortablePdbReaderProvider ().GetSymbolReader (module, fileName); - } - - var pdb_file_name = Mixin.GetPdbFileName (fileName); - - if (File.Exists (pdb_file_name)) { - if (Mixin.IsPortablePdb (Mixin.GetPdbFileName (fileName))) - return new PortablePdbReaderProvider ().GetSymbolReader (module, fileName); - - try { - return SymbolProvider.GetReaderProvider (SymbolKind.NativePdb).GetSymbolReader (module, fileName); - } - catch (Exception) { - // We might not include support for native pdbs. - } - } - - var mdb_file_name = Mixin.GetMdbFileName (fileName); - if (File.Exists (mdb_file_name)) { - try { - return SymbolProvider.GetReaderProvider (SymbolKind.Mdb).GetSymbolReader (module, fileName); - } - catch (Exception) { - // We might not include support for mdbs. - } - } - - if (throw_if_no_symbol) - throw new SymbolsNotFoundException (string.Format ("No symbol found for file: {0}", fileName)); - - return null; - } - - public ISymbolReader GetSymbolReader (ModuleDefinition module, Stream symbolStream) - { - if (module.Image.HasDebugTables ()) - return null; - - if (module.HasDebugHeader) { - var header = module.GetDebugHeader (); - var entry = header.GetEmbeddedPortablePdbEntry (); - if (entry != null) - return new EmbeddedPortablePdbReaderProvider ().GetSymbolReader (module, ""); - } - - Mixin.CheckStream (symbolStream); - Mixin.CheckReadSeek (symbolStream); - - var position = symbolStream.Position; - - const int portablePdbHeader = 0x424a5342; - - var reader = new BinaryStreamReader (symbolStream); - var intHeader = reader.ReadInt32 (); - symbolStream.Position = position; - - if (intHeader == portablePdbHeader) { - return new PortablePdbReaderProvider ().GetSymbolReader (module, symbolStream); - } - - const string nativePdbHeader = "Microsoft C/C++ MSF 7.00"; - - var bytesHeader = reader.ReadBytes (nativePdbHeader.Length); - symbolStream.Position = position; - var isNativePdb = true; - - for (var i = 0; i < bytesHeader.Length; i++) { - if (bytesHeader [i] != (byte)nativePdbHeader [i]) { - isNativePdb = false; - break; - } - } - - if (isNativePdb) { - try { - return SymbolProvider.GetReaderProvider (SymbolKind.NativePdb).GetSymbolReader (module, symbolStream); - } - catch (Exception) { - // We might not include support for native pdbs. - } - } - - const long mdbHeader = 0x45e82623fd7fa614; - - var longHeader = reader.ReadInt64 (); - symbolStream.Position = position; - - if (longHeader == mdbHeader) { - try { - return SymbolProvider.GetReaderProvider (SymbolKind.Mdb).GetSymbolReader (module, symbolStream); - } - catch (Exception) { - // We might not include support for mdbs. - } - } - - if (throw_if_no_symbol) - throw new SymbolsNotFoundException (string.Format ("No symbols found in stream")); - - return null; - } - } - - enum SymbolKind { - NativePdb, - PortablePdb, - EmbeddedPortablePdb, - Mdb, - } - - static class SymbolProvider { - - static SR.AssemblyName GetSymbolAssemblyName (SymbolKind kind) - { - if (kind == SymbolKind.PortablePdb) - throw new ArgumentException (); - - var suffix = GetSymbolNamespace (kind); - - var cecil_name = typeof (SymbolProvider).Assembly.GetName (); - - var name = new SR.AssemblyName { - Name = cecil_name.Name + "." + suffix, - Version = cecil_name.Version, -#if NET_CORE - CultureName = cecil_name.CultureName, -#else - CultureInfo = cecil_name.CultureInfo, -#endif - }; - - name.SetPublicKeyToken (cecil_name.GetPublicKeyToken ()); - - return name; - } - - static Type GetSymbolType (SymbolKind kind, string fullname) - { - var type = Type.GetType (fullname); - if (type != null) - return type; - - var assembly_name = GetSymbolAssemblyName (kind); - - type = Type.GetType (fullname + ", " + assembly_name.FullName); - if (type != null) - return type; - - try { - var assembly = SR.Assembly.Load (assembly_name); - if (assembly != null) - return assembly.GetType (fullname); - } - catch (FileNotFoundException) { - } - catch (FileLoadException) { - } - - return null; - } - - public static ISymbolReaderProvider GetReaderProvider (SymbolKind kind) - { - if (kind == SymbolKind.PortablePdb) - return new PortablePdbReaderProvider (); - if (kind == SymbolKind.EmbeddedPortablePdb) - return new EmbeddedPortablePdbReaderProvider (); - - var provider_name = GetSymbolTypeName (kind, "ReaderProvider"); - var type = GetSymbolType (kind, provider_name); - if (type == null) - throw new TypeLoadException ("Could not find symbol provider type " + provider_name); - - return (ISymbolReaderProvider)Activator.CreateInstance (type); - } - - static string GetSymbolTypeName (SymbolKind kind, string name) - { - return "MonoFN.Cecil" + "." + GetSymbolNamespace (kind) + "." + kind + name; - } - - static string GetSymbolNamespace (SymbolKind kind) - { - if (kind == SymbolKind.PortablePdb || kind == SymbolKind.EmbeddedPortablePdb) - return "Cil"; - if (kind == SymbolKind.NativePdb) - return "Pdb"; - if (kind == SymbolKind.Mdb) - return "Mdb"; - - throw new ArgumentException (); - } - } - - public interface ISymbolWriter : IDisposable { - - ISymbolReaderProvider GetReaderProvider (); - ImageDebugHeader GetDebugHeader (); - void Write (MethodDebugInformation info); - } - - public interface ISymbolWriterProvider { - - ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName); - ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream); - } - - public class DefaultSymbolWriterProvider : ISymbolWriterProvider { - - public ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fileName) - { - var reader = module.SymbolReader; - if (reader == null) - throw new InvalidOperationException (); - - if (module.Image != null && module.Image.HasDebugTables ()) - return null; - - return reader.GetWriterProvider ().GetSymbolWriter (module, fileName); - } - - public ISymbolWriter GetSymbolWriter (ModuleDefinition module, Stream symbolStream) - { - throw new NotSupportedException (); - } - } -} - -namespace MonoFN.Cecil { - - static partial class Mixin { - - public static ImageDebugHeaderEntry GetCodeViewEntry (this ImageDebugHeader header) - { - return GetEntry (header, ImageDebugType.CodeView); - } - - public static ImageDebugHeaderEntry GetDeterministicEntry (this ImageDebugHeader header) - { - return GetEntry (header, ImageDebugType.Deterministic); - } - - public static ImageDebugHeader AddDeterministicEntry (this ImageDebugHeader header) - { - var entry = new ImageDebugHeaderEntry (new ImageDebugDirectory { Type = ImageDebugType.Deterministic }, Empty.Array); - if (header == null) - return new ImageDebugHeader (entry); - - var entries = new ImageDebugHeaderEntry [header.Entries.Length + 1]; - Array.Copy (header.Entries, entries, header.Entries.Length); - entries [entries.Length - 1] = entry; - return new ImageDebugHeader (entries); - } - - public static ImageDebugHeaderEntry GetEmbeddedPortablePdbEntry (this ImageDebugHeader header) - { - return GetEntry (header, ImageDebugType.EmbeddedPortablePdb); - } - - private static ImageDebugHeaderEntry GetEntry (this ImageDebugHeader header, ImageDebugType type) - { - if (!header.HasEntries) - return null; - - for (var i = 0; i < header.Entries.Length; i++) { - var entry = header.Entries [i]; - if (entry.Directory.Type == type) - return entry; - } - - return null; - } - - public static string GetPdbFileName (string assemblyFileName) - { - return Path.ChangeExtension (assemblyFileName, ".pdb"); - } - - public static string GetMdbFileName (string assemblyFileName) - { - return assemblyFileName + ".mdb"; - } - - public static bool IsPortablePdb (string fileName) - { - using (var file = new FileStream (fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - return IsPortablePdb (file); - } - - public static bool IsPortablePdb (Stream stream) - { - const uint ppdb_signature = 0x424a5342; - - if (stream.Length < 4) return false; - var position = stream.Position; - try { - var reader = new BinaryReader (stream); - return reader.ReadUInt32 () == ppdb_signature; - } - finally { - stream.Position = position; - } - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Symbols.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Symbols.cs.meta deleted file mode 100644 index f82ee9b..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/Symbols.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: de9ae158807f471449a81d9b8b3e3c4e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableDefinition.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableDefinition.cs deleted file mode 100644 index b3da0a2..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableDefinition.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil.Cil { - - public sealed class VariableDefinition : VariableReference { - - public bool IsPinned { - get { return variable_type.IsPinned; } - } - - public VariableDefinition (TypeReference variableType) - : base (variableType) - { - } - - public override VariableDefinition Resolve () - { - return this; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableDefinition.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableDefinition.cs.meta deleted file mode 100644 index b4e1886..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableDefinition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1346fa5ba8ac9e8418cc20d2d7d0ad21 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableReference.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableReference.cs deleted file mode 100644 index 1957d8d..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableReference.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil.Cil { - - public abstract class VariableReference { - - internal int index = -1; - protected TypeReference variable_type; - - public TypeReference VariableType { - get { return variable_type; } - set { variable_type = value; } - } - - public int Index { - get { return index; } - } - - internal VariableReference (TypeReference variable_type) - { - this.variable_type = variable_type; - } - - public abstract VariableDefinition Resolve (); - - public override string ToString () - { - if (index >= 0) - return "V_" + index; - - return string.Empty; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableReference.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableReference.cs.meta deleted file mode 100644 index e951cc3..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Cil/VariableReference.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b5dca1eaac23bfd4ba8e881302a72e33 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata.meta deleted file mode 100644 index 8b4cde1..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 8b0e9c3e91af12a4db473e2b25f2d8bd -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/BlobHeap.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/BlobHeap.cs deleted file mode 100644 index 63dcd4d..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/BlobHeap.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil.Metadata { - - sealed class BlobHeap : Heap { - - public BlobHeap (byte [] data) - : base (data) - { - } - - public byte [] Read (uint index) - { - if (index == 0 || index > this.data.Length - 1) - return Empty.Array; - - int position = (int)index; - int length = (int)data.ReadCompressedUInt32 (ref position); - - if (length > data.Length - position) - return Empty.Array; - - var buffer = new byte [length]; - - Buffer.BlockCopy (data, position, buffer, 0, length); - - return buffer; - } - - public void GetView (uint signature, out byte [] buffer, out int index, out int length) - { - if (signature == 0 || signature > data.Length - 1) { - buffer = null; - index = length = 0; - return; - } - - buffer = data; - - index = (int)signature; - length = (int)buffer.ReadCompressedUInt32 (ref index); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/BlobHeap.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/BlobHeap.cs.meta deleted file mode 100644 index b6ef813..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/BlobHeap.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 33eef67f4a74e1c40a6bdb3da9d22d00 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Buffers.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Buffers.cs deleted file mode 100644 index 7ab352c..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Buffers.cs +++ /dev/null @@ -1,499 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.PE; -using System; -using System.Collections.Generic; -using System.Text; -using RVA = System.UInt32; - -namespace MonoFN.Cecil.Metadata { - - sealed class TableHeapBuffer : HeapBuffer { - - readonly ModuleDefinition module; - readonly MetadataBuilder metadata; - - readonly internal TableInformation [] table_infos = new TableInformation [Mixin.TableCount]; - readonly internal MetadataTable [] tables = new MetadataTable [Mixin.TableCount]; - - bool large_string; - bool large_blob; - bool large_guid; - - readonly int [] coded_index_sizes = new int [Mixin.CodedIndexCount]; - readonly Func counter; - - internal uint [] string_offsets; - - public override bool IsEmpty { - get { return false; } - } - - public TableHeapBuffer (ModuleDefinition module, MetadataBuilder metadata) - : base (24) - { - this.module = module; - this.metadata = metadata; - this.counter = GetTableLength; - } - - int GetTableLength (Table table) - { - return (int)table_infos [(int)table].Length; - } - - public TTable GetTable (Table table) where TTable : MetadataTable, new() - { - var md_table = (TTable)tables [(int)table]; - if (md_table != null) - return md_table; - - md_table = new TTable (); - tables [(int)table] = md_table; - return md_table; - } - - public void WriteBySize (uint value, int size) - { - if (size == 4) - WriteUInt32 (value); - else - WriteUInt16 ((ushort)value); - } - - public void WriteBySize (uint value, bool large) - { - if (large) - WriteUInt32 (value); - else - WriteUInt16 ((ushort)value); - } - - public void WriteString (uint @string) - { - WriteBySize (string_offsets [@string], large_string); - } - - public void WriteBlob (uint blob) - { - WriteBySize (blob, large_blob); - } - - public void WriteGuid (uint guid) - { - WriteBySize (guid, large_guid); - } - - public void WriteRID (uint rid, Table table) - { - WriteBySize (rid, table_infos [(int)table].IsLarge); - } - - int GetCodedIndexSize (CodedIndex coded_index) - { - var index = (int)coded_index; - var size = coded_index_sizes [index]; - if (size != 0) - return size; - - return coded_index_sizes [index] = coded_index.GetSize (counter); - } - - public void WriteCodedRID (uint rid, CodedIndex coded_index) - { - WriteBySize (rid, GetCodedIndexSize (coded_index)); - } - - public void WriteTableHeap () - { - WriteUInt32 (0); // Reserved - WriteByte (GetTableHeapVersion ()); // MajorVersion - WriteByte (0); // MinorVersion - WriteByte (GetHeapSizes ()); // HeapSizes - WriteByte (10); // Reserved2 - WriteUInt64 (GetValid ()); // Valid - WriteUInt64 (0xc416003301fa00); // Sorted - - WriteRowCount (); - WriteTables (); - } - - void WriteRowCount () - { - for (int i = 0; i < tables.Length; i++) { - var table = tables [i]; - if (table == null || table.Length == 0) - continue; - - WriteUInt32 ((uint)table.Length); - } - } - - void WriteTables () - { - for (int i = 0; i < tables.Length; i++) { - var table = tables [i]; - if (table == null || table.Length == 0) - continue; - - table.Write (this); - } - } - - ulong GetValid () - { - ulong valid = 0; - - for (int i = 0; i < tables.Length; i++) { - var table = tables [i]; - if (table == null || table.Length == 0) - continue; - - table.Sort (); - valid |= (1UL << i); - } - - return valid; - } - - public void ComputeTableInformations () - { - if (metadata.metadata_builder != null) - ComputeTableInformations (metadata.metadata_builder.table_heap); - - ComputeTableInformations (metadata.table_heap); - } - - void ComputeTableInformations (TableHeapBuffer table_heap) - { - var tables = table_heap.tables; - for (int i = 0; i < tables.Length; i++) { - var table = tables [i]; - if (table != null && table.Length > 0) - table_infos [i].Length = (uint)table.Length; - } - } - - byte GetHeapSizes () - { - byte heap_sizes = 0; - - if (metadata.string_heap.IsLarge) { - large_string = true; - heap_sizes |= 0x01; - } - - if (metadata.guid_heap.IsLarge) { - large_guid = true; - heap_sizes |= 0x02; - } - - if (metadata.blob_heap.IsLarge) { - large_blob = true; - heap_sizes |= 0x04; - } - - return heap_sizes; - } - - byte GetTableHeapVersion () - { - switch (module.Runtime) { - case TargetRuntime.Net_1_0: - case TargetRuntime.Net_1_1: - return 1; - default: - return 2; - } - } - - public void FixupData (RVA data_rva) - { - var table = GetTable (Table.FieldRVA); - if (table.length == 0) - return; - - var field_idx_size = GetTable (Table.Field).IsLarge ? 4 : 2; - var previous = this.position; - - base.position = table.position; - for (int i = 0; i < table.length; i++) { - var rva = ReadUInt32 (); - base.position -= 4; - WriteUInt32 (rva + data_rva); - base.position += field_idx_size; - } - - base.position = previous; - } - } - - sealed class ResourceBuffer : ByteBuffer { - - public ResourceBuffer () - : base (0) - { - } - - public uint AddResource (byte [] resource) - { - var offset = (uint)this.position; - WriteInt32 (resource.Length); - WriteBytes (resource); - return offset; - } - } - - sealed class DataBuffer : ByteBuffer { - - public DataBuffer () - : base (0) - { - } - - public RVA AddData (byte [] data) - { - var rva = (RVA)position; - WriteBytes (data); - return rva; - } - } - - abstract class HeapBuffer : ByteBuffer { - - public bool IsLarge { - get { return base.length > 65535; } - } - - public abstract bool IsEmpty { get; } - - protected HeapBuffer (int length) - : base (length) - { - } - } - - sealed class GuidHeapBuffer : HeapBuffer { - - readonly Dictionary guids = new Dictionary (); - - public override bool IsEmpty { - get { return length == 0; } - } - - public GuidHeapBuffer () - : base (16) - { - } - - public uint GetGuidIndex (Guid guid) - { - uint index; - if (guids.TryGetValue (guid, out index)) - return index; - - index = (uint)guids.Count + 1; - WriteGuid (guid); - guids.Add (guid, index); - return index; - } - - void WriteGuid (Guid guid) - { - WriteBytes (guid.ToByteArray ()); - } - } - - class StringHeapBuffer : HeapBuffer { - - protected Dictionary strings = new Dictionary (StringComparer.Ordinal); - - public sealed override bool IsEmpty { - get { return length <= 1; } - } - - public StringHeapBuffer () - : base (1) - { - WriteByte (0); - } - - public virtual uint GetStringIndex (string @string) - { - uint index; - if (strings.TryGetValue (@string, out index)) - return index; - - index = (uint)strings.Count + 1; - strings.Add (@string, index); - return index; - } - - public uint [] WriteStrings () - { - var sorted = SortStrings (strings); - strings = null; - - // Add 1 for empty string whose index and offset are both 0 - var string_offsets = new uint [sorted.Count + 1]; - string_offsets [0] = 0; - - // Find strings that can be folded - var previous = string.Empty; - foreach (var entry in sorted) { - var @string = entry.Key; - var index = entry.Value; - var position = base.position; - - if (previous.EndsWith (@string, StringComparison.Ordinal) && !IsLowSurrogateChar (entry.Key [0])) { - // Map over the tail of prev string. Watch for null-terminator of prev string. - string_offsets [index] = (uint)(position - (Encoding.UTF8.GetByteCount (entry.Key) + 1)); - } else { - string_offsets [index] = (uint)position; - WriteString (@string); - } - - previous = entry.Key; - } - - return string_offsets; - } - - static List> SortStrings (Dictionary strings) - { - var sorted = new List> (strings); - sorted.Sort (new SuffixSort ()); - return sorted; - } - - static bool IsLowSurrogateChar (int c) - { - return unchecked((uint)(c - 0xDC00)) <= 0xDFFF - 0xDC00; - } - - protected virtual void WriteString (string @string) - { - WriteBytes (Encoding.UTF8.GetBytes (@string)); - WriteByte (0); - } - - // Sorts strings such that a string is followed immediately by all strings - // that are a suffix of it. - private class SuffixSort : IComparer> { - - public int Compare (KeyValuePair xPair, KeyValuePair yPair) - { - var x = xPair.Key; - var y = yPair.Key; - - for (int i = x.Length - 1, j = y.Length - 1; i >= 0 & j >= 0; i--, j--) { - if (x [i] < y [j]) { - return -1; - } - - if (x [i] > y [j]) { - return +1; - } - } - - return y.Length.CompareTo (x.Length); - } - } - } - - sealed class BlobHeapBuffer : HeapBuffer { - - readonly Dictionary blobs = new Dictionary (new ByteBufferEqualityComparer ()); - - public override bool IsEmpty { - get { return length <= 1; } - } - - public BlobHeapBuffer () - : base (1) - { - WriteByte (0); - } - - public uint GetBlobIndex (ByteBuffer blob) - { - uint index; - if (blobs.TryGetValue (blob, out index)) - return index; - - index = (uint)base.position; - WriteBlob (blob); - blobs.Add (blob, index); - return index; - } - - void WriteBlob (ByteBuffer blob) - { - WriteCompressedUInt32 ((uint)blob.length); - WriteBytes (blob); - } - } - - sealed class UserStringHeapBuffer : StringHeapBuffer { - - public override uint GetStringIndex (string @string) - { - uint index; - if (strings.TryGetValue (@string, out index)) - return index; - - index = (uint)base.position; - WriteString (@string); - strings.Add (@string, index); - return index; - } - - protected override void WriteString (string @string) - { - WriteCompressedUInt32 ((uint)@string.Length * 2 + 1); - - byte special = 0; - - for (int i = 0; i < @string.Length; i++) { - var @char = @string [i]; - WriteUInt16 (@char); - - if (special == 1) - continue; - - if (@char < 0x20 || @char > 0x7e) { - if (@char > 0x7e - || (@char >= 0x01 && @char <= 0x08) - || (@char >= 0x0e && @char <= 0x1f) - || @char == 0x27 - || @char == 0x2d) { - - special = 1; - } - } - } - - WriteByte (special); - } - } - - sealed class PdbHeapBuffer : HeapBuffer { - - public override bool IsEmpty { - get { return false; } - } - - public PdbHeapBuffer () - : base (0) - { - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Buffers.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Buffers.cs.meta deleted file mode 100644 index 480046a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Buffers.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4b1d0a81b66e78341ab77acdd3b15234 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/CodedIndex.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/CodedIndex.cs deleted file mode 100644 index 601a347..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/CodedIndex.cs +++ /dev/null @@ -1,29 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil.Metadata { - - enum CodedIndex { - TypeDefOrRef, - HasConstant, - HasCustomAttribute, - HasFieldMarshal, - HasDeclSecurity, - MemberRefParent, - HasSemantics, - MethodDefOrRef, - MemberForwarded, - Implementation, - CustomAttributeType, - ResolutionScope, - TypeOrMethodDef, - HasCustomDebugInformation, - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/CodedIndex.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/CodedIndex.cs.meta deleted file mode 100644 index 553ef4d..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/CodedIndex.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: dd50ffa8272dac444831e33b1b9d7f56 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/ElementType.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/ElementType.cs deleted file mode 100644 index 8351286..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/ElementType.cs +++ /dev/null @@ -1,55 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil.Metadata { - - enum ElementType : byte { - None = 0x00, - Void = 0x01, - Boolean = 0x02, - Char = 0x03, - I1 = 0x04, - U1 = 0x05, - I2 = 0x06, - U2 = 0x07, - I4 = 0x08, - U4 = 0x09, - I8 = 0x0a, - U8 = 0x0b, - R4 = 0x0c, - R8 = 0x0d, - String = 0x0e, - Ptr = 0x0f, // Followed by token - ByRef = 0x10, // Followed by token - ValueType = 0x11, // Followed by token - Class = 0x12, // Followed by token - Var = 0x13, // Followed by generic parameter number - Array = 0x14, // - GenericInst = 0x15, // ... */ - TypedByRef = 0x16, - I = 0x18, // System.IntPtr - U = 0x19, // System.UIntPtr - FnPtr = 0x1b, // Followed by full method signature - Object = 0x1c, // System.Object - SzArray = 0x1d, // Single-dim array with 0 lower bound - MVar = 0x1e, // Followed by generic parameter number - CModReqD = 0x1f, // Required modifier : followed by a TypeDef or TypeRef token - CModOpt = 0x20, // Optional modifier : followed by a TypeDef or TypeRef token - Internal = 0x21, // Implemented within the CLI - Modifier = 0x40, // Or'd with following element types - Sentinel = 0x41, // Sentinel for varargs method signature - Pinned = 0x45, // Denotes a local variable that points at a pinned object - - // special undocumented constants - Type = 0x50, - Boxed = 0x51, - Enum = 0x55 - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/ElementType.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/ElementType.cs.meta deleted file mode 100644 index 58173f6..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/ElementType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 94c4cb498ef60034d83bb60d3f743832 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/GuidHeap.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/GuidHeap.cs deleted file mode 100644 index ec9c644..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/GuidHeap.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil.Metadata { - - sealed class GuidHeap : Heap { - - public GuidHeap (byte [] data) - : base (data) - { - } - - public Guid Read (uint index) - { - const int guid_size = 16; - - if (index == 0 || ((index - 1) + guid_size) > data.Length) - return new Guid (); - - var buffer = new byte [guid_size]; - - Buffer.BlockCopy (this.data, (int)((index - 1) * guid_size), buffer, 0, guid_size); - - return new Guid (buffer); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/GuidHeap.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/GuidHeap.cs.meta deleted file mode 100644 index eaabe77..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/GuidHeap.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4bb39ab6484eb114b91a85d4b53f0f28 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Heap.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Heap.cs deleted file mode 100644 index 3cbb026..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Heap.cs +++ /dev/null @@ -1,24 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil.Metadata { - - abstract class Heap { - - public int IndexSize; - - readonly internal byte [] data; - - protected Heap (byte [] data) - { - this.data = data; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Heap.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Heap.cs.meta deleted file mode 100644 index c0d849b..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Heap.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c343466f40d68574499155a2acd05e6b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/MetadataToken.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/MetadataToken.cs deleted file mode 100644 index 50b2556..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/MetadataToken.cs +++ /dev/null @@ -1,94 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - public struct MetadataToken : IEquatable { - - readonly uint token; - - public uint RID { - get { return token & 0x00ffffff; } - } - - public TokenType TokenType { - get { return (TokenType)(token & 0xff000000); } - } - - public static readonly MetadataToken Zero = new MetadataToken ((uint)0); - - public MetadataToken (uint token) - { - this.token = token; - } - - public MetadataToken (TokenType type) - : this (type, 0) - { - } - - public MetadataToken (TokenType type, uint rid) - { - token = (uint)type | rid; - } - - public MetadataToken (TokenType type, int rid) - { - token = (uint)type | (uint)rid; - } - - public int ToInt32 () - { - return (int)token; - } - - public uint ToUInt32 () - { - return token; - } - - public override int GetHashCode () - { - return (int)token; - } - - public bool Equals (MetadataToken other) - { - return other.token == token; - } - - public override bool Equals (object obj) - { - if (obj is MetadataToken) { - var other = (MetadataToken)obj; - return other.token == token; - } - - return false; - } - - public static bool operator == (MetadataToken one, MetadataToken other) - { - return one.token == other.token; - } - - public static bool operator != (MetadataToken one, MetadataToken other) - { - return one.token != other.token; - } - - public override string ToString () - { - return string.Format ("[{0}:0x{1}]", TokenType, RID.ToString ("x4")); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/MetadataToken.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/MetadataToken.cs.meta deleted file mode 100644 index 3026242..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/MetadataToken.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 755d1954236c374458be77d93493faf8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/PdbHeap.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/PdbHeap.cs deleted file mode 100644 index 6b56710..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/PdbHeap.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using RID = System.UInt32; - -namespace MonoFN.Cecil.Metadata { - - sealed class PdbHeap : Heap { - - public byte [] Id; - public RID EntryPoint; - public long TypeSystemTables; - public uint [] TypeSystemTableRows; - - public PdbHeap (byte [] data) - : base (data) - { - } - - public bool HasTable (Table table) - { - return (TypeSystemTables & (1L << (int)table)) != 0; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/PdbHeap.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/PdbHeap.cs.meta deleted file mode 100644 index 6505525..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/PdbHeap.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c64dd6e20a2b11c44ad424d29380c14c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Row.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Row.cs deleted file mode 100644 index 880eeb3..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Row.cs +++ /dev/null @@ -1,152 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System.Collections.Generic; - -namespace MonoFN.Cecil.Metadata { - - struct Row { - internal T1 Col1; - internal T2 Col2; - - public Row (T1 col1, T2 col2) - { - Col1 = col1; - Col2 = col2; - } - } - - struct Row { - internal T1 Col1; - internal T2 Col2; - internal T3 Col3; - - public Row (T1 col1, T2 col2, T3 col3) - { - Col1 = col1; - Col2 = col2; - Col3 = col3; - } - } - - struct Row { - internal T1 Col1; - internal T2 Col2; - internal T3 Col3; - internal T4 Col4; - - public Row (T1 col1, T2 col2, T3 col3, T4 col4) - { - Col1 = col1; - Col2 = col2; - Col3 = col3; - Col4 = col4; - } - } - - struct Row { - internal T1 Col1; - internal T2 Col2; - internal T3 Col3; - internal T4 Col4; - internal T5 Col5; - - public Row (T1 col1, T2 col2, T3 col3, T4 col4, T5 col5) - { - Col1 = col1; - Col2 = col2; - Col3 = col3; - Col4 = col4; - Col5 = col5; - } - } - - struct Row { - internal T1 Col1; - internal T2 Col2; - internal T3 Col3; - internal T4 Col4; - internal T5 Col5; - internal T6 Col6; - - public Row (T1 col1, T2 col2, T3 col3, T4 col4, T5 col5, T6 col6) - { - Col1 = col1; - Col2 = col2; - Col3 = col3; - Col4 = col4; - Col5 = col5; - Col6 = col6; - } - } - - struct Row { - internal T1 Col1; - internal T2 Col2; - internal T3 Col3; - internal T4 Col4; - internal T5 Col5; - internal T6 Col6; - internal T7 Col7; - internal T8 Col8; - internal T9 Col9; - - public Row (T1 col1, T2 col2, T3 col3, T4 col4, T5 col5, T6 col6, T7 col7, T8 col8, T9 col9) - { - Col1 = col1; - Col2 = col2; - Col3 = col3; - Col4 = col4; - Col5 = col5; - Col6 = col6; - Col7 = col7; - Col8 = col8; - Col9 = col9; - } - } - - sealed class RowEqualityComparer : IEqualityComparer>, IEqualityComparer>, IEqualityComparer> { - - public bool Equals (Row x, Row y) - { - return x.Col1 == y.Col1 - && x.Col2 == y.Col2; - } - - public int GetHashCode (Row obj) - { - string x = obj.Col1, y = obj.Col2; - return (x != null ? x.GetHashCode () : 0) ^ (y != null ? y.GetHashCode () : 0); - } - - public bool Equals (Row x, Row y) - { - return x.Col1 == y.Col1 - && x.Col2 == y.Col2; - } - - public int GetHashCode (Row obj) - { - return (int)(obj.Col1 ^ obj.Col2); - } - - public bool Equals (Row x, Row y) - { - return x.Col1 == y.Col1 - && x.Col2 == y.Col2 - && x.Col3 == y.Col3; - } - - public int GetHashCode (Row obj) - { - return (int)(obj.Col1 ^ obj.Col2 ^ obj.Col3); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Row.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Row.cs.meta deleted file mode 100644 index dc7d118..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Row.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 89fd184bcc2b97840a2c0dfeec671be2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/StringHeap.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/StringHeap.cs deleted file mode 100644 index 22559df..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/StringHeap.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System.Collections.Generic; -using System.Text; - -namespace MonoFN.Cecil.Metadata { - - class StringHeap : Heap { - - readonly Dictionary strings = new Dictionary (); - - public StringHeap (byte [] data) - : base (data) - { - } - - public string Read (uint index) - { - if (index == 0) - return string.Empty; - - string @string; - if (strings.TryGetValue (index, out @string)) - return @string; - - if (index > data.Length - 1) - return string.Empty; - - @string = ReadStringAt (index); - if (@string.Length != 0) - strings.Add (index, @string); - - return @string; - } - - protected virtual string ReadStringAt (uint index) - { - int length = 0; - int start = (int)index; - - for (int i = start; ; i++) { - if (data [i] == 0) - break; - - length++; - } - - return Encoding.UTF8.GetString (data, start, length); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/StringHeap.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/StringHeap.cs.meta deleted file mode 100644 index 9e51e42..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/StringHeap.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e0fc64863ca825b4e994640b0be9a938 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TableHeap.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TableHeap.cs deleted file mode 100644 index e4f206b..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TableHeap.cs +++ /dev/null @@ -1,101 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil.Metadata { - - enum Table : byte { - Module = 0x00, - TypeRef = 0x01, - TypeDef = 0x02, - FieldPtr = 0x03, - Field = 0x04, - MethodPtr = 0x05, - Method = 0x06, - ParamPtr = 0x07, - Param = 0x08, - InterfaceImpl = 0x09, - MemberRef = 0x0a, - Constant = 0x0b, - CustomAttribute = 0x0c, - FieldMarshal = 0x0d, - DeclSecurity = 0x0e, - ClassLayout = 0x0f, - FieldLayout = 0x10, - StandAloneSig = 0x11, - EventMap = 0x12, - EventPtr = 0x13, - Event = 0x14, - PropertyMap = 0x15, - PropertyPtr = 0x16, - Property = 0x17, - MethodSemantics = 0x18, - MethodImpl = 0x19, - ModuleRef = 0x1a, - TypeSpec = 0x1b, - ImplMap = 0x1c, - FieldRVA = 0x1d, - EncLog = 0x1e, - EncMap = 0x1f, - Assembly = 0x20, - AssemblyProcessor = 0x21, - AssemblyOS = 0x22, - AssemblyRef = 0x23, - AssemblyRefProcessor = 0x24, - AssemblyRefOS = 0x25, - File = 0x26, - ExportedType = 0x27, - ManifestResource = 0x28, - NestedClass = 0x29, - GenericParam = 0x2a, - MethodSpec = 0x2b, - GenericParamConstraint = 0x2c, - - Document = 0x30, - MethodDebugInformation = 0x31, - LocalScope = 0x32, - LocalVariable = 0x33, - LocalConstant = 0x34, - ImportScope = 0x35, - StateMachineMethod = 0x36, - CustomDebugInformation = 0x37, - } - - struct TableInformation { - public uint Offset; - public uint Length; - public uint RowSize; - - public bool IsLarge { - get { return Length > ushort.MaxValue; } - } - } - - sealed class TableHeap : Heap { - - public long Valid; - public long Sorted; - - public readonly TableInformation [] Tables = new TableInformation [Mixin.TableCount]; - - public TableInformation this [Table table] { - get { return Tables [(int)table]; } - } - - public TableHeap (byte [] data) - : base (data) - { - } - - public bool HasTable (Table table) - { - return (Valid & (1L << (int)table)) != 0; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TableHeap.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TableHeap.cs.meta deleted file mode 100644 index 64fe6ce..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TableHeap.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 978b1609b2ddc0c4baf628cc608456a9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TokenType.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TokenType.cs deleted file mode 100644 index e527181..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TokenType.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public enum TokenType : uint { - Module = 0x00000000, - TypeRef = 0x01000000, - TypeDef = 0x02000000, - Field = 0x04000000, - Method = 0x06000000, - Param = 0x08000000, - InterfaceImpl = 0x09000000, - MemberRef = 0x0a000000, - CustomAttribute = 0x0c000000, - Permission = 0x0e000000, - Signature = 0x11000000, - Event = 0x14000000, - Property = 0x17000000, - ModuleRef = 0x1a000000, - TypeSpec = 0x1b000000, - Assembly = 0x20000000, - AssemblyRef = 0x23000000, - File = 0x26000000, - ExportedType = 0x27000000, - ManifestResource = 0x28000000, - GenericParam = 0x2a000000, - MethodSpec = 0x2b000000, - GenericParamConstraint = 0x2c000000, - - Document = 0x30000000, - MethodDebugInformation = 0x31000000, - LocalScope = 0x32000000, - LocalVariable = 0x33000000, - LocalConstant = 0x34000000, - ImportScope = 0x35000000, - StateMachineMethod = 0x36000000, - CustomDebugInformation = 0x37000000, - - String = 0x70000000, - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TokenType.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TokenType.cs.meta deleted file mode 100644 index 7dd9eb4..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/TokenType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: dba0af6138c6a084b8787e88b20b142a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/UserStringHeap.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/UserStringHeap.cs deleted file mode 100644 index afdaa2c..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/UserStringHeap.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil.Metadata { - - sealed class UserStringHeap : StringHeap { - - public UserStringHeap (byte [] data) - : base (data) - { - } - - protected override string ReadStringAt (uint index) - { - int start = (int)index; - - uint length = (uint)(data.ReadCompressedUInt32 (ref start) & ~1); - if (length < 1) - return string.Empty; - - var chars = new char [length / 2]; - - for (int i = start, j = 0; i < start + length; i += 2) - chars [j++] = (char)(data [i] | (data [i + 1] << 8)); - - return new string (chars); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/UserStringHeap.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/UserStringHeap.cs.meta deleted file mode 100644 index 40594bf..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/UserStringHeap.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2d89100b382ef8e4ea67917917d04db6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Utilities.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Utilities.cs deleted file mode 100644 index c5a3b03..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Utilities.cs +++ /dev/null @@ -1,649 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Metadata; -using System; - -namespace MonoFN.Cecil { - - static partial class Mixin { - - public const int TableCount = 58; - public const int CodedIndexCount = 14; - - public static uint ReadCompressedUInt32 (this byte [] data, ref int position) - { - uint integer; - if ((data [position] & 0x80) == 0) { - integer = data [position]; - position++; - } else if ((data [position] & 0x40) == 0) { - integer = (uint)(data [position] & ~0x80) << 8; - integer |= data [position + 1]; - position += 2; - } else { - integer = (uint)(data [position] & ~0xc0) << 24; - integer |= (uint)data [position + 1] << 16; - integer |= (uint)data [position + 2] << 8; - integer |= (uint)data [position + 3]; - position += 4; - } - return integer; - } - - public static MetadataToken GetMetadataToken (this CodedIndex self, uint data) - { - uint rid; - TokenType token_type; - switch (self) { - case CodedIndex.TypeDefOrRef: - rid = data >> 2; - switch (data & 3) { - case 0: - token_type = TokenType.TypeDef; goto ret; - case 1: - token_type = TokenType.TypeRef; goto ret; - case 2: - token_type = TokenType.TypeSpec; goto ret; - default: - goto exit; - } - case CodedIndex.HasConstant: - rid = data >> 2; - switch (data & 3) { - case 0: - token_type = TokenType.Field; goto ret; - case 1: - token_type = TokenType.Param; goto ret; - case 2: - token_type = TokenType.Property; goto ret; - default: - goto exit; - } - case CodedIndex.HasCustomAttribute: - rid = data >> 5; - switch (data & 31) { - case 0: - token_type = TokenType.Method; goto ret; - case 1: - token_type = TokenType.Field; goto ret; - case 2: - token_type = TokenType.TypeRef; goto ret; - case 3: - token_type = TokenType.TypeDef; goto ret; - case 4: - token_type = TokenType.Param; goto ret; - case 5: - token_type = TokenType.InterfaceImpl; goto ret; - case 6: - token_type = TokenType.MemberRef; goto ret; - case 7: - token_type = TokenType.Module; goto ret; - case 8: - token_type = TokenType.Permission; goto ret; - case 9: - token_type = TokenType.Property; goto ret; - case 10: - token_type = TokenType.Event; goto ret; - case 11: - token_type = TokenType.Signature; goto ret; - case 12: - token_type = TokenType.ModuleRef; goto ret; - case 13: - token_type = TokenType.TypeSpec; goto ret; - case 14: - token_type = TokenType.Assembly; goto ret; - case 15: - token_type = TokenType.AssemblyRef; goto ret; - case 16: - token_type = TokenType.File; goto ret; - case 17: - token_type = TokenType.ExportedType; goto ret; - case 18: - token_type = TokenType.ManifestResource; goto ret; - case 19: - token_type = TokenType.GenericParam; goto ret; - case 20: - token_type = TokenType.GenericParamConstraint; goto ret; - case 21: - token_type = TokenType.MethodSpec; goto ret; - default: - goto exit; - } - case CodedIndex.HasFieldMarshal: - rid = data >> 1; - switch (data & 1) { - case 0: - token_type = TokenType.Field; goto ret; - case 1: - token_type = TokenType.Param; goto ret; - default: - goto exit; - } - case CodedIndex.HasDeclSecurity: - rid = data >> 2; - switch (data & 3) { - case 0: - token_type = TokenType.TypeDef; goto ret; - case 1: - token_type = TokenType.Method; goto ret; - case 2: - token_type = TokenType.Assembly; goto ret; - default: - goto exit; - } - case CodedIndex.MemberRefParent: - rid = data >> 3; - switch (data & 7) { - case 0: - token_type = TokenType.TypeDef; goto ret; - case 1: - token_type = TokenType.TypeRef; goto ret; - case 2: - token_type = TokenType.ModuleRef; goto ret; - case 3: - token_type = TokenType.Method; goto ret; - case 4: - token_type = TokenType.TypeSpec; goto ret; - default: - goto exit; - } - case CodedIndex.HasSemantics: - rid = data >> 1; - switch (data & 1) { - case 0: - token_type = TokenType.Event; goto ret; - case 1: - token_type = TokenType.Property; goto ret; - default: - goto exit; - } - case CodedIndex.MethodDefOrRef: - rid = data >> 1; - switch (data & 1) { - case 0: - token_type = TokenType.Method; goto ret; - case 1: - token_type = TokenType.MemberRef; goto ret; - default: - goto exit; - } - case CodedIndex.MemberForwarded: - rid = data >> 1; - switch (data & 1) { - case 0: - token_type = TokenType.Field; goto ret; - case 1: - token_type = TokenType.Method; goto ret; - default: - goto exit; - } - case CodedIndex.Implementation: - rid = data >> 2; - switch (data & 3) { - case 0: - token_type = TokenType.File; goto ret; - case 1: - token_type = TokenType.AssemblyRef; goto ret; - case 2: - token_type = TokenType.ExportedType; goto ret; - default: - goto exit; - } - case CodedIndex.CustomAttributeType: - rid = data >> 3; - switch (data & 7) { - case 2: - token_type = TokenType.Method; goto ret; - case 3: - token_type = TokenType.MemberRef; goto ret; - default: - goto exit; - } - case CodedIndex.ResolutionScope: - rid = data >> 2; - switch (data & 3) { - case 0: - token_type = TokenType.Module; goto ret; - case 1: - token_type = TokenType.ModuleRef; goto ret; - case 2: - token_type = TokenType.AssemblyRef; goto ret; - case 3: - token_type = TokenType.TypeRef; goto ret; - default: - goto exit; - } - case CodedIndex.TypeOrMethodDef: - rid = data >> 1; - switch (data & 1) { - case 0: - token_type = TokenType.TypeDef; goto ret; - case 1: - token_type = TokenType.Method; goto ret; - default: goto exit; - } - case CodedIndex.HasCustomDebugInformation: - rid = data >> 5; - switch (data & 31) { - case 0: - token_type = TokenType.Method; goto ret; - case 1: - token_type = TokenType.Field; goto ret; - case 2: - token_type = TokenType.TypeRef; goto ret; - case 3: - token_type = TokenType.TypeDef; goto ret; - case 4: - token_type = TokenType.Param; goto ret; - case 5: - token_type = TokenType.InterfaceImpl; goto ret; - case 6: - token_type = TokenType.MemberRef; goto ret; - case 7: - token_type = TokenType.Module; goto ret; - case 8: - token_type = TokenType.Permission; goto ret; - case 9: - token_type = TokenType.Property; goto ret; - case 10: - token_type = TokenType.Event; goto ret; - case 11: - token_type = TokenType.Signature; goto ret; - case 12: - token_type = TokenType.ModuleRef; goto ret; - case 13: - token_type = TokenType.TypeSpec; goto ret; - case 14: - token_type = TokenType.Assembly; goto ret; - case 15: - token_type = TokenType.AssemblyRef; goto ret; - case 16: - token_type = TokenType.File; goto ret; - case 17: - token_type = TokenType.ExportedType; goto ret; - case 18: - token_type = TokenType.ManifestResource; goto ret; - case 19: - token_type = TokenType.GenericParam; goto ret; - case 20: - token_type = TokenType.GenericParamConstraint; goto ret; - case 21: - token_type = TokenType.MethodSpec; goto ret; - case 22: - token_type = TokenType.Document; goto ret; - case 23: - token_type = TokenType.LocalScope; goto ret; - case 24: - token_type = TokenType.LocalVariable; goto ret; - case 25: - token_type = TokenType.LocalConstant; goto ret; - case 26: - token_type = TokenType.ImportScope; goto ret; - default: - goto exit; - } - default: - goto exit; - } - ret: - return new MetadataToken (token_type, rid); - exit: - return MetadataToken.Zero; - } - - public static uint CompressMetadataToken (this CodedIndex self, MetadataToken token) - { - uint ret = 0; - if (token.RID == 0) - return ret; - switch (self) { - case CodedIndex.TypeDefOrRef: - ret = token.RID << 2; - switch (token.TokenType) { - case TokenType.TypeDef: - return ret | 0; - case TokenType.TypeRef: - return ret | 1; - case TokenType.TypeSpec: - return ret | 2; - default: - goto exit; - } - case CodedIndex.HasConstant: - ret = token.RID << 2; - switch (token.TokenType) { - case TokenType.Field: - return ret | 0; - case TokenType.Param: - return ret | 1; - case TokenType.Property: - return ret | 2; - default: - goto exit; - } - case CodedIndex.HasCustomAttribute: - ret = token.RID << 5; - switch (token.TokenType) { - case TokenType.Method: - return ret | 0; - case TokenType.Field: - return ret | 1; - case TokenType.TypeRef: - return ret | 2; - case TokenType.TypeDef: - return ret | 3; - case TokenType.Param: - return ret | 4; - case TokenType.InterfaceImpl: - return ret | 5; - case TokenType.MemberRef: - return ret | 6; - case TokenType.Module: - return ret | 7; - case TokenType.Permission: - return ret | 8; - case TokenType.Property: - return ret | 9; - case TokenType.Event: - return ret | 10; - case TokenType.Signature: - return ret | 11; - case TokenType.ModuleRef: - return ret | 12; - case TokenType.TypeSpec: - return ret | 13; - case TokenType.Assembly: - return ret | 14; - case TokenType.AssemblyRef: - return ret | 15; - case TokenType.File: - return ret | 16; - case TokenType.ExportedType: - return ret | 17; - case TokenType.ManifestResource: - return ret | 18; - case TokenType.GenericParam: - return ret | 19; - case TokenType.GenericParamConstraint: - return ret | 20; - case TokenType.MethodSpec: - return ret | 21; - default: - goto exit; - } - case CodedIndex.HasFieldMarshal: - ret = token.RID << 1; - switch (token.TokenType) { - case TokenType.Field: - return ret | 0; - case TokenType.Param: - return ret | 1; - default: - goto exit; - } - case CodedIndex.HasDeclSecurity: - ret = token.RID << 2; - switch (token.TokenType) { - case TokenType.TypeDef: - return ret | 0; - case TokenType.Method: - return ret | 1; - case TokenType.Assembly: - return ret | 2; - default: - goto exit; - } - case CodedIndex.MemberRefParent: - ret = token.RID << 3; - switch (token.TokenType) { - case TokenType.TypeDef: - return ret | 0; - case TokenType.TypeRef: - return ret | 1; - case TokenType.ModuleRef: - return ret | 2; - case TokenType.Method: - return ret | 3; - case TokenType.TypeSpec: - return ret | 4; - default: - goto exit; - } - case CodedIndex.HasSemantics: - ret = token.RID << 1; - switch (token.TokenType) { - case TokenType.Event: - return ret | 0; - case TokenType.Property: - return ret | 1; - default: - goto exit; - } - case CodedIndex.MethodDefOrRef: - ret = token.RID << 1; - switch (token.TokenType) { - case TokenType.Method: - return ret | 0; - case TokenType.MemberRef: - return ret | 1; - default: - goto exit; - } - case CodedIndex.MemberForwarded: - ret = token.RID << 1; - switch (token.TokenType) { - case TokenType.Field: - return ret | 0; - case TokenType.Method: - return ret | 1; - default: - goto exit; - } - case CodedIndex.Implementation: - ret = token.RID << 2; - switch (token.TokenType) { - case TokenType.File: - return ret | 0; - case TokenType.AssemblyRef: - return ret | 1; - case TokenType.ExportedType: - return ret | 2; - default: - goto exit; - } - case CodedIndex.CustomAttributeType: - ret = token.RID << 3; - switch (token.TokenType) { - case TokenType.Method: - return ret | 2; - case TokenType.MemberRef: - return ret | 3; - default: - goto exit; - } - case CodedIndex.ResolutionScope: - ret = token.RID << 2; - switch (token.TokenType) { - case TokenType.Module: - return ret | 0; - case TokenType.ModuleRef: - return ret | 1; - case TokenType.AssemblyRef: - return ret | 2; - case TokenType.TypeRef: - return ret | 3; - default: - goto exit; - } - case CodedIndex.TypeOrMethodDef: - ret = token.RID << 1; - switch (token.TokenType) { - case TokenType.TypeDef: - return ret | 0; - case TokenType.Method: - return ret | 1; - default: - goto exit; - } - case CodedIndex.HasCustomDebugInformation: - ret = token.RID << 5; - switch (token.TokenType) { - case TokenType.Method: - return ret | 0; - case TokenType.Field: - return ret | 1; - case TokenType.TypeRef: - return ret | 2; - case TokenType.TypeDef: - return ret | 3; - case TokenType.Param: - return ret | 4; - case TokenType.InterfaceImpl: - return ret | 5; - case TokenType.MemberRef: - return ret | 6; - case TokenType.Module: - return ret | 7; - case TokenType.Permission: - return ret | 8; - case TokenType.Property: - return ret | 9; - case TokenType.Event: - return ret | 10; - case TokenType.Signature: - return ret | 11; - case TokenType.ModuleRef: - return ret | 12; - case TokenType.TypeSpec: - return ret | 13; - case TokenType.Assembly: - return ret | 14; - case TokenType.AssemblyRef: - return ret | 15; - case TokenType.File: - return ret | 16; - case TokenType.ExportedType: - return ret | 17; - case TokenType.ManifestResource: - return ret | 18; - case TokenType.GenericParam: - return ret | 19; - case TokenType.GenericParamConstraint: - return ret | 20; - case TokenType.MethodSpec: - return ret | 21; - case TokenType.Document: - return ret | 22; - case TokenType.LocalScope: - return ret | 23; - case TokenType.LocalVariable: - return ret | 24; - case TokenType.LocalConstant: - return ret | 25; - case TokenType.ImportScope: - return ret | 26; - default: - goto exit; - } - default: - goto exit; - } - exit: - throw new ArgumentException (); - } - - public static int GetSize (this CodedIndex self, Func counter) - { - int bits; - Table [] tables; - - switch (self) { - case CodedIndex.TypeDefOrRef: - bits = 2; - tables = new [] { Table.TypeDef, Table.TypeRef, Table.TypeSpec }; - break; - case CodedIndex.HasConstant: - bits = 2; - tables = new [] { Table.Field, Table.Param, Table.Property }; - break; - case CodedIndex.HasCustomAttribute: - bits = 5; - tables = new [] { - Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef, - Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef, - Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType, - Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec, - }; - break; - case CodedIndex.HasFieldMarshal: - bits = 1; - tables = new [] { Table.Field, Table.Param }; - break; - case CodedIndex.HasDeclSecurity: - bits = 2; - tables = new [] { Table.TypeDef, Table.Method, Table.Assembly }; - break; - case CodedIndex.MemberRefParent: - bits = 3; - tables = new [] { Table.TypeDef, Table.TypeRef, Table.ModuleRef, Table.Method, Table.TypeSpec }; - break; - case CodedIndex.HasSemantics: - bits = 1; - tables = new [] { Table.Event, Table.Property }; - break; - case CodedIndex.MethodDefOrRef: - bits = 1; - tables = new [] { Table.Method, Table.MemberRef }; - break; - case CodedIndex.MemberForwarded: - bits = 1; - tables = new [] { Table.Field, Table.Method }; - break; - case CodedIndex.Implementation: - bits = 2; - tables = new [] { Table.File, Table.AssemblyRef, Table.ExportedType }; - break; - case CodedIndex.CustomAttributeType: - bits = 3; - tables = new [] { Table.Method, Table.MemberRef }; - break; - case CodedIndex.ResolutionScope: - bits = 2; - tables = new [] { Table.Module, Table.ModuleRef, Table.AssemblyRef, Table.TypeRef }; - break; - case CodedIndex.TypeOrMethodDef: - bits = 1; - tables = new [] { Table.TypeDef, Table.Method }; - break; - case CodedIndex.HasCustomDebugInformation: - bits = 5; - tables = new [] { - Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef, - Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef, - Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType, - Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec, - Table.Document, Table.LocalScope, Table.LocalVariable, Table.LocalConstant, Table.ImportScope, - }; - break; - default: - throw new ArgumentException (); - } - - int max = 0; - - for (int i = 0; i < tables.Length; i++) { - max = System.Math.Max (counter (tables [i]), max); - } - - return max < (1 << (16 - bits)) ? 2 : 4; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Utilities.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Utilities.cs.meta deleted file mode 100644 index 6fab64b..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Metadata/Utilities.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4785957c0c546de4680e1196a57f66d2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE.meta deleted file mode 100644 index 9797d0a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 8c654da31387b0a4ea2a1128a28ef87d -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamReader.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamReader.cs deleted file mode 100644 index c584ff8..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamReader.cs +++ /dev/null @@ -1,53 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System.IO; - -namespace MonoFN.Cecil.PE { - - class BinaryStreamReader : BinaryReader { - - public int Position { - get { return (int)BaseStream.Position; } - set { BaseStream.Position = value; } - } - - public int Length { - get { return (int)BaseStream.Length; } - } - - public BinaryStreamReader (Stream stream) - : base (stream) - { - } - - public void Advance (int bytes) - { - BaseStream.Seek (bytes, SeekOrigin.Current); - } - - public void MoveTo (uint position) - { - BaseStream.Seek (position, SeekOrigin.Begin); - } - - public void Align (int align) - { - align--; - var position = Position; - Advance (((position + align) & ~align) - position); - } - - public DataDirectory ReadDataDirectory () - { - return new DataDirectory (ReadUInt32 (), ReadUInt32 ()); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamReader.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamReader.cs.meta deleted file mode 100644 index a1d4c1d..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamReader.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7492ed3a048237443b99d7a25e806ce6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamWriter.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamWriter.cs deleted file mode 100644 index 34ad11a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamWriter.cs +++ /dev/null @@ -1,88 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System.IO; - -namespace MonoFN.Cecil.PE { - - class BinaryStreamWriter : BinaryWriter { - - public int Position { - get { return (int)BaseStream.Position; } - set { BaseStream.Position = value; } - } - - public BinaryStreamWriter (Stream stream) - : base (stream) - { - } - - public void WriteByte (byte value) - { - Write (value); - } - - public void WriteUInt16 (ushort value) - { - Write (value); - } - - public void WriteInt16 (short value) - { - Write (value); - } - - public void WriteUInt32 (uint value) - { - Write (value); - } - - public void WriteInt32 (int value) - { - Write (value); - } - - public void WriteUInt64 (ulong value) - { - Write (value); - } - - public void WriteBytes (byte [] bytes) - { - Write (bytes); - } - - public void WriteDataDirectory (DataDirectory directory) - { - Write (directory.VirtualAddress); - Write (directory.Size); - } - - public void WriteBuffer (ByteBuffer buffer) - { - Write (buffer.buffer, 0, buffer.length); - } - - protected void Advance (int bytes) - { - BaseStream.Seek (bytes, SeekOrigin.Current); - } - - public void Align (int align) - { - align--; - var position = Position; - var bytes = ((position + align) & ~align) - position; - - for (int i = 0; i < bytes; i++) - WriteByte (0); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamWriter.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamWriter.cs.meta deleted file mode 100644 index 2c0e298..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/BinaryStreamWriter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 26d384e0dd0e44549a9faf09adbd0a41 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBuffer.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBuffer.cs deleted file mode 100644 index 8e5c947..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBuffer.cs +++ /dev/null @@ -1,335 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil.PE { - - class ByteBuffer { - - internal byte [] buffer; - internal int length; - internal int position; - - public ByteBuffer () - { - this.buffer = Empty.Array; - } - - public ByteBuffer (int length) - { - this.buffer = new byte [length]; - } - - public ByteBuffer (byte [] buffer) - { - this.buffer = buffer ?? Empty.Array; - this.length = this.buffer.Length; - } - - public void Advance (int length) - { - position += length; - } - - public byte ReadByte () - { - return buffer [position++]; - } - - public sbyte ReadSByte () - { - return (sbyte)ReadByte (); - } - - public byte [] ReadBytes (int length) - { - var bytes = new byte [length]; - Buffer.BlockCopy (buffer, position, bytes, 0, length); - position += length; - return bytes; - } - - public ushort ReadUInt16 () - { - ushort value = (ushort)(buffer [position] - | (buffer [position + 1] << 8)); - position += 2; - return value; - } - - public short ReadInt16 () - { - return (short)ReadUInt16 (); - } - - public uint ReadUInt32 () - { - uint value = (uint)(buffer [position] - | (buffer [position + 1] << 8) - | (buffer [position + 2] << 16) - | (buffer [position + 3] << 24)); - position += 4; - return value; - } - - public int ReadInt32 () - { - return (int)ReadUInt32 (); - } - - public ulong ReadUInt64 () - { - uint low = ReadUInt32 (); - uint high = ReadUInt32 (); - - return (((ulong)high) << 32) | low; - } - - public long ReadInt64 () - { - return (long)ReadUInt64 (); - } - - public uint ReadCompressedUInt32 () - { - byte first = ReadByte (); - if ((first & 0x80) == 0) - return first; - - if ((first & 0x40) == 0) - return ((uint)(first & ~0x80) << 8) - | ReadByte (); - - return ((uint)(first & ~0xc0) << 24) - | (uint)ReadByte () << 16 - | (uint)ReadByte () << 8 - | ReadByte (); - } - - public int ReadCompressedInt32 () - { - var b = buffer [position]; - var u = (int)ReadCompressedUInt32 (); - var v = u >> 1; - if ((u & 1) == 0) - return v; - - switch (b & 0xc0) { - case 0: - case 0x40: - return v - 0x40; - case 0x80: - return v - 0x2000; - default: - return v - 0x10000000; - } - } - - public float ReadSingle () - { - if (!BitConverter.IsLittleEndian) { - var bytes = ReadBytes (4); - Array.Reverse (bytes); - return BitConverter.ToSingle (bytes, 0); - } - - float value = BitConverter.ToSingle (buffer, position); - position += 4; - return value; - } - - public double ReadDouble () - { - if (!BitConverter.IsLittleEndian) { - var bytes = ReadBytes (8); - Array.Reverse (bytes); - return BitConverter.ToDouble (bytes, 0); - } - - double value = BitConverter.ToDouble (buffer, position); - position += 8; - return value; - } - - public void WriteByte (byte value) - { - if (position == buffer.Length) - Grow (1); - - buffer [position++] = value; - - if (position > length) - length = position; - } - - public void WriteSByte (sbyte value) - { - WriteByte ((byte)value); - } - - public void WriteUInt16 (ushort value) - { - if (position + 2 > buffer.Length) - Grow (2); - - buffer [position++] = (byte)value; - buffer [position++] = (byte)(value >> 8); - - if (position > length) - length = position; - } - - public void WriteInt16 (short value) - { - WriteUInt16 ((ushort)value); - } - - public void WriteUInt32 (uint value) - { - if (position + 4 > buffer.Length) - Grow (4); - - buffer [position++] = (byte)value; - buffer [position++] = (byte)(value >> 8); - buffer [position++] = (byte)(value >> 16); - buffer [position++] = (byte)(value >> 24); - - if (position > length) - length = position; - } - - public void WriteInt32 (int value) - { - WriteUInt32 ((uint)value); - } - - public void WriteUInt64 (ulong value) - { - if (position + 8 > buffer.Length) - Grow (8); - - buffer [position++] = (byte)value; - buffer [position++] = (byte)(value >> 8); - buffer [position++] = (byte)(value >> 16); - buffer [position++] = (byte)(value >> 24); - buffer [position++] = (byte)(value >> 32); - buffer [position++] = (byte)(value >> 40); - buffer [position++] = (byte)(value >> 48); - buffer [position++] = (byte)(value >> 56); - - if (position > length) - length = position; - } - - public void WriteInt64 (long value) - { - WriteUInt64 ((ulong)value); - } - - public void WriteCompressedUInt32 (uint value) - { - if (value < 0x80) - WriteByte ((byte)value); - else if (value < 0x4000) { - WriteByte ((byte)(0x80 | (value >> 8))); - WriteByte ((byte)(value & 0xff)); - } else { - WriteByte ((byte)((value >> 24) | 0xc0)); - WriteByte ((byte)((value >> 16) & 0xff)); - WriteByte ((byte)((value >> 8) & 0xff)); - WriteByte ((byte)(value & 0xff)); - } - } - - public void WriteCompressedInt32 (int value) - { - if (value >= 0) { - WriteCompressedUInt32 ((uint)(value << 1)); - return; - } - - if (value > -0x40) - value = 0x40 + value; - else if (value >= -0x2000) - value = 0x2000 + value; - else if (value >= -0x20000000) - value = 0x20000000 + value; - - WriteCompressedUInt32 ((uint)((value << 1) | 1)); - } - - public void WriteBytes (byte [] bytes) - { - var length = bytes.Length; - if (position + length > buffer.Length) - Grow (length); - - Buffer.BlockCopy (bytes, 0, buffer, position, length); - position += length; - - if (position > this.length) - this.length = position; - } - - public void WriteBytes (int length) - { - if (position + length > buffer.Length) - Grow (length); - - position += length; - - if (position > this.length) - this.length = position; - } - - public void WriteBytes (ByteBuffer buffer) - { - if (position + buffer.length > this.buffer.Length) - Grow (buffer.length); - - Buffer.BlockCopy (buffer.buffer, 0, this.buffer, position, buffer.length); - position += buffer.length; - - if (position > this.length) - this.length = position; - } - - public void WriteSingle (float value) - { - var bytes = BitConverter.GetBytes (value); - - if (!BitConverter.IsLittleEndian) - Array.Reverse (bytes); - - WriteBytes (bytes); - } - - public void WriteDouble (double value) - { - var bytes = BitConverter.GetBytes (value); - - if (!BitConverter.IsLittleEndian) - Array.Reverse (bytes); - - WriteBytes (bytes); - } - - void Grow (int desired) - { - var current = this.buffer; - var current_length = current.Length; - - var buffer = new byte [System.Math.Max (current_length + desired, current_length * 2)]; - Buffer.BlockCopy (current, 0, buffer, 0, current_length); - this.buffer = buffer; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBuffer.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBuffer.cs.meta deleted file mode 100644 index 15415a1..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBuffer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3752816249ea16e4aba70adb03f01673 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBufferEqualityComparer.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBufferEqualityComparer.cs deleted file mode 100644 index 25caec1..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBufferEqualityComparer.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System.Collections.Generic; - -namespace MonoFN.Cecil.PE { - - sealed class ByteBufferEqualityComparer : IEqualityComparer { - - public bool Equals (ByteBuffer x, ByteBuffer y) - { - if (x.length != y.length) - return false; - - var x_buffer = x.buffer; - var y_buffer = y.buffer; - - for (int i = 0; i < x.length; i++) - if (x_buffer [i] != y_buffer [i]) - return false; - - return true; - } - - public int GetHashCode (ByteBuffer buffer) - { - // See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function - const int fnv_offset_bias = unchecked((int)2166136261); - const int fnv_prime = 16777619; - - var hash_code = fnv_offset_bias; - var bytes = buffer.buffer; - - for (int i = 0; i < buffer.length; i++) - hash_code = unchecked((hash_code ^ bytes [i]) * fnv_prime); - - return hash_code; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBufferEqualityComparer.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBufferEqualityComparer.cs.meta deleted file mode 100644 index 402b21d..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ByteBufferEqualityComparer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0db5f2f7f9a349d4d89e2329ffd563b2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/DataDirectory.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/DataDirectory.cs deleted file mode 100644 index 81121af..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/DataDirectory.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using RVA = System.UInt32; - -namespace MonoFN.Cecil.PE { - - struct DataDirectory { - - public readonly RVA VirtualAddress; - public readonly uint Size; - - public bool IsZero { - get { return VirtualAddress == 0 && Size == 0; } - } - - public DataDirectory (RVA rva, uint size) - { - this.VirtualAddress = rva; - this.Size = size; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/DataDirectory.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/DataDirectory.cs.meta deleted file mode 100644 index b196baa..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/DataDirectory.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7cd272a7ff953734bbacab398dfc9fe8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Image.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Image.cs deleted file mode 100644 index a129178..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Image.cs +++ /dev/null @@ -1,169 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Cil; -using MonoFN.Cecil.Metadata; -using System; -using System.IO; -using RVA = System.UInt32; - -namespace MonoFN.Cecil.PE { - - sealed class Image : IDisposable { - - public Disposable Stream; - public string FileName; - - public ModuleKind Kind; - public uint Characteristics; - public string RuntimeVersion; - public TargetArchitecture Architecture; - public ModuleCharacteristics DllCharacteristics; - public ushort LinkerVersion; - public ushort SubSystemMajor; - public ushort SubSystemMinor; - - public ImageDebugHeader DebugHeader; - - public Section [] Sections; - - public Section MetadataSection; - - public uint EntryPointToken; - public uint Timestamp; - public ModuleAttributes Attributes; - - public DataDirectory Win32Resources; - public DataDirectory Debug; - public DataDirectory Resources; - public DataDirectory StrongName; - - public StringHeap StringHeap; - public BlobHeap BlobHeap; - public UserStringHeap UserStringHeap; - public GuidHeap GuidHeap; - public TableHeap TableHeap; - public PdbHeap PdbHeap; - - readonly int [] coded_index_sizes = new int [14]; - - readonly Func counter; - - public Image () - { - counter = GetTableLength; - } - - public bool HasTable (Table table) - { - return GetTableLength (table) > 0; - } - - public int GetTableLength (Table table) - { - return (int)TableHeap [table].Length; - } - - public int GetTableIndexSize (Table table) - { - return GetTableLength (table) < 65536 ? 2 : 4; - } - - public int GetCodedIndexSize (CodedIndex coded_index) - { - var index = (int)coded_index; - var size = coded_index_sizes [index]; - if (size != 0) - return size; - - return coded_index_sizes [index] = coded_index.GetSize (counter); - } - - public uint ResolveVirtualAddress (RVA rva) - { - var section = GetSectionAtVirtualAddress (rva); - if (section == null) - throw new ArgumentOutOfRangeException (); - - return ResolveVirtualAddressInSection (rva, section); - } - - public uint ResolveVirtualAddressInSection (RVA rva, Section section) - { - return rva + section.PointerToRawData - section.VirtualAddress; - } - - public Section GetSection (string name) - { - var sections = this.Sections; - for (int i = 0; i < sections.Length; i++) { - var section = sections [i]; - if (section.Name == name) - return section; - } - - return null; - } - - public Section GetSectionAtVirtualAddress (RVA rva) - { - var sections = this.Sections; - for (int i = 0; i < sections.Length; i++) { - var section = sections [i]; - if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.SizeOfRawData) - return section; - } - - return null; - } - - BinaryStreamReader GetReaderAt (RVA rva) - { - var section = GetSectionAtVirtualAddress (rva); - if (section == null) - return null; - - var reader = new BinaryStreamReader (Stream.value); - reader.MoveTo (ResolveVirtualAddressInSection (rva, section)); - return reader; - } - - public TRet GetReaderAt (RVA rva, TItem item, Func read) where TRet : class - { - var position = Stream.value.Position; - try { - var reader = GetReaderAt (rva); - if (reader == null) - return null; - - return read (item, reader); - } - finally { - Stream.value.Position = position; - } - } - - public bool HasDebugTables () - { - return HasTable (Table.Document) - || HasTable (Table.MethodDebugInformation) - || HasTable (Table.LocalScope) - || HasTable (Table.LocalVariable) - || HasTable (Table.LocalConstant) - || HasTable (Table.StateMachineMethod) - || HasTable (Table.CustomDebugInformation); - } - - public void Dispose () - { - Stream.Dispose (); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Image.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Image.cs.meta deleted file mode 100644 index 2978245..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Image.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: be7f3ca6a9f5ad34db68702bd99778fd -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageReader.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageReader.cs deleted file mode 100644 index 8837e6b..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageReader.cs +++ /dev/null @@ -1,793 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Cil; -using MonoFN.Cecil.Metadata; -using System; -using System.IO; - -namespace MonoFN.Cecil.PE { - - sealed class ImageReader : BinaryStreamReader { - - readonly Image image; - - DataDirectory cli; - DataDirectory metadata; - - uint table_heap_offset; - - public ImageReader (Disposable stream, string file_name) - : base (stream.value) - { - image = new Image (); - image.Stream = stream; - image.FileName = file_name; - } - - void MoveTo (DataDirectory directory) - { - BaseStream.Position = image.ResolveVirtualAddress (directory.VirtualAddress); - } - - void ReadImage () - { - if (BaseStream.Length < 128) - throw new BadImageFormatException (); - - // - DOSHeader - - // PE 2 - // Start 58 - // Lfanew 4 - // End 64 - - if (ReadUInt16 () != 0x5a4d) - throw new BadImageFormatException (); - - Advance (58); - - MoveTo (ReadUInt32 ()); - - if (ReadUInt32 () != 0x00004550) - throw new BadImageFormatException (); - - // - PEFileHeader - - // Machine 2 - image.Architecture = ReadArchitecture (); - - // NumberOfSections 2 - ushort sections = ReadUInt16 (); - - // TimeDateStamp 4 - image.Timestamp = ReadUInt32 (); - // PointerToSymbolTable 4 - // NumberOfSymbols 4 - // OptionalHeaderSize 2 - Advance (10); - - // Characteristics 2 - ushort characteristics = ReadUInt16 (); - - ushort subsystem, dll_characteristics; - ReadOptionalHeaders (out subsystem, out dll_characteristics); - ReadSections (sections); - ReadCLIHeader (); - ReadMetadata (); - ReadDebugHeader (); - - image.Characteristics = characteristics; - image.Kind = GetModuleKind (characteristics, subsystem); - image.DllCharacteristics = (ModuleCharacteristics)dll_characteristics; - } - - TargetArchitecture ReadArchitecture () - { - return (TargetArchitecture)ReadUInt16 (); - } - - static ModuleKind GetModuleKind (ushort characteristics, ushort subsystem) - { - if ((characteristics & 0x2000) != 0) // ImageCharacteristics.Dll - return ModuleKind.Dll; - - if (subsystem == 0x2 || subsystem == 0x9) // SubSystem.WindowsGui || SubSystem.WindowsCeGui - return ModuleKind.Windows; - - return ModuleKind.Console; - } - - void ReadOptionalHeaders (out ushort subsystem, out ushort dll_characteristics) - { - // - PEOptionalHeader - // - StandardFieldsHeader - - // Magic 2 - bool pe64 = ReadUInt16 () == 0x20b; - - // pe32 || pe64 - - image.LinkerVersion = ReadUInt16 (); - // CodeSize 4 - // InitializedDataSize 4 - // UninitializedDataSize4 - // EntryPointRVA 4 - // BaseOfCode 4 - // BaseOfData 4 || 0 - - // - NTSpecificFieldsHeader - - // ImageBase 4 || 8 - // SectionAlignment 4 - // FileAlignement 4 - // OSMajor 2 - // OSMinor 2 - // UserMajor 2 - // UserMinor 2 - // SubSysMajor 2 - // SubSysMinor 2 - Advance (44); - - image.SubSystemMajor = ReadUInt16 (); - image.SubSystemMinor = ReadUInt16 (); - - // Reserved 4 - // ImageSize 4 - // HeaderSize 4 - // FileChecksum 4 - Advance (16); - - // SubSystem 2 - subsystem = ReadUInt16 (); - - // DLLFlags 2 - dll_characteristics = ReadUInt16 (); - // StackReserveSize 4 || 8 - // StackCommitSize 4 || 8 - // HeapReserveSize 4 || 8 - // HeapCommitSize 4 || 8 - // LoaderFlags 4 - // NumberOfDataDir 4 - - // - DataDirectoriesHeader - - // ExportTable 8 - // ImportTable 8 - - Advance (pe64 ? 56 : 40); - - // ResourceTable 8 - - image.Win32Resources = ReadDataDirectory (); - - // ExceptionTable 8 - // CertificateTable 8 - // BaseRelocationTable 8 - - Advance (24); - - // Debug 8 - image.Debug = ReadDataDirectory (); - - // Copyright 8 - // GlobalPtr 8 - // TLSTable 8 - // LoadConfigTable 8 - // BoundImport 8 - // IAT 8 - // DelayImportDescriptor8 - Advance (56); - - // CLIHeader 8 - cli = ReadDataDirectory (); - - if (cli.IsZero) - throw new BadImageFormatException (); - - // Reserved 8 - Advance (8); - } - - string ReadAlignedString (int length) - { - int read = 0; - var buffer = new char [length]; - while (read < length) { - var current = ReadByte (); - if (current == 0) - break; - - buffer [read++] = (char)current; - } - - Advance (-1 + ((read + 4) & ~3) - read); - - return new string (buffer, 0, read); - } - - string ReadZeroTerminatedString (int length) - { - int read = 0; - var buffer = new char [length]; - var bytes = ReadBytes (length); - while (read < length) { - var current = bytes [read]; - if (current == 0) - break; - - buffer [read++] = (char)current; - } - - return new string (buffer, 0, read); - } - - void ReadSections (ushort count) - { - var sections = new Section [count]; - - for (int i = 0; i < count; i++) { - var section = new Section (); - - // Name - section.Name = ReadZeroTerminatedString (8); - - // VirtualSize 4 - Advance (4); - - // VirtualAddress 4 - section.VirtualAddress = ReadUInt32 (); - // SizeOfRawData 4 - section.SizeOfRawData = ReadUInt32 (); - // PointerToRawData 4 - section.PointerToRawData = ReadUInt32 (); - - // PointerToRelocations 4 - // PointerToLineNumbers 4 - // NumberOfRelocations 2 - // NumberOfLineNumbers 2 - // Characteristics 4 - Advance (16); - - sections [i] = section; - } - - image.Sections = sections; - } - - void ReadCLIHeader () - { - MoveTo (cli); - - // - CLIHeader - - // Cb 4 - // MajorRuntimeVersion 2 - // MinorRuntimeVersion 2 - Advance (8); - - // Metadata 8 - metadata = ReadDataDirectory (); - // Flags 4 - image.Attributes = (ModuleAttributes)ReadUInt32 (); - // EntryPointToken 4 - image.EntryPointToken = ReadUInt32 (); - // Resources 8 - image.Resources = ReadDataDirectory (); - // StrongNameSignature 8 - image.StrongName = ReadDataDirectory (); - // CodeManagerTable 8 - // VTableFixups 8 - // ExportAddressTableJumps 8 - // ManagedNativeHeader 8 - } - - void ReadMetadata () - { - MoveTo (metadata); - - if (ReadUInt32 () != 0x424a5342) - throw new BadImageFormatException (); - - // MajorVersion 2 - // MinorVersion 2 - // Reserved 4 - Advance (8); - - image.RuntimeVersion = ReadZeroTerminatedString (ReadInt32 ()); - - // Flags 2 - Advance (2); - - var streams = ReadUInt16 (); - - var section = image.GetSectionAtVirtualAddress (metadata.VirtualAddress); - if (section == null) - throw new BadImageFormatException (); - - image.MetadataSection = section; - - for (int i = 0; i < streams; i++) - ReadMetadataStream (section); - - if (image.PdbHeap != null) - ReadPdbHeap (); - - if (image.TableHeap != null) - ReadTableHeap (); - } - - void ReadDebugHeader () - { - if (image.Debug.IsZero) { - image.DebugHeader = new ImageDebugHeader (Empty.Array); - return; - } - - MoveTo (image.Debug); - - var entries = new ImageDebugHeaderEntry [(int)image.Debug.Size / ImageDebugDirectory.Size]; - - for (int i = 0; i < entries.Length; i++) { - var directory = new ImageDebugDirectory { - Characteristics = ReadInt32 (), - TimeDateStamp = ReadInt32 (), - MajorVersion = ReadInt16 (), - MinorVersion = ReadInt16 (), - Type = (ImageDebugType)ReadInt32 (), - SizeOfData = ReadInt32 (), - AddressOfRawData = ReadInt32 (), - PointerToRawData = ReadInt32 (), - }; - - if (directory.PointerToRawData == 0 || directory.SizeOfData < 0) { - entries [i] = new ImageDebugHeaderEntry (directory, Empty.Array); - continue; - } - - var position = Position; - try { - MoveTo ((uint)directory.PointerToRawData); - var data = ReadBytes (directory.SizeOfData); - entries [i] = new ImageDebugHeaderEntry (directory, data); - } - finally { - Position = position; - } - } - - image.DebugHeader = new ImageDebugHeader (entries); - } - - void ReadMetadataStream (Section section) - { - // Offset 4 - uint offset = metadata.VirtualAddress - section.VirtualAddress + ReadUInt32 (); // relative to the section start - - // Size 4 - uint size = ReadUInt32 (); - - var data = ReadHeapData (offset, size); - - var name = ReadAlignedString (16); - switch (name) { - case "#~": - case "#-": - image.TableHeap = new TableHeap (data); - table_heap_offset = offset; - break; - case "#Strings": - image.StringHeap = new StringHeap (data); - break; - case "#Blob": - image.BlobHeap = new BlobHeap (data); - break; - case "#GUID": - image.GuidHeap = new GuidHeap (data); - break; - case "#US": - image.UserStringHeap = new UserStringHeap (data); - break; - case "#Pdb": - image.PdbHeap = new PdbHeap (data); - break; - } - } - - byte [] ReadHeapData (uint offset, uint size) - { - var position = BaseStream.Position; - MoveTo (offset + image.MetadataSection.PointerToRawData); - var data = ReadBytes ((int)size); - BaseStream.Position = position; - - return data; - } - - void ReadTableHeap () - { - var heap = image.TableHeap; - - MoveTo (table_heap_offset + image.MetadataSection.PointerToRawData); - - // Reserved 4 - // MajorVersion 1 - // MinorVersion 1 - Advance (6); - - // HeapSizes 1 - var sizes = ReadByte (); - - // Reserved2 1 - Advance (1); - - // Valid 8 - heap.Valid = ReadInt64 (); - - // Sorted 8 - heap.Sorted = ReadInt64 (); - - if (image.PdbHeap != null) { - for (int i = 0; i < Mixin.TableCount; i++) { - if (!image.PdbHeap.HasTable ((Table)i)) - continue; - - heap.Tables [i].Length = image.PdbHeap.TypeSystemTableRows [i]; - } - } - - for (int i = 0; i < Mixin.TableCount; i++) { - if (!heap.HasTable ((Table)i)) - continue; - - heap.Tables [i].Length = ReadUInt32 (); - } - - SetIndexSize (image.StringHeap, sizes, 0x1); - SetIndexSize (image.GuidHeap, sizes, 0x2); - SetIndexSize (image.BlobHeap, sizes, 0x4); - - ComputeTableInformations (); - } - - static void SetIndexSize (Heap heap, uint sizes, byte flag) - { - if (heap == null) - return; - - heap.IndexSize = (sizes & flag) > 0 ? 4 : 2; - } - - int GetTableIndexSize (Table table) - { - return image.GetTableIndexSize (table); - } - - int GetCodedIndexSize (CodedIndex index) - { - return image.GetCodedIndexSize (index); - } - - void ComputeTableInformations () - { - uint offset = (uint)BaseStream.Position - table_heap_offset - image.MetadataSection.PointerToRawData; // header - - int stridx_size = image.StringHeap != null ? image.StringHeap.IndexSize : 2; - int guididx_size = image.GuidHeap != null ? image.GuidHeap.IndexSize : 2; - int blobidx_size = image.BlobHeap != null ? image.BlobHeap.IndexSize : 2; - - var heap = image.TableHeap; - var tables = heap.Tables; - - for (int i = 0; i < Mixin.TableCount; i++) { - var table = (Table)i; - if (!heap.HasTable (table)) - continue; - - int size; - switch (table) { - case Table.Module: - size = 2 // Generation - + stridx_size // Name - + (guididx_size * 3); // Mvid, EncId, EncBaseId - break; - case Table.TypeRef: - size = GetCodedIndexSize (CodedIndex.ResolutionScope) // ResolutionScope - + (stridx_size * 2); // Name, Namespace - break; - case Table.TypeDef: - size = 4 // Flags - + (stridx_size * 2) // Name, Namespace - + GetCodedIndexSize (CodedIndex.TypeDefOrRef) // BaseType - + GetTableIndexSize (Table.Field) // FieldList - + GetTableIndexSize (Table.Method); // MethodList - break; - case Table.FieldPtr: - size = GetTableIndexSize (Table.Field); // Field - break; - case Table.Field: - size = 2 // Flags - + stridx_size // Name - + blobidx_size; // Signature - break; - case Table.MethodPtr: - size = GetTableIndexSize (Table.Method); // Method - break; - case Table.Method: - size = 8 // Rva 4, ImplFlags 2, Flags 2 - + stridx_size // Name - + blobidx_size // Signature - + GetTableIndexSize (Table.Param); // ParamList - break; - case Table.ParamPtr: - size = GetTableIndexSize (Table.Param); // Param - break; - case Table.Param: - size = 4 // Flags 2, Sequence 2 - + stridx_size; // Name - break; - case Table.InterfaceImpl: - size = GetTableIndexSize (Table.TypeDef) // Class - + GetCodedIndexSize (CodedIndex.TypeDefOrRef); // Interface - break; - case Table.MemberRef: - size = GetCodedIndexSize (CodedIndex.MemberRefParent) // Class - + stridx_size // Name - + blobidx_size; // Signature - break; - case Table.Constant: - size = 2 // Type - + GetCodedIndexSize (CodedIndex.HasConstant) // Parent - + blobidx_size; // Value - break; - case Table.CustomAttribute: - size = GetCodedIndexSize (CodedIndex.HasCustomAttribute) // Parent - + GetCodedIndexSize (CodedIndex.CustomAttributeType) // Type - + blobidx_size; // Value - break; - case Table.FieldMarshal: - size = GetCodedIndexSize (CodedIndex.HasFieldMarshal) // Parent - + blobidx_size; // NativeType - break; - case Table.DeclSecurity: - size = 2 // Action - + GetCodedIndexSize (CodedIndex.HasDeclSecurity) // Parent - + blobidx_size; // PermissionSet - break; - case Table.ClassLayout: - size = 6 // PackingSize 2, ClassSize 4 - + GetTableIndexSize (Table.TypeDef); // Parent - break; - case Table.FieldLayout: - size = 4 // Offset - + GetTableIndexSize (Table.Field); // Field - break; - case Table.StandAloneSig: - size = blobidx_size; // Signature - break; - case Table.EventMap: - size = GetTableIndexSize (Table.TypeDef) // Parent - + GetTableIndexSize (Table.Event); // EventList - break; - case Table.EventPtr: - size = GetTableIndexSize (Table.Event); // Event - break; - case Table.Event: - size = 2 // Flags - + stridx_size // Name - + GetCodedIndexSize (CodedIndex.TypeDefOrRef); // EventType - break; - case Table.PropertyMap: - size = GetTableIndexSize (Table.TypeDef) // Parent - + GetTableIndexSize (Table.Property); // PropertyList - break; - case Table.PropertyPtr: - size = GetTableIndexSize (Table.Property); // Property - break; - case Table.Property: - size = 2 // Flags - + stridx_size // Name - + blobidx_size; // Type - break; - case Table.MethodSemantics: - size = 2 // Semantics - + GetTableIndexSize (Table.Method) // Method - + GetCodedIndexSize (CodedIndex.HasSemantics); // Association - break; - case Table.MethodImpl: - size = GetTableIndexSize (Table.TypeDef) // Class - + GetCodedIndexSize (CodedIndex.MethodDefOrRef) // MethodBody - + GetCodedIndexSize (CodedIndex.MethodDefOrRef); // MethodDeclaration - break; - case Table.ModuleRef: - size = stridx_size; // Name - break; - case Table.TypeSpec: - size = blobidx_size; // Signature - break; - case Table.ImplMap: - size = 2 // MappingFlags - + GetCodedIndexSize (CodedIndex.MemberForwarded) // MemberForwarded - + stridx_size // ImportName - + GetTableIndexSize (Table.ModuleRef); // ImportScope - break; - case Table.FieldRVA: - size = 4 // RVA - + GetTableIndexSize (Table.Field); // Field - break; - case Table.EncLog: - size = 8; - break; - case Table.EncMap: - size = 4; - break; - case Table.Assembly: - size = 16 // HashAlgId 4, Version 4 * 2, Flags 4 - + blobidx_size // PublicKey - + (stridx_size * 2); // Name, Culture - break; - case Table.AssemblyProcessor: - size = 4; // Processor - break; - case Table.AssemblyOS: - size = 12; // Platform 4, Version 2 * 4 - break; - case Table.AssemblyRef: - size = 12 // Version 2 * 4 + Flags 4 - + (blobidx_size * 2) // PublicKeyOrToken, HashValue - + (stridx_size * 2); // Name, Culture - break; - case Table.AssemblyRefProcessor: - size = 4 // Processor - + GetTableIndexSize (Table.AssemblyRef); // AssemblyRef - break; - case Table.AssemblyRefOS: - size = 12 // Platform 4, Version 2 * 4 - + GetTableIndexSize (Table.AssemblyRef); // AssemblyRef - break; - case Table.File: - size = 4 // Flags - + stridx_size // Name - + blobidx_size; // HashValue - break; - case Table.ExportedType: - size = 8 // Flags 4, TypeDefId 4 - + (stridx_size * 2) // Name, Namespace - + GetCodedIndexSize (CodedIndex.Implementation); // Implementation - break; - case Table.ManifestResource: - size = 8 // Offset, Flags - + stridx_size // Name - + GetCodedIndexSize (CodedIndex.Implementation); // Implementation - break; - case Table.NestedClass: - size = GetTableIndexSize (Table.TypeDef) // NestedClass - + GetTableIndexSize (Table.TypeDef); // EnclosingClass - break; - case Table.GenericParam: - size = 4 // Number, Flags - + GetCodedIndexSize (CodedIndex.TypeOrMethodDef) // Owner - + stridx_size; // Name - break; - case Table.MethodSpec: - size = GetCodedIndexSize (CodedIndex.MethodDefOrRef) // Method - + blobidx_size; // Instantiation - break; - case Table.GenericParamConstraint: - size = GetTableIndexSize (Table.GenericParam) // Owner - + GetCodedIndexSize (CodedIndex.TypeDefOrRef); // Constraint - break; - case Table.Document: - size = blobidx_size // Name - + guididx_size // HashAlgorithm - + blobidx_size // Hash - + guididx_size; // Language - break; - case Table.MethodDebugInformation: - size = GetTableIndexSize (Table.Document) // Document - + blobidx_size; // SequencePoints - break; - case Table.LocalScope: - size = GetTableIndexSize (Table.Method) // Method - + GetTableIndexSize (Table.ImportScope) // ImportScope - + GetTableIndexSize (Table.LocalVariable) // VariableList - + GetTableIndexSize (Table.LocalConstant) // ConstantList - + 4 * 2; // StartOffset, Length - break; - case Table.LocalVariable: - size = 2 // Attributes - + 2 // Index - + stridx_size; // Name - break; - case Table.LocalConstant: - size = stridx_size // Name - + blobidx_size; // Signature - break; - case Table.ImportScope: - size = GetTableIndexSize (Table.ImportScope) // Parent - + blobidx_size; - break; - case Table.StateMachineMethod: - size = GetTableIndexSize (Table.Method) // MoveNextMethod - + GetTableIndexSize (Table.Method); // KickOffMethod - break; - case Table.CustomDebugInformation: - size = GetCodedIndexSize (CodedIndex.HasCustomDebugInformation) // Parent - + guididx_size // Kind - + blobidx_size; // Value - break; - default: - throw new NotSupportedException (); - } - - tables [i].RowSize = (uint)size; - tables [i].Offset = offset; - - offset += (uint)size * tables [i].Length; - } - } - - void ReadPdbHeap () - { - var heap = image.PdbHeap; - - var buffer = new ByteBuffer (heap.data); - - heap.Id = buffer.ReadBytes (20); - heap.EntryPoint = buffer.ReadUInt32 (); - heap.TypeSystemTables = buffer.ReadInt64 (); - heap.TypeSystemTableRows = new uint [Mixin.TableCount]; - - for (int i = 0; i < Mixin.TableCount; i++) { - var table = (Table)i; - if (!heap.HasTable (table)) - continue; - - heap.TypeSystemTableRows [i] = buffer.ReadUInt32 (); - } - } - - public static Image ReadImage (Disposable stream, string file_name) - { - try { - var reader = new ImageReader (stream, file_name); - reader.ReadImage (); - return reader.image; - } - catch (EndOfStreamException e) { - throw new BadImageFormatException (stream.value.GetFileName (), e); - } - } - - public static Image ReadPortablePdb (Disposable stream, string file_name) - { - try { - var reader = new ImageReader (stream, file_name); - var length = (uint)stream.value.Length; - - reader.image.Sections = new [] { - new Section { - PointerToRawData = 0, - SizeOfRawData = length, - VirtualAddress = 0, - VirtualSize = length, - } - }; - - reader.metadata = new DataDirectory (0, length); - reader.ReadMetadata (); - return reader.image; - } - catch (EndOfStreamException e) { - throw new BadImageFormatException (stream.value.GetFileName (), e); - } - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageReader.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageReader.cs.meta deleted file mode 100644 index a001d10..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageReader.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ba04d4e3389423e47b35aaccee205576 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageWriter.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageWriter.cs deleted file mode 100644 index 061a95f..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageWriter.cs +++ /dev/null @@ -1,860 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Cil; -using MonoFN.Cecil.Metadata; -using System; -using System.IO; -using RVA = System.UInt32; - -namespace MonoFN.Cecil.PE { - - sealed class ImageWriter : BinaryStreamWriter { - - readonly ModuleDefinition module; - readonly MetadataBuilder metadata; - readonly TextMap text_map; - readonly internal Disposable stream; - - readonly string runtime_version; - - ImageDebugHeader debug_header; - - ByteBuffer win32_resources; - - const uint pe_header_size = 0x98u; - const uint section_header_size = 0x28u; - const uint file_alignment = 0x200; - const uint section_alignment = 0x2000; - const ulong image_base = 0x00400000; - - internal const RVA text_rva = 0x2000; - - readonly bool pe64; - readonly bool has_reloc; - - internal Section text; - internal Section rsrc; - internal Section reloc; - - ushort sections; - - ImageWriter (ModuleDefinition module, string runtime_version, MetadataBuilder metadata, Disposable stream, bool metadataOnly = false) - : base (stream.value) - { - this.module = module; - this.runtime_version = runtime_version; - this.text_map = metadata.text_map; - this.stream = stream; - this.metadata = metadata; - if (metadataOnly) - return; - - this.pe64 = module.Architecture == TargetArchitecture.AMD64 || module.Architecture == TargetArchitecture.IA64 || module.Architecture == TargetArchitecture.ARM64; - this.has_reloc = module.Architecture == TargetArchitecture.I386; - this.GetDebugHeader (); - this.GetWin32Resources (); - this.BuildTextMap (); - this.sections = (ushort)(has_reloc ? 2 : 1); // text + reloc? - } - - void GetDebugHeader () - { - var symbol_writer = metadata.symbol_writer; - if (symbol_writer != null) - debug_header = symbol_writer.GetDebugHeader (); - - if (module.HasDebugHeader) { - var header = module.GetDebugHeader (); - var deterministic = header.GetDeterministicEntry (); - if (deterministic == null) - return; - - debug_header = debug_header.AddDeterministicEntry (); - } - } - - void GetWin32Resources () - { - if (!module.HasImage) - return; - - DataDirectory win32_resources_directory = module.Image.Win32Resources; - var size = win32_resources_directory.Size; - - if (size > 0) { - win32_resources = module.Image.GetReaderAt (win32_resources_directory.VirtualAddress, size, (s, reader) => new ByteBuffer (reader.ReadBytes ((int)s))); - } - } - - public static ImageWriter CreateWriter (ModuleDefinition module, MetadataBuilder metadata, Disposable stream) - { - var writer = new ImageWriter (module, module.runtime_version, metadata, stream); - writer.BuildSections (); - return writer; - } - - public static ImageWriter CreateDebugWriter (ModuleDefinition module, MetadataBuilder metadata, Disposable stream) - { - var writer = new ImageWriter (module, "PDB v1.0", metadata, stream, metadataOnly: true); - var length = metadata.text_map.GetLength (); - writer.text = new Section { SizeOfRawData = length, VirtualSize = length }; - return writer; - } - - void BuildSections () - { - var has_win32_resources = win32_resources != null; - if (has_win32_resources) - sections++; - - text = CreateSection (".text", text_map.GetLength (), null); - var previous = text; - - if (has_win32_resources) { - rsrc = CreateSection (".rsrc", (uint)win32_resources.length, previous); - - PatchWin32Resources (win32_resources); - previous = rsrc; - } - - if (has_reloc) - reloc = CreateSection (".reloc", 12u, previous); - } - - Section CreateSection (string name, uint size, Section previous) - { - return new Section { - Name = name, - VirtualAddress = previous != null - ? previous.VirtualAddress + Align (previous.VirtualSize, section_alignment) - : text_rva, - VirtualSize = size, - PointerToRawData = previous != null - ? previous.PointerToRawData + previous.SizeOfRawData - : Align (GetHeaderSize (), file_alignment), - SizeOfRawData = Align (size, file_alignment) - }; - } - - static uint Align (uint value, uint align) - { - align--; - return (value + align) & ~align; - } - - void WriteDOSHeader () - { - Write (new byte [] { - // dos header start - 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - // lfanew - 0x80, 0x00, 0x00, 0x00, - // dos header end - 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, - 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, - 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, - 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, - 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, - 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, - 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20, 0x6d, - 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, - 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 - }); - } - - ushort SizeOfOptionalHeader () - { - return (ushort)(!pe64 ? 0xe0 : 0xf0); - } - - void WritePEFileHeader () - { - WriteUInt32 (0x00004550); // Magic - WriteUInt16 ((ushort)module.Architecture); // Machine - WriteUInt16 (sections); // NumberOfSections - WriteUInt32 (metadata.timestamp); - WriteUInt32 (0); // PointerToSymbolTable - WriteUInt32 (0); // NumberOfSymbols - WriteUInt16 (SizeOfOptionalHeader ()); // SizeOfOptionalHeader - - const ushort LargeAddressAware = 0x0020; - - // ExecutableImage | (!pe64 ? 32BitsMachine : LargeAddressAware) - var characteristics = (ushort)(0x0002 | (!pe64 ? 0x0100 : LargeAddressAware)); - if (module.Kind == ModuleKind.Dll || module.Kind == ModuleKind.NetModule) - characteristics |= 0x2000; - - if (module.Image != null && (module.Image.Characteristics & LargeAddressAware) != 0) - characteristics |= LargeAddressAware; - - WriteUInt16 (characteristics); // Characteristics - } - - Section LastSection () - { - if (reloc != null) - return reloc; - - if (rsrc != null) - return rsrc; - - return text; - } - - void WriteOptionalHeaders () - { - WriteUInt16 ((ushort)(!pe64 ? 0x10b : 0x20b)); // Magic - WriteUInt16 (module.linker_version); - WriteUInt32 (text.SizeOfRawData); // CodeSize - WriteUInt32 ((reloc != null ? reloc.SizeOfRawData : 0) - + (rsrc != null ? rsrc.SizeOfRawData : 0)); // InitializedDataSize - WriteUInt32 (0); // UninitializedDataSize - - var startub_stub = text_map.GetRange (TextSegment.StartupStub); - WriteUInt32 (startub_stub.Length > 0 ? startub_stub.Start : 0); // EntryPointRVA - WriteUInt32 (text_rva); // BaseOfCode - - if (!pe64) { - WriteUInt32 (0); // BaseOfData - WriteUInt32 ((uint)image_base); // ImageBase - } else { - WriteUInt64 (image_base); // ImageBase - } - - WriteUInt32 (section_alignment); // SectionAlignment - WriteUInt32 (file_alignment); // FileAlignment - - WriteUInt16 (4); // OSMajor - WriteUInt16 (0); // OSMinor - WriteUInt16 (0); // UserMajor - WriteUInt16 (0); // UserMinor - WriteUInt16 (module.subsystem_major); // SubSysMajor - WriteUInt16 (module.subsystem_minor); // SubSysMinor - WriteUInt32 (0); // Reserved - - var last_section = LastSection (); - WriteUInt32 (last_section.VirtualAddress + Align (last_section.VirtualSize, section_alignment)); // ImageSize - WriteUInt32 (text.PointerToRawData); // HeaderSize - - WriteUInt32 (0); // Checksum - WriteUInt16 (GetSubSystem ()); // SubSystem - WriteUInt16 ((ushort)module.Characteristics); // DLLFlags - - if (!pe64) { - const uint stack_reserve = 0x100000; - const uint stack_commit = 0x1000; - const uint heap_reserve = 0x100000; - const uint heap_commit = 0x1000; - - WriteUInt32 (stack_reserve); - WriteUInt32 (stack_commit); - WriteUInt32 (heap_reserve); - WriteUInt32 (heap_commit); - } else { - const ulong stack_reserve = 0x400000; - const ulong stack_commit = 0x4000; - const ulong heap_reserve = 0x100000; - const ulong heap_commit = 0x2000; - - WriteUInt64 (stack_reserve); - WriteUInt64 (stack_commit); - WriteUInt64 (heap_reserve); - WriteUInt64 (heap_commit); - } - - WriteUInt32 (0); // LoaderFlags - WriteUInt32 (16); // NumberOfDataDir - - WriteZeroDataDirectory (); // ExportTable - WriteDataDirectory (text_map.GetDataDirectory (TextSegment.ImportDirectory)); // ImportTable - if (rsrc != null) { // ResourceTable - WriteUInt32 (rsrc.VirtualAddress); - WriteUInt32 (rsrc.VirtualSize); - } else - WriteZeroDataDirectory (); - - WriteZeroDataDirectory (); // ExceptionTable - WriteZeroDataDirectory (); // CertificateTable - WriteUInt32 (reloc != null ? reloc.VirtualAddress : 0); // BaseRelocationTable - WriteUInt32 (reloc != null ? reloc.VirtualSize : 0); - - if (text_map.GetLength (TextSegment.DebugDirectory) > 0) { - WriteUInt32 (text_map.GetRVA (TextSegment.DebugDirectory)); - WriteUInt32 ((uint)(debug_header.Entries.Length * ImageDebugDirectory.Size)); - } else - WriteZeroDataDirectory (); - - WriteZeroDataDirectory (); // Copyright - WriteZeroDataDirectory (); // GlobalPtr - WriteZeroDataDirectory (); // TLSTable - WriteZeroDataDirectory (); // LoadConfigTable - WriteZeroDataDirectory (); // BoundImport - WriteDataDirectory (text_map.GetDataDirectory (TextSegment.ImportAddressTable)); // IAT - WriteZeroDataDirectory (); // DelayImportDesc - WriteDataDirectory (text_map.GetDataDirectory (TextSegment.CLIHeader)); // CLIHeader - WriteZeroDataDirectory (); // Reserved - } - - void WriteZeroDataDirectory () - { - WriteUInt32 (0); - WriteUInt32 (0); - } - - ushort GetSubSystem () - { - switch (module.Kind) { - case ModuleKind.Console: - case ModuleKind.Dll: - case ModuleKind.NetModule: - return 0x3; - case ModuleKind.Windows: - return 0x2; - default: - throw new ArgumentOutOfRangeException (); - } - } - - void WriteSectionHeaders () - { - WriteSection (text, 0x60000020); - - if (rsrc != null) - WriteSection (rsrc, 0x40000040); - - if (reloc != null) - WriteSection (reloc, 0x42000040); - } - - void WriteSection (Section section, uint characteristics) - { - var name = new byte [8]; - var sect_name = section.Name; - for (int i = 0; i < sect_name.Length; i++) - name [i] = (byte)sect_name [i]; - - WriteBytes (name); - WriteUInt32 (section.VirtualSize); - WriteUInt32 (section.VirtualAddress); - WriteUInt32 (section.SizeOfRawData); - WriteUInt32 (section.PointerToRawData); - WriteUInt32 (0); // PointerToRelocations - WriteUInt32 (0); // PointerToLineNumbers - WriteUInt16 (0); // NumberOfRelocations - WriteUInt16 (0); // NumberOfLineNumbers - WriteUInt32 (characteristics); - } - - uint GetRVAFileOffset (Section section, RVA rva) - { - return section.PointerToRawData + rva - section.VirtualAddress; - } - - void MoveTo (uint pointer) - { - BaseStream.Seek (pointer, SeekOrigin.Begin); - } - - void MoveToRVA (Section section, RVA rva) - { - BaseStream.Seek (GetRVAFileOffset (section, rva), SeekOrigin.Begin); - } - - void MoveToRVA (TextSegment segment) - { - MoveToRVA (text, text_map.GetRVA (segment)); - } - - void WriteRVA (RVA rva) - { - if (!pe64) - WriteUInt32 (rva); - else - WriteUInt64 (rva); - } - - void PrepareSection (Section section) - { - MoveTo (section.PointerToRawData); - - const int buffer_size = 4096; - - if (section.SizeOfRawData <= buffer_size) { - Write (new byte [section.SizeOfRawData]); - MoveTo (section.PointerToRawData); - return; - } - - var written = 0; - var buffer = new byte [buffer_size]; - while (written != section.SizeOfRawData) { - var write_size = System.Math.Min ((int)section.SizeOfRawData - written, buffer_size); - Write (buffer, 0, write_size); - written += write_size; - } - - MoveTo (section.PointerToRawData); - } - - void WriteText () - { - PrepareSection (text); - - // ImportAddressTable - - if (has_reloc) { - WriteRVA (text_map.GetRVA (TextSegment.ImportHintNameTable)); - WriteRVA (0); - } - - // CLIHeader - - WriteUInt32 (0x48); - WriteUInt16 (2); - WriteUInt16 ((ushort)((module.Runtime <= TargetRuntime.Net_1_1) ? 0 : 5)); - - WriteUInt32 (text_map.GetRVA (TextSegment.MetadataHeader)); - WriteUInt32 (GetMetadataLength ()); - WriteUInt32 ((uint)module.Attributes); - WriteUInt32 (metadata.entry_point.ToUInt32 ()); - WriteDataDirectory (text_map.GetDataDirectory (TextSegment.Resources)); - WriteDataDirectory (text_map.GetDataDirectory (TextSegment.StrongNameSignature)); - WriteZeroDataDirectory (); // CodeManagerTable - WriteZeroDataDirectory (); // VTableFixups - WriteZeroDataDirectory (); // ExportAddressTableJumps - WriteZeroDataDirectory (); // ManagedNativeHeader - - // Code - - MoveToRVA (TextSegment.Code); - WriteBuffer (metadata.code); - - // Resources - - MoveToRVA (TextSegment.Resources); - WriteBuffer (metadata.resources); - - // Data - - if (metadata.data.length > 0) { - MoveToRVA (TextSegment.Data); - WriteBuffer (metadata.data); - } - - // StrongNameSignature - // stays blank - - // MetadataHeader - - MoveToRVA (TextSegment.MetadataHeader); - WriteMetadataHeader (); - - WriteMetadata (); - - // DebugDirectory - if (text_map.GetLength (TextSegment.DebugDirectory) > 0) { - MoveToRVA (TextSegment.DebugDirectory); - WriteDebugDirectory (); - } - - if (!has_reloc) - return; - - // ImportDirectory - MoveToRVA (TextSegment.ImportDirectory); - WriteImportDirectory (); - - // StartupStub - MoveToRVA (TextSegment.StartupStub); - WriteStartupStub (); - } - - uint GetMetadataLength () - { - return text_map.GetRVA (TextSegment.DebugDirectory) - text_map.GetRVA (TextSegment.MetadataHeader); - } - - public void WriteMetadataHeader () - { - WriteUInt32 (0x424a5342); // Signature - WriteUInt16 (1); // MajorVersion - WriteUInt16 (1); // MinorVersion - WriteUInt32 (0); // Reserved - - var version = GetZeroTerminatedString (runtime_version); - WriteUInt32 ((uint)version.Length); - WriteBytes (version); - WriteUInt16 (0); // Flags - WriteUInt16 (GetStreamCount ()); - - uint offset = text_map.GetRVA (TextSegment.TableHeap) - text_map.GetRVA (TextSegment.MetadataHeader); - - WriteStreamHeader (ref offset, TextSegment.TableHeap, "#~"); - WriteStreamHeader (ref offset, TextSegment.StringHeap, "#Strings"); - WriteStreamHeader (ref offset, TextSegment.UserStringHeap, "#US"); - WriteStreamHeader (ref offset, TextSegment.GuidHeap, "#GUID"); - WriteStreamHeader (ref offset, TextSegment.BlobHeap, "#Blob"); - WriteStreamHeader (ref offset, TextSegment.PdbHeap, "#Pdb"); - } - - ushort GetStreamCount () - { - return (ushort)( - 1 // #~ - + 1 // #Strings - + (metadata.user_string_heap.IsEmpty ? 0 : 1) // #US - + (metadata.guid_heap.IsEmpty ? 0 : 1) // GUID - + (metadata.blob_heap.IsEmpty ? 0 : 1) - + (metadata.pdb_heap == null ? 0 : 1)); // #Blob - } - - void WriteStreamHeader (ref uint offset, TextSegment heap, string name) - { - var length = (uint)text_map.GetLength (heap); - if (length == 0) - return; - - WriteUInt32 (offset); - WriteUInt32 (length); - WriteBytes (GetZeroTerminatedString (name)); - offset += length; - } - - static int GetZeroTerminatedStringLength (string @string) - { - return (@string.Length + 1 + 3) & ~3; - } - - static byte [] GetZeroTerminatedString (string @string) - { - return GetString (@string, GetZeroTerminatedStringLength (@string)); - } - - static byte [] GetSimpleString (string @string) - { - return GetString (@string, @string.Length); - } - - static byte [] GetString (string @string, int length) - { - var bytes = new byte [length]; - for (int i = 0; i < @string.Length; i++) - bytes [i] = (byte)@string [i]; - - return bytes; - } - - public void WriteMetadata () - { - WriteHeap (TextSegment.TableHeap, metadata.table_heap); - WriteHeap (TextSegment.StringHeap, metadata.string_heap); - WriteHeap (TextSegment.UserStringHeap, metadata.user_string_heap); - WriteHeap (TextSegment.GuidHeap, metadata.guid_heap); - WriteHeap (TextSegment.BlobHeap, metadata.blob_heap); - WriteHeap (TextSegment.PdbHeap, metadata.pdb_heap); - } - - void WriteHeap (TextSegment heap, HeapBuffer buffer) - { - if (buffer == null || buffer.IsEmpty) - return; - - MoveToRVA (heap); - WriteBuffer (buffer); - } - - void WriteDebugDirectory () - { - var data_start = (int)BaseStream.Position + (debug_header.Entries.Length * ImageDebugDirectory.Size); - - for (var i = 0; i < debug_header.Entries.Length; i++) { - var entry = debug_header.Entries [i]; - var directory = entry.Directory; - WriteInt32 (directory.Characteristics); - WriteInt32 (directory.TimeDateStamp); - WriteInt16 (directory.MajorVersion); - WriteInt16 (directory.MinorVersion); - WriteInt32 ((int)directory.Type); - WriteInt32 (directory.SizeOfData); - WriteInt32 (directory.AddressOfRawData); - WriteInt32 (data_start); - - data_start += entry.Data.Length; - } - - for (var i = 0; i < debug_header.Entries.Length; i++) { - var entry = debug_header.Entries [i]; - WriteBytes (entry.Data); - } - } - - void WriteImportDirectory () - { - WriteUInt32 (text_map.GetRVA (TextSegment.ImportDirectory) + 40); // ImportLookupTable - WriteUInt32 (0); // DateTimeStamp - WriteUInt32 (0); // ForwarderChain - WriteUInt32 (text_map.GetRVA (TextSegment.ImportHintNameTable) + 14); - WriteUInt32 (text_map.GetRVA (TextSegment.ImportAddressTable)); - Advance (20); - - // ImportLookupTable - WriteUInt32 (text_map.GetRVA (TextSegment.ImportHintNameTable)); - - // ImportHintNameTable - MoveToRVA (TextSegment.ImportHintNameTable); - - WriteUInt16 (0); // Hint - WriteBytes (GetRuntimeMain ()); - WriteByte (0); - WriteBytes (GetSimpleString ("mscoree.dll")); - WriteUInt16 (0); - } - - byte [] GetRuntimeMain () - { - return module.Kind == ModuleKind.Dll || module.Kind == ModuleKind.NetModule - ? GetSimpleString ("_CorDllMain") - : GetSimpleString ("_CorExeMain"); - } - - void WriteStartupStub () - { - switch (module.Architecture) { - case TargetArchitecture.I386: - WriteUInt16 (0x25ff); - WriteUInt32 ((uint)image_base + text_map.GetRVA (TextSegment.ImportAddressTable)); - return; - default: - throw new NotSupportedException (); - } - } - - void WriteRsrc () - { - PrepareSection (rsrc); - WriteBuffer (win32_resources); - } - - void WriteReloc () - { - PrepareSection (reloc); - - var reloc_rva = text_map.GetRVA (TextSegment.StartupStub); - reloc_rva += module.Architecture == TargetArchitecture.IA64 ? 0x20u : 2; - var page_rva = reloc_rva & ~0xfffu; - - WriteUInt32 (page_rva); // PageRVA - WriteUInt32 (0x000c); // Block Size - - switch (module.Architecture) { - case TargetArchitecture.I386: - WriteUInt32 (0x3000 + reloc_rva - page_rva); - break; - default: - throw new NotSupportedException (); - } - } - - public void WriteImage () - { - WriteDOSHeader (); - WritePEFileHeader (); - WriteOptionalHeaders (); - WriteSectionHeaders (); - WriteText (); - if (rsrc != null) - WriteRsrc (); - if (reloc != null) - WriteReloc (); - Flush (); - } - - void BuildTextMap () - { - var map = text_map; - - map.AddMap (TextSegment.Code, metadata.code.length, !pe64 ? 4 : 16); - map.AddMap (TextSegment.Resources, metadata.resources.length, 8); - map.AddMap (TextSegment.Data, metadata.data.length, 4); - if (metadata.data.length > 0) - metadata.table_heap.FixupData (map.GetRVA (TextSegment.Data)); - map.AddMap (TextSegment.StrongNameSignature, GetStrongNameLength (), 4); - - BuildMetadataTextMap (); - - int debug_dir_len = 0; - if (debug_header != null && debug_header.HasEntries) { - var directories_len = debug_header.Entries.Length * ImageDebugDirectory.Size; - var data_address = (int)map.GetNextRVA (TextSegment.BlobHeap) + directories_len; - var data_len = 0; - - for (var i = 0; i < debug_header.Entries.Length; i++) { - var entry = debug_header.Entries [i]; - var directory = entry.Directory; - - directory.AddressOfRawData = entry.Data.Length == 0 ? 0 : data_address; - entry.Directory = directory; - - data_len += entry.Data.Length; - data_address += data_len; - } - - debug_dir_len = directories_len + data_len; - } - - map.AddMap (TextSegment.DebugDirectory, debug_dir_len, 4); - - if (!has_reloc) { - var start = map.GetNextRVA (TextSegment.DebugDirectory); - map.AddMap (TextSegment.ImportDirectory, new Range (start, 0)); - map.AddMap (TextSegment.ImportHintNameTable, new Range (start, 0)); - map.AddMap (TextSegment.StartupStub, new Range (start, 0)); - return; - } - - RVA import_dir_rva = map.GetNextRVA (TextSegment.DebugDirectory); - RVA import_hnt_rva = import_dir_rva + 48u; - import_hnt_rva = (import_hnt_rva + 15u) & ~15u; - uint import_dir_len = (import_hnt_rva - import_dir_rva) + 27u; - - RVA startup_stub_rva = import_dir_rva + import_dir_len; - startup_stub_rva = module.Architecture == TargetArchitecture.IA64 - ? (startup_stub_rva + 15u) & ~15u - : 2 + ((startup_stub_rva + 3u) & ~3u); - - map.AddMap (TextSegment.ImportDirectory, new Range (import_dir_rva, import_dir_len)); - map.AddMap (TextSegment.ImportHintNameTable, new Range (import_hnt_rva, 0)); - map.AddMap (TextSegment.StartupStub, new Range (startup_stub_rva, GetStartupStubLength ())); - } - - public void BuildMetadataTextMap () - { - var map = text_map; - - map.AddMap (TextSegment.MetadataHeader, GetMetadataHeaderLength (module.RuntimeVersion)); - map.AddMap (TextSegment.TableHeap, metadata.table_heap.length, 4); - map.AddMap (TextSegment.StringHeap, metadata.string_heap.length, 4); - map.AddMap (TextSegment.UserStringHeap, metadata.user_string_heap.IsEmpty ? 0 : metadata.user_string_heap.length, 4); - map.AddMap (TextSegment.GuidHeap, metadata.guid_heap.length, 4); - map.AddMap (TextSegment.BlobHeap, metadata.blob_heap.IsEmpty ? 0 : metadata.blob_heap.length, 4); - map.AddMap (TextSegment.PdbHeap, metadata.pdb_heap == null ? 0 : metadata.pdb_heap.length, 4); - } - - uint GetStartupStubLength () - { - switch (module.Architecture) { - case TargetArchitecture.I386: - return 6; - default: - throw new NotSupportedException (); - } - } - - int GetMetadataHeaderLength (string runtimeVersion) - { - return - // MetadataHeader - 20 + GetZeroTerminatedStringLength (runtimeVersion) - // #~ header - + 12 - // #Strings header - + 20 - // #US header - + (metadata.user_string_heap.IsEmpty ? 0 : 12) - // #GUID header - + 16 - // #Blob header - + (metadata.blob_heap.IsEmpty ? 0 : 16) - // - + (metadata.pdb_heap == null ? 0 : 16); - } - - int GetStrongNameLength () - { - if (module.kind == ModuleKind.NetModule || module.Assembly == null) - return 0; - - var public_key = module.Assembly.Name.PublicKey; - if (public_key.IsNullOrEmpty ()) - return 0; - - // in fx 2.0 the key may be from 384 to 16384 bits - // so we must calculate the signature size based on - // the size of the public key (minus the 32 byte header) - int size = public_key.Length; - if (size > 32) - return size - 32; - - // note: size == 16 for the ECMA "key" which is replaced - // by the runtime with a 1024 bits key (128 bytes) - - return 128; // default strongname signature size - } - - public DataDirectory GetStrongNameSignatureDirectory () - { - return text_map.GetDataDirectory (TextSegment.StrongNameSignature); - } - - public uint GetHeaderSize () - { - return pe_header_size + SizeOfOptionalHeader () + (sections * section_header_size); - } - - void PatchWin32Resources (ByteBuffer resources) - { - PatchResourceDirectoryTable (resources); - } - - void PatchResourceDirectoryTable (ByteBuffer resources) - { - resources.Advance (12); - - var entries = resources.ReadUInt16 () + resources.ReadUInt16 (); - - for (int i = 0; i < entries; i++) - PatchResourceDirectoryEntry (resources); - } - - void PatchResourceDirectoryEntry (ByteBuffer resources) - { - resources.Advance (4); - var child = resources.ReadUInt32 (); - - var position = resources.position; - resources.position = (int)child & 0x7fffffff; - - if ((child & 0x80000000) != 0) - PatchResourceDirectoryTable (resources); - else - PatchResourceDataEntry (resources); - - resources.position = position; - } - - void PatchResourceDataEntry (ByteBuffer resources) - { - var rva = resources.ReadUInt32 (); - resources.position -= 4; - - resources.WriteUInt32 (rva - module.Image.Win32Resources.VirtualAddress + rsrc.VirtualAddress); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageWriter.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageWriter.cs.meta deleted file mode 100644 index c230acb..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/ImageWriter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 88ebae078ed1c8346be0a945ce3b03b0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Section.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Section.cs deleted file mode 100644 index 9c52503..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Section.cs +++ /dev/null @@ -1,22 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using RVA = System.UInt32; - -namespace MonoFN.Cecil.PE { - - sealed class Section { - public string Name; - public RVA VirtualAddress; - public uint VirtualSize; - public uint SizeOfRawData; - public uint PointerToRawData; - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Section.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Section.cs.meta deleted file mode 100644 index 33d91fb..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/Section.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: dc33915bdaaf42a428f8a4694e9611a8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/TextMap.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/TextMap.cs deleted file mode 100644 index fbe06e2..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/TextMap.cs +++ /dev/null @@ -1,106 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using RVA = System.UInt32; - -namespace MonoFN.Cecil.PE { - - enum TextSegment { - ImportAddressTable, - CLIHeader, - Code, - Resources, - Data, - StrongNameSignature, - - // Metadata - MetadataHeader, - TableHeap, - StringHeap, - UserStringHeap, - GuidHeap, - BlobHeap, - PdbHeap, - // End Metadata - - DebugDirectory, - ImportDirectory, - ImportHintNameTable, - StartupStub, - } - - sealed class TextMap { - - readonly Range [] map = new Range [17 /*Enum.GetValues (typeof (TextSegment)).Length*/]; - - public void AddMap (TextSegment segment, int length) - { - map [(int)segment] = new Range (GetStart (segment), (uint)length); - } - - public void AddMap (TextSegment segment, int length, int align) - { - align--; - - AddMap (segment, (length + align) & ~align); - } - - public void AddMap (TextSegment segment, Range range) - { - map [(int)segment] = range; - } - - public Range GetRange (TextSegment segment) - { - return map [(int)segment]; - } - - public DataDirectory GetDataDirectory (TextSegment segment) - { - var range = map [(int)segment]; - - return new DataDirectory (range.Length == 0 ? 0 : range.Start, range.Length); - } - - public RVA GetRVA (TextSegment segment) - { - return map [(int)segment].Start; - } - - public RVA GetNextRVA (TextSegment segment) - { - var i = (int)segment; - return map [i].Start + map [i].Length; - } - - public int GetLength (TextSegment segment) - { - return (int)map [(int)segment].Length; - } - - RVA GetStart (TextSegment segment) - { - var index = (int)segment; - return index == 0 ? ImageWriter.text_rva : ComputeStart (index); - } - - RVA ComputeStart (int index) - { - index--; - return map [index].Start + map [index].Length; - } - - public uint GetLength () - { - var range = map [(int)TextSegment.StartupStub]; - return range.Start - ImageWriter.text_rva + range.Length; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/TextMap.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/TextMap.cs.meta deleted file mode 100644 index 93ceea3..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.PE/TextMap.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1d36ca0589eb8014fa28bc58a88ae85f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Tests.props b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Tests.props deleted file mode 100644 index bd6df1f..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.Tests.props +++ /dev/null @@ -1,16 +0,0 @@ - - - true - - - - 3.11.0 - - - 15.9.0 - - - 3.12.0 - - - diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.meta deleted file mode 100644 index 835dc15..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 9a32c41438af560498f0e8ae5548097a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nunit b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nunit deleted file mode 100644 index 2acfc12..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nunit +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nunit.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nunit.meta deleted file mode 100644 index 0163c57..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nunit.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 70249fc3714c2ba43bb69eeceaf02171 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nuspec b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nuspec deleted file mode 100644 index 626c5ac..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nuspec +++ /dev/null @@ -1,42 +0,0 @@ - - - - Mono.Cecil - 0.11.4.0 - Mono.Cecil - Jb Evain - Jb Evain - MIT - false - http://github.com/jbevain/cecil/ - Cecil is a library written by Jb Evain to generate and inspect programs and libraries in the ECMA CIL format. - Cecil is a library written by Jb Evain to generate and inspect programs and libraries in the ECMA CIL format. It has full support for generics, and support some debugging symbol format. In simple English, with Cecil, you can load existing managed assemblies, browse all the contained types, modify them on the fly and save back to the disk the modified assembly. - en-US - assembly assemblies module modules il cil msil bytecode reflection injection cecil mono aop - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nuspec.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nuspec.meta deleted file mode 100644 index 033480e..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil.nuspec.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 9ab5a3af6caf6d14da0bad821a809a27 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ArrayType.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ArrayType.cs deleted file mode 100644 index df72aab..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ArrayType.cs +++ /dev/null @@ -1,145 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; -using System.Text; -using System.Threading; -using MD = MonoFN.Cecil.Metadata; - -namespace MonoFN.Cecil { - - public struct ArrayDimension { - - int? lower_bound; - int? upper_bound; - - public int? LowerBound { - get { return lower_bound; } - set { lower_bound = value; } - } - - public int? UpperBound { - get { return upper_bound; } - set { upper_bound = value; } - } - - public bool IsSized { - get { return lower_bound.HasValue || upper_bound.HasValue; } - } - - public ArrayDimension (int? lowerBound, int? upperBound) - { - this.lower_bound = lowerBound; - this.upper_bound = upperBound; - } - - public override string ToString () - { - return !IsSized - ? string.Empty - : lower_bound + "..." + upper_bound; - } - } - - public sealed class ArrayType : TypeSpecification { - - Collection dimensions; - - public Collection Dimensions { - get { - if (dimensions != null) - return dimensions; - - var empty_dimensions = new Collection (); - empty_dimensions.Add (new ArrayDimension ()); - - Interlocked.CompareExchange (ref dimensions, empty_dimensions, null); - - return dimensions; - } - } - - public int Rank { - get { return dimensions == null ? 1 : dimensions.Count; } - } - - public bool IsVector { - get { - if (dimensions == null) - return true; - - if (dimensions.Count > 1) - return false; - - var dimension = dimensions [0]; - - return !dimension.IsSized; - } - } - - public override bool IsValueType { - get { return false; } - set { throw new InvalidOperationException (); } - } - - public override string Name { - get { return base.Name + Suffix; } - } - - public override string FullName { - get { return base.FullName + Suffix; } - } - - string Suffix { - get { - if (IsVector) - return "[]"; - - var suffix = new StringBuilder (); - suffix.Append ("["); - for (int i = 0; i < dimensions.Count; i++) { - if (i > 0) - suffix.Append (","); - - suffix.Append (dimensions [i].ToString ()); - } - suffix.Append ("]"); - - return suffix.ToString (); - } - } - - public override bool IsArray { - get { return true; } - } - - public ArrayType (TypeReference type) - : base (type) - { - Mixin.CheckType (type); - this.etype = MD.ElementType.Array; - } - - public ArrayType (TypeReference type, int rank) - : this (type) - { - Mixin.CheckType (type); - - if (rank == 1) - return; - - dimensions = new Collection (rank); - for (int i = 0; i < rank; i++) - dimensions.Add (new ArrayDimension ()); - this.etype = MD.ElementType.Array; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ArrayType.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ArrayType.cs.meta deleted file mode 100644 index bace606..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ArrayType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7add098db82a032428c139b59f0878be -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyDefinition.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyDefinition.cs deleted file mode 100644 index de9ffde..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyDefinition.cs +++ /dev/null @@ -1,189 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; -using System.IO; -using System.Threading; - -namespace MonoFN.Cecil { - - public sealed class AssemblyDefinition : ICustomAttributeProvider, ISecurityDeclarationProvider, IDisposable { - - AssemblyNameDefinition name; - - internal ModuleDefinition main_module; - Collection modules; - Collection custom_attributes; - Collection security_declarations; - - public AssemblyNameDefinition Name { - get { return name; } - set { name = value; } - } - - public string FullName { - get { return name != null ? name.FullName : string.Empty; } - } - - public MetadataToken MetadataToken { - get { return new MetadataToken (TokenType.Assembly, 1); } - set { } - } - - public Collection Modules { - get { - if (modules != null) - return modules; - - if (main_module.HasImage) - return main_module.Read (ref modules, this, (_, reader) => reader.ReadModules ()); - - Interlocked.CompareExchange (ref modules, new Collection (1) { main_module }, null); - return modules; - } - } - - public ModuleDefinition MainModule { - get { return main_module; } - } - - public MethodDefinition EntryPoint { - get { return main_module.EntryPoint; } - set { main_module.EntryPoint = value; } - } - - public bool HasCustomAttributes { - get { - if (custom_attributes != null) - return custom_attributes.Count > 0; - - return this.GetHasCustomAttributes (main_module); - } - } - - public Collection CustomAttributes { - get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, main_module)); } - } - - public bool HasSecurityDeclarations { - get { - if (security_declarations != null) - return security_declarations.Count > 0; - - return this.GetHasSecurityDeclarations (main_module); - } - } - - public Collection SecurityDeclarations { - get { return security_declarations ?? (this.GetSecurityDeclarations (ref security_declarations, main_module)); } - } - - internal AssemblyDefinition () - { - } - - public void Dispose () - { - if (this.modules == null) { - main_module.Dispose (); - return; - } - - var modules = this.Modules; - for (int i = 0; i < modules.Count; i++) - modules [i].Dispose (); - } - public static AssemblyDefinition CreateAssembly (AssemblyNameDefinition assemblyName, string moduleName, ModuleKind kind) - { - return CreateAssembly (assemblyName, moduleName, new ModuleParameters { Kind = kind }); - } - - public static AssemblyDefinition CreateAssembly (AssemblyNameDefinition assemblyName, string moduleName, ModuleParameters parameters) - { - if (assemblyName == null) - throw new ArgumentNullException ("assemblyName"); - if (moduleName == null) - throw new ArgumentNullException ("moduleName"); - Mixin.CheckParameters (parameters); - if (parameters.Kind == ModuleKind.NetModule) - throw new ArgumentException ("kind"); - - var assembly = ModuleDefinition.CreateModule (moduleName, parameters).Assembly; - assembly.Name = assemblyName; - - return assembly; - } - - public static AssemblyDefinition ReadAssembly (string fileName) - { - return ReadAssembly (ModuleDefinition.ReadModule (fileName)); - } - - public static AssemblyDefinition ReadAssembly (string fileName, ReaderParameters parameters) - { - return ReadAssembly (ModuleDefinition.ReadModule (fileName, parameters)); - } - - public static AssemblyDefinition ReadAssembly (Stream stream) - { - return ReadAssembly (ModuleDefinition.ReadModule (stream)); - } - - public static AssemblyDefinition ReadAssembly (Stream stream, ReaderParameters parameters) - { - return ReadAssembly (ModuleDefinition.ReadModule (stream, parameters)); - } - - static AssemblyDefinition ReadAssembly (ModuleDefinition module) - { - var assembly = module.Assembly; - if (assembly == null) - throw new ArgumentException (); - - return assembly; - } - - public void Write (string fileName) - { - Write (fileName, new WriterParameters ()); - } - - public void Write (string fileName, WriterParameters parameters) - { - main_module.Write (fileName, parameters); - } - - public void Write () - { - main_module.Write (); - } - - public void Write (WriterParameters parameters) - { - main_module.Write (parameters); - } - - public void Write (Stream stream) - { - Write (stream, new WriterParameters ()); - } - - public void Write (Stream stream, WriterParameters parameters) - { - main_module.Write (stream, parameters); - } - - public override string ToString () - { - return this.FullName; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyDefinition.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyDefinition.cs.meta deleted file mode 100644 index d66f03d..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyDefinition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1c1ac0fc48f2d424f9c0d9fa74b16b07 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyFlags.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyFlags.cs deleted file mode 100644 index a5f83a7..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyFlags.cs +++ /dev/null @@ -1,24 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - [Flags] - public enum AssemblyAttributes : uint { - PublicKey = 0x0001, - SideBySideCompatible = 0x0000, - Retargetable = 0x0100, - WindowsRuntime = 0x0200, - DisableJITCompileOptimizer = 0x4000, - EnableJITCompileTracking = 0x8000, - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyFlags.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyFlags.cs.meta deleted file mode 100644 index d7c8791..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyFlags.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 257c8151138cda34dafbe0ca56ebedf4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyHashAlgorithm.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyHashAlgorithm.cs deleted file mode 100644 index fb0cc5f..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyHashAlgorithm.cs +++ /dev/null @@ -1,22 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public enum AssemblyHashAlgorithm : uint { - None = 0x0000, - MD5 = 0x8003, - SHA1 = 0x8004, - SHA256 = 0x800C, - SHA384 = 0x800D, - SHA512 = 0x800E, - Reserved = 0x8003, // MD5 - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyHashAlgorithm.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyHashAlgorithm.cs.meta deleted file mode 100644 index 98687b5..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyHashAlgorithm.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b200bdec09584af41bd3f656e091cccf -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyInfo.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyInfo.cs deleted file mode 100644 index 45534f1..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyInfo.cs +++ /dev/null @@ -1,22 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle (Consts.AssemblyName)] - -[assembly: Guid ("fd225bb4-fa53-44b2-a6db-85f5e48dcb54")] - -[assembly: InternalsVisibleTo ("MonoFN.Cecil.Tests, PublicKey=" + Consts.PublicKey)] -[assembly: InternalsVisibleTo ("MonoFN.Cecil.Pdb, PublicKey=" + Consts.PublicKey)] -[assembly: InternalsVisibleTo ("MonoFN.Cecil.Mdb, PublicKey=" + Consts.PublicKey)] -[assembly: InternalsVisibleTo ("MonoFN.Cecil.Rocks, PublicKey=" + Consts.PublicKey)] diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyInfo.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyInfo.cs.meta deleted file mode 100644 index 715025d..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyInfo.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ff23d7231ddfa574b816532360874834 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyLinkedResource.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyLinkedResource.cs deleted file mode 100644 index de592ae..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyLinkedResource.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public sealed class AssemblyLinkedResource : Resource { - - AssemblyNameReference reference; - - public AssemblyNameReference Assembly { - get { return reference; } - set { reference = value; } - } - - public override ResourceType ResourceType { - get { return ResourceType.AssemblyLinked; } - } - - public AssemblyLinkedResource (string name, ManifestResourceAttributes flags) - : base (name, flags) - { - } - - public AssemblyLinkedResource (string name, ManifestResourceAttributes flags, AssemblyNameReference reference) - : base (name, flags) - { - this.reference = reference; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyLinkedResource.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyLinkedResource.cs.meta deleted file mode 100644 index 259e540..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyLinkedResource.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c3d5a207fc55ac5419e42c86cef15db0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameDefinition.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameDefinition.cs deleted file mode 100644 index b46e1b9..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameDefinition.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - public sealed class AssemblyNameDefinition : AssemblyNameReference { - - public override byte [] Hash { - get { return Empty.Array; } - } - - internal AssemblyNameDefinition () - { - this.token = new MetadataToken (TokenType.Assembly, 1); - } - - public AssemblyNameDefinition (string name, Version version) - : base (name, version) - { - this.token = new MetadataToken (TokenType.Assembly, 1); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameDefinition.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameDefinition.cs.meta deleted file mode 100644 index 7409717..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameDefinition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 68b90f4f023a67e4db7ddb52802ca21e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameReference.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameReference.cs deleted file mode 100644 index d0b0585..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameReference.cs +++ /dev/null @@ -1,269 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; -using System.Globalization; -using System.Security.Cryptography; -using System.Text; -using System.Threading; - -namespace MonoFN.Cecil { - - public class AssemblyNameReference : IMetadataScope { - - string name; - string culture; - Version version; - uint attributes; - byte [] public_key; - byte [] public_key_token; - AssemblyHashAlgorithm hash_algorithm; - byte [] hash; - - internal MetadataToken token; - - string full_name; - - public string Name { - get { return name; } - set { - name = value; - full_name = null; - } - } - - public string Culture { - get { return culture; } - set { - culture = value; - full_name = null; - } - } - - public Version Version { - get { return version; } - set { - version = Mixin.CheckVersion (value); - full_name = null; - } - } - - public AssemblyAttributes Attributes { - get { return (AssemblyAttributes)attributes; } - set { attributes = (uint)value; } - } - - public bool HasPublicKey { - get { return attributes.GetAttributes ((uint)AssemblyAttributes.PublicKey); } - set { attributes = attributes.SetAttributes ((uint)AssemblyAttributes.PublicKey, value); } - } - - public bool IsSideBySideCompatible { - get { return attributes.GetAttributes ((uint)AssemblyAttributes.SideBySideCompatible); } - set { attributes = attributes.SetAttributes ((uint)AssemblyAttributes.SideBySideCompatible, value); } - } - - public bool IsRetargetable { - get { return attributes.GetAttributes ((uint)AssemblyAttributes.Retargetable); } - set { attributes = attributes.SetAttributes ((uint)AssemblyAttributes.Retargetable, value); } - } - - public bool IsWindowsRuntime { - get { return attributes.GetAttributes ((uint)AssemblyAttributes.WindowsRuntime); } - set { attributes = attributes.SetAttributes ((uint)AssemblyAttributes.WindowsRuntime, value); } - } - - public byte [] PublicKey { - get { return public_key ?? Empty.Array; } - set { - public_key = value; - HasPublicKey = !public_key.IsNullOrEmpty (); - public_key_token = null; - full_name = null; - } - } - - public byte [] PublicKeyToken { - get { - if (public_key_token == null && !public_key.IsNullOrEmpty ()) { - var hash = HashPublicKey (); - // we need the last 8 bytes in reverse order - var local_public_key_token = new byte [8]; - Array.Copy (hash, (hash.Length - 8), local_public_key_token, 0, 8); - Array.Reverse (local_public_key_token, 0, 8); - Interlocked.CompareExchange (ref public_key_token, local_public_key_token, null); // publish only once finished (required for thread-safety) - } - return public_key_token ?? Empty.Array; - } - set { - public_key_token = value; - full_name = null; - } - } - - byte [] HashPublicKey () - { - HashAlgorithm algorithm; - - switch (hash_algorithm) { - case AssemblyHashAlgorithm.Reserved: - algorithm = MD5.Create (); - break; - default: - // None default to SHA1 - algorithm = SHA1.Create (); - break; - } - - using (algorithm) - return algorithm.ComputeHash (public_key); - } - - public virtual MetadataScopeType MetadataScopeType { - get { return MetadataScopeType.AssemblyNameReference; } - } - - public string FullName { - get { - if (full_name != null) - return full_name; - - const string sep = ", "; - - var builder = new StringBuilder (); - builder.Append (name); - builder.Append (sep); - builder.Append ("Version="); - builder.Append (version.ToString (fieldCount: 4)); - builder.Append (sep); - builder.Append ("Culture="); - builder.Append (string.IsNullOrEmpty (culture) ? "neutral" : culture); - builder.Append (sep); - builder.Append ("PublicKeyToken="); - - var pk_token = PublicKeyToken; - if (!pk_token.IsNullOrEmpty () && pk_token.Length > 0) { - for (int i = 0; i < pk_token.Length; i++) { - builder.Append (pk_token [i].ToString ("x2")); - } - } else - builder.Append ("null"); - - if (IsRetargetable) { - builder.Append (sep); - builder.Append ("Retargetable=Yes"); - } - - Interlocked.CompareExchange (ref full_name, builder.ToString (), null); - - return full_name; - } - } - - public static AssemblyNameReference Parse (string fullName) - { - if (fullName == null) - throw new ArgumentNullException ("fullName"); - if (fullName.Length == 0) - throw new ArgumentException ("Name can not be empty"); - - var name = new AssemblyNameReference (); - var tokens = fullName.Split (','); - for (int i = 0; i < tokens.Length; i++) { - var token = tokens [i].Trim (); - - if (i == 0) { - name.Name = token; - continue; - } - - var parts = token.Split ('='); - if (parts.Length != 2) - throw new ArgumentException ("Malformed name"); - - switch (parts [0].ToLowerInvariant ()) { - case "version": - name.Version = new Version (parts [1]); - break; - case "culture": - name.Culture = parts [1] == "neutral" ? "" : parts [1]; - break; - case "publickeytoken": - var pk_token = parts [1]; - if (pk_token == "null") - break; - - name.PublicKeyToken = new byte [pk_token.Length / 2]; - for (int j = 0; j < name.PublicKeyToken.Length; j++) - name.PublicKeyToken [j] = Byte.Parse (pk_token.Substring (j * 2, 2), NumberStyles.HexNumber); - - break; - } - } - - return name; - } - - public AssemblyHashAlgorithm HashAlgorithm { - get { return hash_algorithm; } - set { hash_algorithm = value; } - } - - public virtual byte [] Hash { - get { return hash; } - set { hash = value; } - } - - public MetadataToken MetadataToken { - get { return token; } - set { token = value; } - } - - internal AssemblyNameReference () - { - this.version = Mixin.ZeroVersion; - this.token = new MetadataToken (TokenType.AssemblyRef); - } - - public AssemblyNameReference (string name, Version version) - { - Mixin.CheckName (name); - - this.name = name; - this.version = Mixin.CheckVersion (version); - this.hash_algorithm = AssemblyHashAlgorithm.None; - this.token = new MetadataToken (TokenType.AssemblyRef); - } - - public override string ToString () - { - return this.FullName; - } - } - - partial class Mixin { - - public static Version ZeroVersion = new Version (0, 0, 0, 0); - - public static Version CheckVersion (Version version) - { - if (version == null) - return ZeroVersion; - - if (version.Build == -1) - return new Version (version.Major, version.Minor, 0, 0); - - if (version.Revision == -1) - return new Version (version.Major, version.Minor, version.Build, 0); - - return version; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameReference.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameReference.cs.meta deleted file mode 100644 index 980b1fd..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyNameReference.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fdaf7563058f3f54ba3e6b32c888eb3c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyReader.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyReader.cs deleted file mode 100644 index 2a3d6ef..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyReader.cs +++ /dev/null @@ -1,3889 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Cil; -using MonoFN.Cecil.Metadata; -using MonoFN.Cecil.PE; -using MonoFN.Collections.Generic; -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Text; -using RVA = System.UInt32; - -namespace MonoFN.Cecil { - - abstract class ModuleReader { - - readonly protected ModuleDefinition module; - - protected ModuleReader (Image image, ReadingMode mode) - { - this.module = new ModuleDefinition (image); - this.module.ReadingMode = mode; - } - - protected abstract void ReadModule (); - public abstract void ReadSymbols (ModuleDefinition module); - - protected void ReadModuleManifest (MetadataReader reader) - { - reader.Populate (module); - - ReadAssembly (reader); - } - - void ReadAssembly (MetadataReader reader) - { - var name = reader.ReadAssemblyNameDefinition (); - if (name == null) { - module.kind = ModuleKind.NetModule; - return; - } - - var assembly = new AssemblyDefinition (); - assembly.Name = name; - - module.assembly = assembly; - assembly.main_module = module; - } - - public static ModuleDefinition CreateModule (Image image, ReaderParameters parameters) - { - var reader = CreateModuleReader (image, parameters.ReadingMode); - var module = reader.module; - - if (parameters.assembly_resolver != null) - module.assembly_resolver = Disposable.NotOwned (parameters.assembly_resolver); - - if (parameters.metadata_resolver != null) - module.metadata_resolver = parameters.metadata_resolver; - - if (parameters.metadata_importer_provider != null) - module.metadata_importer = parameters.metadata_importer_provider.GetMetadataImporter (module); - - if (parameters.reflection_importer_provider != null) - module.reflection_importer = parameters.reflection_importer_provider.GetReflectionImporter (module); - - GetMetadataKind (module, parameters); - - reader.ReadModule (); - - ReadSymbols (module, parameters); - - reader.ReadSymbols (module); - - if (parameters.ReadingMode == ReadingMode.Immediate) - module.MetadataSystem.Clear (); - - return module; - } - - static void ReadSymbols (ModuleDefinition module, ReaderParameters parameters) - { - var symbol_reader_provider = parameters.SymbolReaderProvider; - - if (symbol_reader_provider == null && parameters.ReadSymbols) - symbol_reader_provider = new DefaultSymbolReaderProvider (); - - if (symbol_reader_provider != null) { - module.SymbolReaderProvider = symbol_reader_provider; - - var reader = parameters.SymbolStream != null - ? symbol_reader_provider.GetSymbolReader (module, parameters.SymbolStream) - : symbol_reader_provider.GetSymbolReader (module, module.FileName); - - if (reader != null) { - try { - module.ReadSymbols (reader, parameters.ThrowIfSymbolsAreNotMatching); - } - catch (Exception) { - reader.Dispose (); - throw; - } - } - } - - if (module.Image.HasDebugTables ()) - module.ReadSymbols (new PortablePdbReader (module.Image, module)); - } - - static void GetMetadataKind (ModuleDefinition module, ReaderParameters parameters) - { - if (!parameters.ApplyWindowsRuntimeProjections) { - module.MetadataKind = MetadataKind.Ecma335; - return; - } - - var runtime_version = module.RuntimeVersion; - - if (!runtime_version.Contains ("WindowsRuntime")) - module.MetadataKind = MetadataKind.Ecma335; - else if (runtime_version.Contains ("CLR")) - module.MetadataKind = MetadataKind.ManagedWindowsMetadata; - else - module.MetadataKind = MetadataKind.WindowsMetadata; - } - - static ModuleReader CreateModuleReader (Image image, ReadingMode mode) - { - switch (mode) { - case ReadingMode.Immediate: - return new ImmediateModuleReader (image); - case ReadingMode.Deferred: - return new DeferredModuleReader (image); - default: - throw new ArgumentException (); - } - } - } - - sealed class ImmediateModuleReader : ModuleReader { - - bool resolve_attributes; - - public ImmediateModuleReader (Image image) - : base (image, ReadingMode.Immediate) - { - } - - protected override void ReadModule () - { - this.module.Read (this.module, (module, reader) => { - ReadModuleManifest (reader); - ReadModule (module, resolve_attributes: true); - }); - } - - public void ReadModule (ModuleDefinition module, bool resolve_attributes) - { - this.resolve_attributes = resolve_attributes; - - if (module.HasAssemblyReferences) - Mixin.Read (module.AssemblyReferences); - if (module.HasResources) - Mixin.Read (module.Resources); - if (module.HasModuleReferences) - Mixin.Read (module.ModuleReferences); - if (module.HasTypes) - ReadTypes (module.Types); - if (module.HasExportedTypes) - Mixin.Read (module.ExportedTypes); - - ReadCustomAttributes (module); - - var assembly = module.Assembly; - if (module.kind == ModuleKind.NetModule || assembly == null) - return; - - ReadCustomAttributes (assembly); - ReadSecurityDeclarations (assembly); - } - - void ReadTypes (Collection types) - { - for (int i = 0; i < types.Count; i++) - ReadType (types [i]); - } - - void ReadType (TypeDefinition type) - { - ReadGenericParameters (type); - - if (type.HasInterfaces) - ReadInterfaces (type); - - if (type.HasNestedTypes) - ReadTypes (type.NestedTypes); - - if (type.HasLayoutInfo) - Mixin.Read (type.ClassSize); - - if (type.HasFields) - ReadFields (type); - - if (type.HasMethods) - ReadMethods (type); - - if (type.HasProperties) - ReadProperties (type); - - if (type.HasEvents) - ReadEvents (type); - - ReadSecurityDeclarations (type); - ReadCustomAttributes (type); - } - - void ReadInterfaces (TypeDefinition type) - { - var interfaces = type.Interfaces; - - for (int i = 0; i < interfaces.Count; i++) - ReadCustomAttributes (interfaces [i]); - } - - void ReadGenericParameters (IGenericParameterProvider provider) - { - if (!provider.HasGenericParameters) - return; - - var parameters = provider.GenericParameters; - - for (int i = 0; i < parameters.Count; i++) { - var parameter = parameters [i]; - - if (parameter.HasConstraints) - ReadGenericParameterConstraints (parameter); - - ReadCustomAttributes (parameter); - } - } - - void ReadGenericParameterConstraints (GenericParameter parameter) - { - var constraints = parameter.Constraints; - - for (int i = 0; i < constraints.Count; i++) - ReadCustomAttributes (constraints [i]); - } - - void ReadSecurityDeclarations (ISecurityDeclarationProvider provider) - { - if (!provider.HasSecurityDeclarations) - return; - - var security_declarations = provider.SecurityDeclarations; - - if (!resolve_attributes) - return; - - for (int i = 0; i < security_declarations.Count; i++) { - var security_declaration = security_declarations [i]; - - Mixin.Read (security_declaration.SecurityAttributes); - } - } - - void ReadCustomAttributes (ICustomAttributeProvider provider) - { - if (!provider.HasCustomAttributes) - return; - - var custom_attributes = provider.CustomAttributes; - - if (!resolve_attributes) - return; - - for (int i = 0; i < custom_attributes.Count; i++) { - var custom_attribute = custom_attributes [i]; - - Mixin.Read (custom_attribute.ConstructorArguments); - } - } - - void ReadFields (TypeDefinition type) - { - var fields = type.Fields; - - for (int i = 0; i < fields.Count; i++) { - var field = fields [i]; - - if (field.HasConstant) - Mixin.Read (field.Constant); - - if (field.HasLayoutInfo) - Mixin.Read (field.Offset); - - if (field.RVA > 0) - Mixin.Read (field.InitialValue); - - if (field.HasMarshalInfo) - Mixin.Read (field.MarshalInfo); - - ReadCustomAttributes (field); - } - } - - void ReadMethods (TypeDefinition type) - { - var methods = type.Methods; - - for (int i = 0; i < methods.Count; i++) { - var method = methods [i]; - - ReadGenericParameters (method); - - if (method.HasParameters) - ReadParameters (method); - - if (method.HasOverrides) - Mixin.Read (method.Overrides); - - if (method.IsPInvokeImpl) - Mixin.Read (method.PInvokeInfo); - - ReadSecurityDeclarations (method); - ReadCustomAttributes (method); - - var return_type = method.MethodReturnType; - if (return_type.HasConstant) - Mixin.Read (return_type.Constant); - - if (return_type.HasMarshalInfo) - Mixin.Read (return_type.MarshalInfo); - - ReadCustomAttributes (return_type); - } - } - - void ReadParameters (MethodDefinition method) - { - var parameters = method.Parameters; - - for (int i = 0; i < parameters.Count; i++) { - var parameter = parameters [i]; - - if (parameter.HasConstant) - Mixin.Read (parameter.Constant); - - if (parameter.HasMarshalInfo) - Mixin.Read (parameter.MarshalInfo); - - ReadCustomAttributes (parameter); - } - } - - void ReadProperties (TypeDefinition type) - { - var properties = type.Properties; - - for (int i = 0; i < properties.Count; i++) { - var property = properties [i]; - - Mixin.Read (property.GetMethod); - - if (property.HasConstant) - Mixin.Read (property.Constant); - - ReadCustomAttributes (property); - } - } - - void ReadEvents (TypeDefinition type) - { - var events = type.Events; - - for (int i = 0; i < events.Count; i++) { - var @event = events [i]; - - Mixin.Read (@event.AddMethod); - - ReadCustomAttributes (@event); - } - } - - public override void ReadSymbols (ModuleDefinition module) - { - if (module.symbol_reader == null) - return; - - ReadTypesSymbols (module.Types, module.symbol_reader); - } - - void ReadTypesSymbols (Collection types, ISymbolReader symbol_reader) - { - for (int i = 0; i < types.Count; i++) { - var type = types [i]; - - if (type.HasNestedTypes) - ReadTypesSymbols (type.NestedTypes, symbol_reader); - - if (type.HasMethods) - ReadMethodsSymbols (type, symbol_reader); - } - } - - void ReadMethodsSymbols (TypeDefinition type, ISymbolReader symbol_reader) - { - var methods = type.Methods; - for (int i = 0; i < methods.Count; i++) { - var method = methods [i]; - - if (method.HasBody && method.token.RID != 0 && method.debug_info == null) - method.debug_info = symbol_reader.Read (method); - } - } - } - - sealed class DeferredModuleReader : ModuleReader { - - public DeferredModuleReader (Image image) - : base (image, ReadingMode.Deferred) - { - } - - protected override void ReadModule () - { - this.module.Read (this.module, (_, reader) => ReadModuleManifest (reader)); - } - - public override void ReadSymbols (ModuleDefinition module) - { - } - } - - sealed class MetadataReader : ByteBuffer { - - readonly internal Image image; - readonly internal ModuleDefinition module; - readonly internal MetadataSystem metadata; - - internal CodeReader code; - internal IGenericContext context; - - readonly MetadataReader metadata_reader; - - public MetadataReader (ModuleDefinition module) - : base (module.Image.TableHeap.data) - { - this.image = module.Image; - this.module = module; - this.metadata = module.MetadataSystem; - this.code = new CodeReader (this); - } - - public MetadataReader (Image image, ModuleDefinition module, MetadataReader metadata_reader) - : base (image.TableHeap.data) - { - this.image = image; - this.module = module; - this.metadata = module.MetadataSystem; - this.metadata_reader = metadata_reader; - } - - int GetCodedIndexSize (CodedIndex index) - { - return image.GetCodedIndexSize (index); - } - - uint ReadByIndexSize (int size) - { - if (size == 4) - return ReadUInt32 (); - else - return ReadUInt16 (); - } - - byte [] ReadBlob () - { - var blob_heap = image.BlobHeap; - if (blob_heap == null) { - position += 2; - return Empty.Array; - } - - return blob_heap.Read (ReadBlobIndex ()); - } - - byte [] ReadBlob (uint signature) - { - var blob_heap = image.BlobHeap; - if (blob_heap == null) - return Empty.Array; - - return blob_heap.Read (signature); - } - - uint ReadBlobIndex () - { - var blob_heap = image.BlobHeap; - return ReadByIndexSize (blob_heap != null ? blob_heap.IndexSize : 2); - } - - void GetBlobView (uint signature, out byte [] blob, out int index, out int count) - { - var blob_heap = image.BlobHeap; - if (blob_heap == null) { - blob = null; - index = count = 0; - return; - } - - blob_heap.GetView (signature, out blob, out index, out count); - } - - string ReadString () - { - return image.StringHeap.Read (ReadByIndexSize (image.StringHeap.IndexSize)); - } - - uint ReadStringIndex () - { - return ReadByIndexSize (image.StringHeap.IndexSize); - } - - Guid ReadGuid () - { - return image.GuidHeap.Read (ReadByIndexSize (image.GuidHeap.IndexSize)); - } - - uint ReadTableIndex (Table table) - { - return ReadByIndexSize (image.GetTableIndexSize (table)); - } - - MetadataToken ReadMetadataToken (CodedIndex index) - { - return index.GetMetadataToken (ReadByIndexSize (GetCodedIndexSize (index))); - } - - int MoveTo (Table table) - { - var info = image.TableHeap [table]; - if (info.Length != 0) - this.position = (int)info.Offset; - - return (int)info.Length; - } - - bool MoveTo (Table table, uint row) - { - var info = image.TableHeap [table]; - var length = info.Length; - if (length == 0 || row > length) - return false; - - this.position = (int)(info.Offset + (info.RowSize * (row - 1))); - return true; - } - - public AssemblyNameDefinition ReadAssemblyNameDefinition () - { - if (MoveTo (Table.Assembly) == 0) - return null; - - var name = new AssemblyNameDefinition (); - - name.HashAlgorithm = (AssemblyHashAlgorithm)ReadUInt32 (); - - PopulateVersionAndFlags (name); - - name.PublicKey = ReadBlob (); - - PopulateNameAndCulture (name); - - return name; - } - - public ModuleDefinition Populate (ModuleDefinition module) - { - if (MoveTo (Table.Module) == 0) - return module; - - Advance (2); // Generation - - module.Name = ReadString (); - module.Mvid = ReadGuid (); - - return module; - } - - void InitializeAssemblyReferences () - { - if (metadata.AssemblyReferences != null) - return; - - int length = MoveTo (Table.AssemblyRef); - var references = metadata.AssemblyReferences = new AssemblyNameReference [length]; - - for (uint i = 0; i < length; i++) { - var reference = new AssemblyNameReference (); - reference.token = new MetadataToken (TokenType.AssemblyRef, i + 1); - - PopulateVersionAndFlags (reference); - - var key_or_token = ReadBlob (); - - if (reference.HasPublicKey) - reference.PublicKey = key_or_token; - else - reference.PublicKeyToken = key_or_token; - - PopulateNameAndCulture (reference); - - reference.Hash = ReadBlob (); - - references [i] = reference; - } - } - - public Collection ReadAssemblyReferences () - { - InitializeAssemblyReferences (); - - var references = new Collection (metadata.AssemblyReferences); - if (module.IsWindowsMetadata ()) - module.Projections.AddVirtualReferences (references); - - return references; - } - - public MethodDefinition ReadEntryPoint () - { - if (module.Image.EntryPointToken == 0) - return null; - - var token = new MetadataToken (module.Image.EntryPointToken); - return GetMethodDefinition (token.RID); - } - - public Collection ReadModules () - { - var modules = new Collection (1); - modules.Add (this.module); - - int length = MoveTo (Table.File); - for (uint i = 1; i <= length; i++) { - var attributes = (FileAttributes)ReadUInt32 (); - var name = ReadString (); - ReadBlobIndex (); - - if (attributes != FileAttributes.ContainsMetaData) - continue; - - var parameters = new ReaderParameters { - ReadingMode = module.ReadingMode, - SymbolReaderProvider = module.SymbolReaderProvider, - AssemblyResolver = module.AssemblyResolver - }; - - var netmodule = ModuleDefinition.ReadModule (GetModuleFileName (name), parameters); - netmodule.assembly = this.module.assembly; - - modules.Add (netmodule); - } - - return modules; - } - - string GetModuleFileName (string name) - { - if (module.FileName == null) - throw new NotSupportedException (); - - var path = Path.GetDirectoryName (module.FileName); - return Path.Combine (path, name); - } - - void InitializeModuleReferences () - { - if (metadata.ModuleReferences != null) - return; - - int length = MoveTo (Table.ModuleRef); - var references = metadata.ModuleReferences = new ModuleReference [length]; - - for (uint i = 0; i < length; i++) { - var reference = new ModuleReference (ReadString ()); - reference.token = new MetadataToken (TokenType.ModuleRef, i + 1); - - references [i] = reference; - } - } - - public Collection ReadModuleReferences () - { - InitializeModuleReferences (); - - return new Collection (metadata.ModuleReferences); - } - - public bool HasFileResource () - { - int length = MoveTo (Table.File); - if (length == 0) - return false; - - for (uint i = 1; i <= length; i++) - if (ReadFileRecord (i).Col1 == FileAttributes.ContainsNoMetaData) - return true; - - return false; - } - - public Collection ReadResources () - { - int length = MoveTo (Table.ManifestResource); - var resources = new Collection (length); - - for (int i = 1; i <= length; i++) { - var offset = ReadUInt32 (); - var flags = (ManifestResourceAttributes)ReadUInt32 (); - var name = ReadString (); - var implementation = ReadMetadataToken (CodedIndex.Implementation); - - Resource resource; - - if (implementation.RID == 0) { - resource = new EmbeddedResource (name, flags, offset, this); - } else if (implementation.TokenType == TokenType.AssemblyRef) { - resource = new AssemblyLinkedResource (name, flags) { - Assembly = (AssemblyNameReference)GetTypeReferenceScope (implementation), - }; - } else if (implementation.TokenType == TokenType.File) { - var file_record = ReadFileRecord (implementation.RID); - - resource = new LinkedResource (name, flags) { - File = file_record.Col2, - hash = ReadBlob (file_record.Col3) - }; - } else - continue; - - resources.Add (resource); - } - - return resources; - } - - Row ReadFileRecord (uint rid) - { - var position = this.position; - - if (!MoveTo (Table.File, rid)) - throw new ArgumentException (); - - var record = new Row ( - (FileAttributes)ReadUInt32 (), - ReadString (), - ReadBlobIndex ()); - - this.position = position; - - return record; - } - - public byte [] GetManagedResource (uint offset) - { - return image.GetReaderAt (image.Resources.VirtualAddress, offset, (o, reader) => { - reader.Advance ((int)o); - return reader.ReadBytes (reader.ReadInt32 ()); - }) ?? Empty.Array; - } - - void PopulateVersionAndFlags (AssemblyNameReference name) - { - name.Version = new Version ( - ReadUInt16 (), - ReadUInt16 (), - ReadUInt16 (), - ReadUInt16 ()); - - name.Attributes = (AssemblyAttributes)ReadUInt32 (); - } - - void PopulateNameAndCulture (AssemblyNameReference name) - { - name.Name = ReadString (); - name.Culture = ReadString (); - } - - public TypeDefinitionCollection ReadTypes () - { - InitializeTypeDefinitions (); - var mtypes = metadata.Types; - var type_count = mtypes.Length - metadata.NestedTypes.Count; - var types = new TypeDefinitionCollection (module, type_count); - - for (int i = 0; i < mtypes.Length; i++) { - var type = mtypes [i]; - if (IsNested (type.Attributes)) - continue; - - types.Add (type); - } - - if (image.HasTable (Table.MethodPtr) || image.HasTable (Table.FieldPtr)) - CompleteTypes (); - - return types; - } - - void CompleteTypes () - { - var types = metadata.Types; - - for (int i = 0; i < types.Length; i++) { - var type = types [i]; - - Mixin.Read (type.Fields); - Mixin.Read (type.Methods); - } - } - - void InitializeTypeDefinitions () - { - if (metadata.Types != null) - return; - - InitializeNestedTypes (); - InitializeFields (); - InitializeMethods (); - - int length = MoveTo (Table.TypeDef); - var types = metadata.Types = new TypeDefinition [length]; - - for (uint i = 0; i < length; i++) { - if (types [i] != null) - continue; - - types [i] = ReadType (i + 1); - } - - if (module.IsWindowsMetadata ()) { - for (uint i = 0; i < length; i++) { - WindowsRuntimeProjections.Project (types [i]); - } - } - } - - static bool IsNested (TypeAttributes attributes) - { - switch (attributes & TypeAttributes.VisibilityMask) { - case TypeAttributes.NestedAssembly: - case TypeAttributes.NestedFamANDAssem: - case TypeAttributes.NestedFamily: - case TypeAttributes.NestedFamORAssem: - case TypeAttributes.NestedPrivate: - case TypeAttributes.NestedPublic: - return true; - default: - return false; - } - } - - public bool HasNestedTypes (TypeDefinition type) - { - Collection mapping; - InitializeNestedTypes (); - - if (!metadata.TryGetNestedTypeMapping (type, out mapping)) - return false; - - return mapping.Count > 0; - } - - public Collection ReadNestedTypes (TypeDefinition type) - { - InitializeNestedTypes (); - Collection mapping; - if (!metadata.TryGetNestedTypeMapping (type, out mapping)) - return new MemberDefinitionCollection (type); - - var nested_types = new MemberDefinitionCollection (type, mapping.Count); - - for (int i = 0; i < mapping.Count; i++) { - var nested_type = GetTypeDefinition (mapping [i]); - - if (nested_type != null) - nested_types.Add (nested_type); - } - - metadata.RemoveNestedTypeMapping (type); - - return nested_types; - } - - void InitializeNestedTypes () - { - if (metadata.NestedTypes != null) - return; - - var length = MoveTo (Table.NestedClass); - - metadata.NestedTypes = new Dictionary> (length); - metadata.ReverseNestedTypes = new Dictionary (length); - - if (length == 0) - return; - - for (int i = 1; i <= length; i++) { - var nested = ReadTableIndex (Table.TypeDef); - var declaring = ReadTableIndex (Table.TypeDef); - - AddNestedMapping (declaring, nested); - } - } - - void AddNestedMapping (uint declaring, uint nested) - { - metadata.SetNestedTypeMapping (declaring, AddMapping (metadata.NestedTypes, declaring, nested)); - metadata.SetReverseNestedTypeMapping (nested, declaring); - } - - static Collection AddMapping (Dictionary> cache, TKey key, TValue value) - { - Collection mapped; - if (!cache.TryGetValue (key, out mapped)) { - mapped = new Collection (); - } - mapped.Add (value); - return mapped; - } - - TypeDefinition ReadType (uint rid) - { - if (!MoveTo (Table.TypeDef, rid)) - return null; - - var attributes = (TypeAttributes)ReadUInt32 (); - var name = ReadString (); - var @namespace = ReadString (); - var type = new TypeDefinition (@namespace, name, attributes); - type.token = new MetadataToken (TokenType.TypeDef, rid); - type.scope = module; - type.module = module; - - metadata.AddTypeDefinition (type); - - this.context = type; - - type.BaseType = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef)); - - type.fields_range = ReadListRange (rid, Table.TypeDef, Table.Field); - type.methods_range = ReadListRange (rid, Table.TypeDef, Table.Method); - - if (IsNested (attributes)) - type.DeclaringType = GetNestedTypeDeclaringType (type); - - return type; - } - - TypeDefinition GetNestedTypeDeclaringType (TypeDefinition type) - { - uint declaring_rid; - if (!metadata.TryGetReverseNestedTypeMapping (type, out declaring_rid)) - return null; - - metadata.RemoveReverseNestedTypeMapping (type); - return GetTypeDefinition (declaring_rid); - } - - Range ReadListRange (uint current_index, Table current, Table target) - { - var list = new Range (); - - var start = ReadTableIndex (target); - if (start == 0) - return list; - - uint next_index; - var current_table = image.TableHeap [current]; - - if (current_index == current_table.Length) - next_index = image.TableHeap [target].Length + 1; - else { - var position = this.position; - this.position += (int)(current_table.RowSize - image.GetTableIndexSize (target)); - next_index = ReadTableIndex (target); - this.position = position; - } - - list.Start = start; - list.Length = next_index - start; - - return list; - } - - public Row ReadTypeLayout (TypeDefinition type) - { - InitializeTypeLayouts (); - Row class_layout; - var rid = type.token.RID; - if (!metadata.ClassLayouts.TryGetValue (rid, out class_layout)) - return new Row (Mixin.NoDataMarker, Mixin.NoDataMarker); - - type.PackingSize = (short)class_layout.Col1; - type.ClassSize = (int)class_layout.Col2; - - metadata.ClassLayouts.Remove (rid); - - return new Row ((short)class_layout.Col1, (int)class_layout.Col2); - } - - void InitializeTypeLayouts () - { - if (metadata.ClassLayouts != null) - return; - - int length = MoveTo (Table.ClassLayout); - - var class_layouts = metadata.ClassLayouts = new Dictionary> (length); - - for (uint i = 0; i < length; i++) { - var packing_size = ReadUInt16 (); - var class_size = ReadUInt32 (); - - var parent = ReadTableIndex (Table.TypeDef); - - class_layouts.Add (parent, new Row (packing_size, class_size)); - } - } - - public TypeReference GetTypeDefOrRef (MetadataToken token) - { - return (TypeReference)LookupToken (token); - } - - public TypeDefinition GetTypeDefinition (uint rid) - { - InitializeTypeDefinitions (); - - var type = metadata.GetTypeDefinition (rid); - if (type != null) - return type; - - type = ReadTypeDefinition (rid); - - if (module.IsWindowsMetadata ()) - WindowsRuntimeProjections.Project (type); - - return type; - } - - TypeDefinition ReadTypeDefinition (uint rid) - { - if (!MoveTo (Table.TypeDef, rid)) - return null; - - return ReadType (rid); - } - - void InitializeTypeReferences () - { - if (metadata.TypeReferences != null) - return; - - metadata.TypeReferences = new TypeReference [image.GetTableLength (Table.TypeRef)]; - } - - public TypeReference GetTypeReference (string scope, string full_name) - { - InitializeTypeReferences (); - - var length = metadata.TypeReferences.Length; - - for (uint i = 1; i <= length; i++) { - var type = GetTypeReference (i); - - if (type.FullName != full_name) - continue; - - if (string.IsNullOrEmpty (scope)) - return type; - - if (type.Scope.Name == scope) - return type; - } - - return null; - } - - TypeReference GetTypeReference (uint rid) - { - InitializeTypeReferences (); - - var type = metadata.GetTypeReference (rid); - if (type != null) - return type; - - return ReadTypeReference (rid); - } - - TypeReference ReadTypeReference (uint rid) - { - if (!MoveTo (Table.TypeRef, rid)) - return null; - - TypeReference declaring_type = null; - IMetadataScope scope; - - var scope_token = ReadMetadataToken (CodedIndex.ResolutionScope); - - var name = ReadString (); - var @namespace = ReadString (); - - var type = new TypeReference ( - @namespace, - name, - module, - null); - - type.token = new MetadataToken (TokenType.TypeRef, rid); - - metadata.AddTypeReference (type); - - if (scope_token.TokenType == TokenType.TypeRef) { - if (scope_token.RID != rid) { - declaring_type = GetTypeDefOrRef (scope_token); - - scope = declaring_type != null - ? declaring_type.Scope - : module; - } else // obfuscated typeref row pointing to self - scope = module; - } else - scope = GetTypeReferenceScope (scope_token); - - type.scope = scope; - type.DeclaringType = declaring_type; - - MetadataSystem.TryProcessPrimitiveTypeReference (type); - - if (type.Module.IsWindowsMetadata ()) - WindowsRuntimeProjections.Project (type); - - return type; - } - - IMetadataScope GetTypeReferenceScope (MetadataToken scope) - { - if (scope.TokenType == TokenType.Module) - return module; - - IMetadataScope [] scopes; - - switch (scope.TokenType) { - case TokenType.AssemblyRef: - InitializeAssemblyReferences (); - scopes = metadata.AssemblyReferences; - break; - case TokenType.ModuleRef: - InitializeModuleReferences (); - scopes = metadata.ModuleReferences; - break; - default: - throw new NotSupportedException (); - } - - var index = scope.RID - 1; - if (index < 0 || index >= scopes.Length) - return null; - - return scopes [index]; - } - - public IEnumerable GetTypeReferences () - { - InitializeTypeReferences (); - - var length = image.GetTableLength (Table.TypeRef); - - var type_references = new TypeReference [length]; - - for (uint i = 1; i <= length; i++) - type_references [i - 1] = GetTypeReference (i); - - return type_references; - } - - TypeReference GetTypeSpecification (uint rid) - { - if (!MoveTo (Table.TypeSpec, rid)) - return null; - - var reader = ReadSignature (ReadBlobIndex ()); - var type = reader.ReadTypeSignature (); - if (type.token.RID == 0) - type.token = new MetadataToken (TokenType.TypeSpec, rid); - - return type; - } - - SignatureReader ReadSignature (uint signature) - { - return new SignatureReader (signature, this); - } - - public bool HasInterfaces (TypeDefinition type) - { - InitializeInterfaces (); - Collection> mapping; - - return metadata.TryGetInterfaceMapping (type, out mapping); - } - - public InterfaceImplementationCollection ReadInterfaces (TypeDefinition type) - { - InitializeInterfaces (); - Collection> mapping; - - if (!metadata.TryGetInterfaceMapping (type, out mapping)) - return new InterfaceImplementationCollection (type); - - var interfaces = new InterfaceImplementationCollection (type, mapping.Count); - - this.context = type; - - for (int i = 0; i < mapping.Count; i++) { - interfaces.Add ( - new InterfaceImplementation ( - GetTypeDefOrRef (mapping [i].Col2), - new MetadataToken (TokenType.InterfaceImpl, mapping [i].Col1))); - } - - metadata.RemoveInterfaceMapping (type); - - return interfaces; - } - - void InitializeInterfaces () - { - if (metadata.Interfaces != null) - return; - - int length = MoveTo (Table.InterfaceImpl); - - metadata.Interfaces = new Dictionary>> (length); - - for (uint i = 1; i <= length; i++) { - var type = ReadTableIndex (Table.TypeDef); - var @interface = ReadMetadataToken (CodedIndex.TypeDefOrRef); - - AddInterfaceMapping (type, new Row (i, @interface)); - } - } - - void AddInterfaceMapping (uint type, Row @interface) - { - metadata.SetInterfaceMapping (type, AddMapping (metadata.Interfaces, type, @interface)); - } - - public Collection ReadFields (TypeDefinition type) - { - var fields_range = type.fields_range; - if (fields_range.Length == 0) - return new MemberDefinitionCollection (type); - - var fields = new MemberDefinitionCollection (type, (int)fields_range.Length); - this.context = type; - - if (!MoveTo (Table.FieldPtr, fields_range.Start)) { - if (!MoveTo (Table.Field, fields_range.Start)) - return fields; - - for (uint i = 0; i < fields_range.Length; i++) - ReadField (fields_range.Start + i, fields); - } else - ReadPointers (Table.FieldPtr, Table.Field, fields_range, fields, ReadField); - - return fields; - } - - void ReadField (uint field_rid, Collection fields) - { - var attributes = (FieldAttributes)ReadUInt16 (); - var name = ReadString (); - var signature = ReadBlobIndex (); - - var field = new FieldDefinition (name, attributes, ReadFieldType (signature)); - field.token = new MetadataToken (TokenType.Field, field_rid); - metadata.AddFieldDefinition (field); - - if (IsDeleted (field)) - return; - - fields.Add (field); - - if (module.IsWindowsMetadata ()) - WindowsRuntimeProjections.Project (field); - } - - void InitializeFields () - { - if (metadata.Fields != null) - return; - - metadata.Fields = new FieldDefinition [image.GetTableLength (Table.Field)]; - } - - TypeReference ReadFieldType (uint signature) - { - var reader = ReadSignature (signature); - - const byte field_sig = 0x6; - - if (reader.ReadByte () != field_sig) - throw new NotSupportedException (); - - return reader.ReadTypeSignature (); - } - - public int ReadFieldRVA (FieldDefinition field) - { - InitializeFieldRVAs (); - var rid = field.token.RID; - - RVA rva; - if (!metadata.FieldRVAs.TryGetValue (rid, out rva)) - return 0; - - var size = GetFieldTypeSize (field.FieldType); - - if (size == 0 || rva == 0) - return 0; - - metadata.FieldRVAs.Remove (rid); - - field.InitialValue = GetFieldInitializeValue (size, rva); - - return (int)rva; - } - - byte [] GetFieldInitializeValue (int size, RVA rva) - { - return image.GetReaderAt (rva, size, (s, reader) => reader.ReadBytes (s)) ?? Empty.Array; - } - - static int GetFieldTypeSize (TypeReference type) - { - int size = 0; - - switch (type.etype) { - case ElementType.Boolean: - case ElementType.U1: - case ElementType.I1: - size = 1; - break; - case ElementType.U2: - case ElementType.I2: - case ElementType.Char: - size = 2; - break; - case ElementType.U4: - case ElementType.I4: - case ElementType.R4: - size = 4; - break; - case ElementType.U8: - case ElementType.I8: - case ElementType.R8: - size = 8; - break; - case ElementType.Ptr: - case ElementType.FnPtr: - size = IntPtr.Size; - break; - case ElementType.CModOpt: - case ElementType.CModReqD: - return GetFieldTypeSize (((IModifierType)type).ElementType); - default: - var field_type = type.Resolve (); - if (field_type != null && field_type.HasLayoutInfo) - size = field_type.ClassSize; - - break; - } - - return size; - } - - void InitializeFieldRVAs () - { - if (metadata.FieldRVAs != null) - return; - - int length = MoveTo (Table.FieldRVA); - - var field_rvas = metadata.FieldRVAs = new Dictionary (length); - - for (int i = 0; i < length; i++) { - var rva = ReadUInt32 (); - var field = ReadTableIndex (Table.Field); - - field_rvas.Add (field, rva); - } - } - - public int ReadFieldLayout (FieldDefinition field) - { - InitializeFieldLayouts (); - var rid = field.token.RID; - uint offset; - if (!metadata.FieldLayouts.TryGetValue (rid, out offset)) - return Mixin.NoDataMarker; - - metadata.FieldLayouts.Remove (rid); - - return (int)offset; - } - - void InitializeFieldLayouts () - { - if (metadata.FieldLayouts != null) - return; - - int length = MoveTo (Table.FieldLayout); - - var field_layouts = metadata.FieldLayouts = new Dictionary (length); - - for (int i = 0; i < length; i++) { - var offset = ReadUInt32 (); - var field = ReadTableIndex (Table.Field); - - field_layouts.Add (field, offset); - } - } - - public bool HasEvents (TypeDefinition type) - { - InitializeEvents (); - - Range range; - if (!metadata.TryGetEventsRange (type, out range)) - return false; - - return range.Length > 0; - } - - public Collection ReadEvents (TypeDefinition type) - { - InitializeEvents (); - Range range; - - if (!metadata.TryGetEventsRange (type, out range)) - return new MemberDefinitionCollection (type); - - var events = new MemberDefinitionCollection (type, (int)range.Length); - - metadata.RemoveEventsRange (type); - - if (range.Length == 0) - return events; - - this.context = type; - - if (!MoveTo (Table.EventPtr, range.Start)) { - if (!MoveTo (Table.Event, range.Start)) - return events; - - for (uint i = 0; i < range.Length; i++) - ReadEvent (range.Start + i, events); - } else - ReadPointers (Table.EventPtr, Table.Event, range, events, ReadEvent); - - return events; - } - - void ReadEvent (uint event_rid, Collection events) - { - var attributes = (EventAttributes)ReadUInt16 (); - var name = ReadString (); - var event_type = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef)); - - var @event = new EventDefinition (name, attributes, event_type); - @event.token = new MetadataToken (TokenType.Event, event_rid); - - if (IsDeleted (@event)) - return; - - events.Add (@event); - } - - void InitializeEvents () - { - if (metadata.Events != null) - return; - - int length = MoveTo (Table.EventMap); - - metadata.Events = new Dictionary (length); - - for (uint i = 1; i <= length; i++) { - var type_rid = ReadTableIndex (Table.TypeDef); - Range events_range = ReadListRange (i, Table.EventMap, Table.Event); - metadata.AddEventsRange (type_rid, events_range); - } - } - - public bool HasProperties (TypeDefinition type) - { - InitializeProperties (); - - Range range; - if (!metadata.TryGetPropertiesRange (type, out range)) - return false; - - return range.Length > 0; - } - - public Collection ReadProperties (TypeDefinition type) - { - InitializeProperties (); - - Range range; - - if (!metadata.TryGetPropertiesRange (type, out range)) - return new MemberDefinitionCollection (type); - - metadata.RemovePropertiesRange (type); - - var properties = new MemberDefinitionCollection (type, (int)range.Length); - - if (range.Length == 0) - return properties; - - this.context = type; - - if (!MoveTo (Table.PropertyPtr, range.Start)) { - if (!MoveTo (Table.Property, range.Start)) - return properties; - for (uint i = 0; i < range.Length; i++) - ReadProperty (range.Start + i, properties); - } else - ReadPointers (Table.PropertyPtr, Table.Property, range, properties, ReadProperty); - - return properties; - } - - void ReadProperty (uint property_rid, Collection properties) - { - var attributes = (PropertyAttributes)ReadUInt16 (); - var name = ReadString (); - var signature = ReadBlobIndex (); - - var reader = ReadSignature (signature); - const byte property_signature = 0x8; - - var calling_convention = reader.ReadByte (); - - if ((calling_convention & property_signature) == 0) - throw new NotSupportedException (); - - var has_this = (calling_convention & 0x20) != 0; - - reader.ReadCompressedUInt32 (); // count - - var property = new PropertyDefinition (name, attributes, reader.ReadTypeSignature ()); - property.HasThis = has_this; - property.token = new MetadataToken (TokenType.Property, property_rid); - - if (IsDeleted (property)) - return; - - properties.Add (property); - } - - void InitializeProperties () - { - if (metadata.Properties != null) - return; - - int length = MoveTo (Table.PropertyMap); - - metadata.Properties = new Dictionary (length); - - for (uint i = 1; i <= length; i++) { - var type_rid = ReadTableIndex (Table.TypeDef); - var properties_range = ReadListRange (i, Table.PropertyMap, Table.Property); - metadata.AddPropertiesRange (type_rid, properties_range); - } - } - - MethodSemanticsAttributes ReadMethodSemantics (MethodDefinition method) - { - InitializeMethodSemantics (); - Row row; - if (!metadata.Semantics.TryGetValue (method.token.RID, out row)) - return MethodSemanticsAttributes.None; - - var type = method.DeclaringType; - - switch (row.Col1) { - case MethodSemanticsAttributes.AddOn: - GetEvent (type, row.Col2).add_method = method; - break; - case MethodSemanticsAttributes.Fire: - GetEvent (type, row.Col2).invoke_method = method; - break; - case MethodSemanticsAttributes.RemoveOn: - GetEvent (type, row.Col2).remove_method = method; - break; - case MethodSemanticsAttributes.Getter: - GetProperty (type, row.Col2).get_method = method; - break; - case MethodSemanticsAttributes.Setter: - GetProperty (type, row.Col2).set_method = method; - break; - case MethodSemanticsAttributes.Other: - switch (row.Col2.TokenType) { - case TokenType.Event: { - var @event = GetEvent (type, row.Col2); - if (@event.other_methods == null) - @event.other_methods = new Collection (); - - @event.other_methods.Add (method); - break; - } - case TokenType.Property: { - var property = GetProperty (type, row.Col2); - if (property.other_methods == null) - property.other_methods = new Collection (); - - property.other_methods.Add (method); - - break; - } - default: - throw new NotSupportedException (); - } - break; - default: - throw new NotSupportedException (); - } - - metadata.Semantics.Remove (method.token.RID); - - return row.Col1; - } - - static EventDefinition GetEvent (TypeDefinition type, MetadataToken token) - { - if (token.TokenType != TokenType.Event) - throw new ArgumentException (); - - return GetMember (type.Events, token); - } - - static PropertyDefinition GetProperty (TypeDefinition type, MetadataToken token) - { - if (token.TokenType != TokenType.Property) - throw new ArgumentException (); - - return GetMember (type.Properties, token); - } - - static TMember GetMember (Collection members, MetadataToken token) where TMember : IMemberDefinition - { - for (int i = 0; i < members.Count; i++) { - var member = members [i]; - if (member.MetadataToken == token) - return member; - } - - throw new ArgumentException (); - } - - void InitializeMethodSemantics () - { - if (metadata.Semantics != null) - return; - - int length = MoveTo (Table.MethodSemantics); - - var semantics = metadata.Semantics = new Dictionary> (0); - - for (uint i = 0; i < length; i++) { - var attributes = (MethodSemanticsAttributes)ReadUInt16 (); - var method_rid = ReadTableIndex (Table.Method); - var association = ReadMetadataToken (CodedIndex.HasSemantics); - - semantics [method_rid] = new Row (attributes, association); - } - } - - public void ReadMethods (PropertyDefinition property) - { - ReadAllSemantics (property.DeclaringType); - } - - public void ReadMethods (EventDefinition @event) - { - ReadAllSemantics (@event.DeclaringType); - } - - public void ReadAllSemantics (MethodDefinition method) - { - ReadAllSemantics (method.DeclaringType); - } - - void ReadAllSemantics (TypeDefinition type) - { - var methods = type.Methods; - for (int i = 0; i < methods.Count; i++) { - var method = methods [i]; - if (method.sem_attrs_ready) - continue; - - method.sem_attrs = ReadMethodSemantics (method); - method.sem_attrs_ready = true; - } - } - - public Collection ReadMethods (TypeDefinition type) - { - var methods_range = type.methods_range; - if (methods_range.Length == 0) - return new MemberDefinitionCollection (type); - - var methods = new MemberDefinitionCollection (type, (int)methods_range.Length); - if (!MoveTo (Table.MethodPtr, methods_range.Start)) { - if (!MoveTo (Table.Method, methods_range.Start)) - return methods; - - for (uint i = 0; i < methods_range.Length; i++) - ReadMethod (methods_range.Start + i, methods); - } else - ReadPointers (Table.MethodPtr, Table.Method, methods_range, methods, ReadMethod); - - return methods; - } - - void ReadPointers (Table ptr, Table table, Range range, Collection members, Action> reader) - where TMember : IMemberDefinition - { - for (uint i = 0; i < range.Length; i++) { - MoveTo (ptr, range.Start + i); - - var rid = ReadTableIndex (table); - MoveTo (table, rid); - - reader (rid, members); - } - } - - static bool IsDeleted (IMemberDefinition member) - { - return member.IsSpecialName && member.Name == "_Deleted"; - } - - void InitializeMethods () - { - if (metadata.Methods != null) - return; - - metadata.Methods = new MethodDefinition [image.GetTableLength (Table.Method)]; - } - - void ReadMethod (uint method_rid, Collection methods) - { - var method = new MethodDefinition (); - method.rva = ReadUInt32 (); - method.ImplAttributes = (MethodImplAttributes)ReadUInt16 (); - method.Attributes = (MethodAttributes)ReadUInt16 (); - method.Name = ReadString (); - method.token = new MetadataToken (TokenType.Method, method_rid); - - if (IsDeleted (method)) - return; - - methods.Add (method); // attach method - - var signature = ReadBlobIndex (); - var param_range = ReadListRange (method_rid, Table.Method, Table.Param); - - this.context = method; - - ReadMethodSignature (signature, method); - metadata.AddMethodDefinition (method); - - if (param_range.Length != 0) { - var position = base.position; - ReadParameters (method, param_range); - base.position = position; - } - - if (module.IsWindowsMetadata ()) - WindowsRuntimeProjections.Project (method); - } - - void ReadParameters (MethodDefinition method, Range param_range) - { - if (!MoveTo (Table.ParamPtr, param_range.Start)) { - if (!MoveTo (Table.Param, param_range.Start)) - return; - - for (uint i = 0; i < param_range.Length; i++) - ReadParameter (param_range.Start + i, method); - } else - ReadParameterPointers (method, param_range); - } - - void ReadParameterPointers (MethodDefinition method, Range range) - { - for (uint i = 0; i < range.Length; i++) { - MoveTo (Table.ParamPtr, range.Start + i); - - var rid = ReadTableIndex (Table.Param); - - MoveTo (Table.Param, rid); - - ReadParameter (rid, method); - } - } - - void ReadParameter (uint param_rid, MethodDefinition method) - { - var attributes = (ParameterAttributes)ReadUInt16 (); - var sequence = ReadUInt16 (); - var name = ReadString (); - - var parameter = sequence == 0 - ? method.MethodReturnType.Parameter - : method.Parameters [sequence - 1]; - - parameter.token = new MetadataToken (TokenType.Param, param_rid); - parameter.Name = name; - parameter.Attributes = attributes; - } - - void ReadMethodSignature (uint signature, IMethodSignature method) - { - var reader = ReadSignature (signature); - reader.ReadMethodSignature (method); - } - - public PInvokeInfo ReadPInvokeInfo (MethodDefinition method) - { - InitializePInvokes (); - Row row; - - var rid = method.token.RID; - - if (!metadata.PInvokes.TryGetValue (rid, out row)) - return null; - - metadata.PInvokes.Remove (rid); - - return new PInvokeInfo ( - row.Col1, - image.StringHeap.Read (row.Col2), - module.ModuleReferences [(int)row.Col3 - 1]); - } - - void InitializePInvokes () - { - if (metadata.PInvokes != null) - return; - - int length = MoveTo (Table.ImplMap); - - var pinvokes = metadata.PInvokes = new Dictionary> (length); - - for (int i = 1; i <= length; i++) { - var attributes = (PInvokeAttributes)ReadUInt16 (); - var method = ReadMetadataToken (CodedIndex.MemberForwarded); - var name = ReadStringIndex (); - var scope = ReadTableIndex (Table.File); - - if (method.TokenType != TokenType.Method) - continue; - - pinvokes.Add (method.RID, new Row (attributes, name, scope)); - } - } - - public bool HasGenericParameters (IGenericParameterProvider provider) - { - InitializeGenericParameters (); - - Range [] ranges; - if (!metadata.TryGetGenericParameterRanges (provider, out ranges)) - return false; - - return RangesSize (ranges) > 0; - } - - public Collection ReadGenericParameters (IGenericParameterProvider provider) - { - InitializeGenericParameters (); - - Range [] ranges; - if (!metadata.TryGetGenericParameterRanges (provider, out ranges)) - return new GenericParameterCollection (provider); - - metadata.RemoveGenericParameterRange (provider); - - var generic_parameters = new GenericParameterCollection (provider, RangesSize (ranges)); - - for (int i = 0; i < ranges.Length; i++) - ReadGenericParametersRange (ranges [i], provider, generic_parameters); - - return generic_parameters; - } - - void ReadGenericParametersRange (Range range, IGenericParameterProvider provider, GenericParameterCollection generic_parameters) - { - if (!MoveTo (Table.GenericParam, range.Start)) - return; - - for (uint i = 0; i < range.Length; i++) { - ReadUInt16 (); // index - var flags = (GenericParameterAttributes)ReadUInt16 (); - ReadMetadataToken (CodedIndex.TypeOrMethodDef); - var name = ReadString (); - - var parameter = new GenericParameter (name, provider); - parameter.token = new MetadataToken (TokenType.GenericParam, range.Start + i); - parameter.Attributes = flags; - - generic_parameters.Add (parameter); - } - } - - void InitializeGenericParameters () - { - if (metadata.GenericParameters != null) - return; - - metadata.GenericParameters = InitializeRanges ( - Table.GenericParam, () => { - Advance (4); - var next = ReadMetadataToken (CodedIndex.TypeOrMethodDef); - ReadStringIndex (); - return next; - }); - } - - Dictionary InitializeRanges (Table table, Func get_next) - { - int length = MoveTo (table); - var ranges = new Dictionary (length); - - if (length == 0) - return ranges; - - MetadataToken owner = MetadataToken.Zero; - Range range = new Range (1, 0); - - for (uint i = 1; i <= length; i++) { - var next = get_next (); - - if (i == 1) { - owner = next; - range.Length++; - } else if (next != owner) { - AddRange (ranges, owner, range); - range = new Range (i, 1); - owner = next; - } else - range.Length++; - } - - AddRange (ranges, owner, range); - - return ranges; - } - - static void AddRange (Dictionary ranges, MetadataToken owner, Range range) - { - if (owner.RID == 0) - return; - - Range [] slots; - if (!ranges.TryGetValue (owner, out slots)) { - ranges.Add (owner, new [] { range }); - return; - } - - ranges [owner] = slots.Add (range); - } - - public bool HasGenericConstraints (GenericParameter generic_parameter) - { - InitializeGenericConstraints (); - - Collection> mapping; - if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping)) - return false; - - return mapping.Count > 0; - } - - public GenericParameterConstraintCollection ReadGenericConstraints (GenericParameter generic_parameter) - { - InitializeGenericConstraints (); - - Collection> mapping; - if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping)) - return new GenericParameterConstraintCollection (generic_parameter); - - var constraints = new GenericParameterConstraintCollection (generic_parameter, mapping.Count); - - this.context = (IGenericContext)generic_parameter.Owner; - - for (int i = 0; i < mapping.Count; i++) { - constraints.Add ( - new GenericParameterConstraint ( - GetTypeDefOrRef (mapping [i].Col2), - new MetadataToken (TokenType.GenericParamConstraint, mapping [i].Col1))); - } - - metadata.RemoveGenericConstraintMapping (generic_parameter); - - return constraints; - } - - void InitializeGenericConstraints () - { - if (metadata.GenericConstraints != null) - return; - - var length = MoveTo (Table.GenericParamConstraint); - - metadata.GenericConstraints = new Dictionary>> (length); - - for (uint i = 1; i <= length; i++) { - AddGenericConstraintMapping ( - ReadTableIndex (Table.GenericParam), - new Row (i, ReadMetadataToken (CodedIndex.TypeDefOrRef))); - } - } - - void AddGenericConstraintMapping (uint generic_parameter, Row constraint) - { - metadata.SetGenericConstraintMapping ( - generic_parameter, - AddMapping (metadata.GenericConstraints, generic_parameter, constraint)); - } - - public bool HasOverrides (MethodDefinition method) - { - InitializeOverrides (); - Collection mapping; - - if (!metadata.TryGetOverrideMapping (method, out mapping)) - return false; - - return mapping.Count > 0; - } - - public Collection ReadOverrides (MethodDefinition method) - { - InitializeOverrides (); - - Collection mapping; - if (!metadata.TryGetOverrideMapping (method, out mapping)) - return new Collection (); - - var overrides = new Collection (mapping.Count); - - this.context = method; - - for (int i = 0; i < mapping.Count; i++) - overrides.Add ((MethodReference)LookupToken (mapping [i])); - - metadata.RemoveOverrideMapping (method); - - return overrides; - } - - void InitializeOverrides () - { - if (metadata.Overrides != null) - return; - - var length = MoveTo (Table.MethodImpl); - - metadata.Overrides = new Dictionary> (length); - - for (int i = 1; i <= length; i++) { - ReadTableIndex (Table.TypeDef); - - var method = ReadMetadataToken (CodedIndex.MethodDefOrRef); - if (method.TokenType != TokenType.Method) - throw new NotSupportedException (); - - var @override = ReadMetadataToken (CodedIndex.MethodDefOrRef); - - AddOverrideMapping (method.RID, @override); - } - } - - void AddOverrideMapping (uint method_rid, MetadataToken @override) - { - metadata.SetOverrideMapping ( - method_rid, - AddMapping (metadata.Overrides, method_rid, @override)); - } - - public MethodBody ReadMethodBody (MethodDefinition method) - { - return code.ReadMethodBody (method); - } - - public int ReadCodeSize (MethodDefinition method) - { - return code.ReadCodeSize (method); - } - - public CallSite ReadCallSite (MetadataToken token) - { - if (!MoveTo (Table.StandAloneSig, token.RID)) - return null; - - var signature = ReadBlobIndex (); - - var call_site = new CallSite (); - - ReadMethodSignature (signature, call_site); - - call_site.MetadataToken = token; - - return call_site; - } - - public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token, MethodDefinition method = null) - { - if (!MoveTo (Table.StandAloneSig, local_var_token.RID)) - return null; - - var reader = ReadSignature (ReadBlobIndex ()); - const byte local_sig = 0x7; - - if (reader.ReadByte () != local_sig) - throw new NotSupportedException (); - - var count = reader.ReadCompressedUInt32 (); - if (count == 0) - return null; - - var variables = new VariableDefinitionCollection (method, (int)count); - - for (int i = 0; i < count; i++) - variables.Add (new VariableDefinition (reader.ReadTypeSignature ())); - - return variables; - } - - public IMetadataTokenProvider LookupToken (MetadataToken token) - { - var rid = token.RID; - - if (rid == 0) - return null; - - if (metadata_reader != null) - return metadata_reader.LookupToken (token); - - IMetadataTokenProvider element; - var position = this.position; - var context = this.context; - - switch (token.TokenType) { - case TokenType.TypeDef: - element = GetTypeDefinition (rid); - break; - case TokenType.TypeRef: - element = GetTypeReference (rid); - break; - case TokenType.TypeSpec: - element = GetTypeSpecification (rid); - break; - case TokenType.Field: - element = GetFieldDefinition (rid); - break; - case TokenType.Method: - element = GetMethodDefinition (rid); - break; - case TokenType.MemberRef: - element = GetMemberReference (rid); - break; - case TokenType.MethodSpec: - element = GetMethodSpecification (rid); - break; - default: - return null; - } - - this.position = position; - this.context = context; - - return element; - } - - public FieldDefinition GetFieldDefinition (uint rid) - { - InitializeTypeDefinitions (); - - var field = metadata.GetFieldDefinition (rid); - if (field != null) - return field; - - return LookupField (rid); - } - - FieldDefinition LookupField (uint rid) - { - var type = metadata.GetFieldDeclaringType (rid); - if (type == null) - return null; - - Mixin.Read (type.Fields); - - return metadata.GetFieldDefinition (rid); - } - - public MethodDefinition GetMethodDefinition (uint rid) - { - InitializeTypeDefinitions (); - - var method = metadata.GetMethodDefinition (rid); - if (method != null) - return method; - - return LookupMethod (rid); - } - - MethodDefinition LookupMethod (uint rid) - { - var type = metadata.GetMethodDeclaringType (rid); - if (type == null) - return null; - - Mixin.Read (type.Methods); - - return metadata.GetMethodDefinition (rid); - } - - MethodSpecification GetMethodSpecification (uint rid) - { - if (!MoveTo (Table.MethodSpec, rid)) - return null; - - var element_method = (MethodReference)LookupToken ( - ReadMetadataToken (CodedIndex.MethodDefOrRef)); - var signature = ReadBlobIndex (); - - var method_spec = ReadMethodSpecSignature (signature, element_method); - method_spec.token = new MetadataToken (TokenType.MethodSpec, rid); - return method_spec; - } - - MethodSpecification ReadMethodSpecSignature (uint signature, MethodReference method) - { - var reader = ReadSignature (signature); - const byte methodspec_sig = 0x0a; - - var call_conv = reader.ReadByte (); - - if (call_conv != methodspec_sig) - throw new NotSupportedException (); - - var arity = reader.ReadCompressedUInt32 (); - - var instance = new GenericInstanceMethod (method, (int)arity); - - reader.ReadGenericInstanceSignature (method, instance, arity); - - return instance; - } - - MemberReference GetMemberReference (uint rid) - { - InitializeMemberReferences (); - - var member = metadata.GetMemberReference (rid); - if (member != null) - return member; - - member = ReadMemberReference (rid); - if (member != null && !member.ContainsGenericParameter) - metadata.AddMemberReference (member); - return member; - } - - MemberReference ReadMemberReference (uint rid) - { - if (!MoveTo (Table.MemberRef, rid)) - return null; - - var token = ReadMetadataToken (CodedIndex.MemberRefParent); - var name = ReadString (); - var signature = ReadBlobIndex (); - - MemberReference member; - - switch (token.TokenType) { - case TokenType.TypeDef: - case TokenType.TypeRef: - case TokenType.TypeSpec: - member = ReadTypeMemberReference (token, name, signature); - break; - case TokenType.Method: - member = ReadMethodMemberReference (token, name, signature); - break; - default: - throw new NotSupportedException (); - } - - member.token = new MetadataToken (TokenType.MemberRef, rid); - return member; - } - - MemberReference ReadTypeMemberReference (MetadataToken type, string name, uint signature) - { - var declaring_type = GetTypeDefOrRef (type); - - if (!declaring_type.IsArray) - this.context = declaring_type; - - var member = ReadMemberReferenceSignature (signature, declaring_type); - member.Name = name; - - return member; - } - - MemberReference ReadMemberReferenceSignature (uint signature, TypeReference declaring_type) - { - var reader = ReadSignature (signature); - const byte field_sig = 0x6; - - if (reader.buffer [reader.position] == field_sig) { - reader.position++; - var field = new FieldReference (); - field.DeclaringType = declaring_type; - field.FieldType = reader.ReadTypeSignature (); - return field; - } else { - var method = new MethodReference (); - method.DeclaringType = declaring_type; - reader.ReadMethodSignature (method); - return method; - } - } - - MemberReference ReadMethodMemberReference (MetadataToken token, string name, uint signature) - { - var method = GetMethodDefinition (token.RID); - - this.context = method; - - var member = ReadMemberReferenceSignature (signature, method.DeclaringType); - member.Name = name; - - return member; - } - - void InitializeMemberReferences () - { - if (metadata.MemberReferences != null) - return; - - metadata.MemberReferences = new MemberReference [image.GetTableLength (Table.MemberRef)]; - } - - public IEnumerable GetMemberReferences () - { - InitializeMemberReferences (); - - var length = image.GetTableLength (Table.MemberRef); - - var type_system = module.TypeSystem; - - var context = new MethodDefinition (string.Empty, MethodAttributes.Static, type_system.Void); - context.DeclaringType = new TypeDefinition (string.Empty, string.Empty, TypeAttributes.Public); - - var member_references = new MemberReference [length]; - - for (uint i = 1; i <= length; i++) { - this.context = context; - member_references [i - 1] = GetMemberReference (i); - } - - return member_references; - } - - void InitializeConstants () - { - if (metadata.Constants != null) - return; - - var length = MoveTo (Table.Constant); - - var constants = metadata.Constants = new Dictionary> (length); - - for (uint i = 1; i <= length; i++) { - var type = (ElementType)ReadUInt16 (); - var owner = ReadMetadataToken (CodedIndex.HasConstant); - var signature = ReadBlobIndex (); - - constants.Add (owner, new Row (type, signature)); - } - } - - public TypeReference ReadConstantSignature (MetadataToken token) - { - if (token.TokenType != TokenType.Signature) - throw new NotSupportedException (); - - if (token.RID == 0) - return null; - - if (!MoveTo (Table.StandAloneSig, token.RID)) - return null; - - return ReadFieldType (ReadBlobIndex ()); - } - - public object ReadConstant (IConstantProvider owner) - { - InitializeConstants (); - - Row row; - if (!metadata.Constants.TryGetValue (owner.MetadataToken, out row)) - return Mixin.NoValue; - - metadata.Constants.Remove (owner.MetadataToken); - - return ReadConstantValue (row.Col1, row.Col2); - } - - object ReadConstantValue (ElementType etype, uint signature) - { - switch (etype) { - case ElementType.Class: - case ElementType.Object: - return null; - case ElementType.String: - return ReadConstantString (signature); - default: - return ReadConstantPrimitive (etype, signature); - } - } - - string ReadConstantString (uint signature) - { - byte [] blob; - int index, count; - - GetBlobView (signature, out blob, out index, out count); - if (count == 0) - return string.Empty; - - if ((count & 1) == 1) - count--; - - return Encoding.Unicode.GetString (blob, index, count); - } - - object ReadConstantPrimitive (ElementType type, uint signature) - { - var reader = ReadSignature (signature); - return reader.ReadConstantSignature (type); - } - - internal void InitializeCustomAttributes () - { - if (metadata.CustomAttributes != null) - return; - - metadata.CustomAttributes = InitializeRanges ( - Table.CustomAttribute, () => { - var next = ReadMetadataToken (CodedIndex.HasCustomAttribute); - ReadMetadataToken (CodedIndex.CustomAttributeType); - ReadBlobIndex (); - return next; - }); - } - - public bool HasCustomAttributes (ICustomAttributeProvider owner) - { - InitializeCustomAttributes (); - - Range [] ranges; - if (!metadata.TryGetCustomAttributeRanges (owner, out ranges)) - return false; - - return RangesSize (ranges) > 0; - } - - public Collection ReadCustomAttributes (ICustomAttributeProvider owner) - { - InitializeCustomAttributes (); - - Range [] ranges; - if (!metadata.TryGetCustomAttributeRanges (owner, out ranges)) - return new Collection (); - - var custom_attributes = new Collection (RangesSize (ranges)); - - for (int i = 0; i < ranges.Length; i++) - ReadCustomAttributeRange (ranges [i], custom_attributes); - - metadata.RemoveCustomAttributeRange (owner); - - if (module.IsWindowsMetadata ()) - foreach (var custom_attribute in custom_attributes) - WindowsRuntimeProjections.Project (owner, custom_attribute); - - return custom_attributes; - } - - void ReadCustomAttributeRange (Range range, Collection custom_attributes) - { - if (!MoveTo (Table.CustomAttribute, range.Start)) - return; - - for (var i = 0; i < range.Length; i++) { - ReadMetadataToken (CodedIndex.HasCustomAttribute); - - var constructor = (MethodReference)LookupToken ( - ReadMetadataToken (CodedIndex.CustomAttributeType)); - - var signature = ReadBlobIndex (); - - custom_attributes.Add (new CustomAttribute (signature, constructor)); - } - } - - static int RangesSize (Range [] ranges) - { - uint size = 0; - for (int i = 0; i < ranges.Length; i++) - size += ranges [i].Length; - - return (int)size; - } - - public IEnumerable GetCustomAttributes () - { - InitializeTypeDefinitions (); - - var length = image.TableHeap [Table.CustomAttribute].Length; - var custom_attributes = new Collection ((int)length); - ReadCustomAttributeRange (new Range (1, length), custom_attributes); - - return custom_attributes; - } - - public byte [] ReadCustomAttributeBlob (uint signature) - { - return ReadBlob (signature); - } - - public void ReadCustomAttributeSignature (CustomAttribute attribute) - { - var reader = ReadSignature (attribute.signature); - - if (!reader.CanReadMore ()) - return; - - if (reader.ReadUInt16 () != 0x0001) - throw new InvalidOperationException (); - - var constructor = attribute.Constructor; - if (constructor.HasParameters) - reader.ReadCustomAttributeConstructorArguments (attribute, constructor.Parameters); - - if (!reader.CanReadMore ()) - return; - - var named = reader.ReadUInt16 (); - - if (named == 0) - return; - - reader.ReadCustomAttributeNamedArguments (named, ref attribute.fields, ref attribute.properties); - } - - void InitializeMarshalInfos () - { - if (metadata.FieldMarshals != null) - return; - - var length = MoveTo (Table.FieldMarshal); - - var marshals = metadata.FieldMarshals = new Dictionary (length); - - for (int i = 0; i < length; i++) { - var token = ReadMetadataToken (CodedIndex.HasFieldMarshal); - var signature = ReadBlobIndex (); - if (token.RID == 0) - continue; - - marshals.Add (token, signature); - } - } - - public bool HasMarshalInfo (IMarshalInfoProvider owner) - { - InitializeMarshalInfos (); - - return metadata.FieldMarshals.ContainsKey (owner.MetadataToken); - } - - public MarshalInfo ReadMarshalInfo (IMarshalInfoProvider owner) - { - InitializeMarshalInfos (); - - uint signature; - if (!metadata.FieldMarshals.TryGetValue (owner.MetadataToken, out signature)) - return null; - - var reader = ReadSignature (signature); - - metadata.FieldMarshals.Remove (owner.MetadataToken); - - return reader.ReadMarshalInfo (); - } - - void InitializeSecurityDeclarations () - { - if (metadata.SecurityDeclarations != null) - return; - - metadata.SecurityDeclarations = InitializeRanges ( - Table.DeclSecurity, () => { - ReadUInt16 (); - var next = ReadMetadataToken (CodedIndex.HasDeclSecurity); - ReadBlobIndex (); - return next; - }); - } - - public bool HasSecurityDeclarations (ISecurityDeclarationProvider owner) - { - InitializeSecurityDeclarations (); - - Range [] ranges; - if (!metadata.TryGetSecurityDeclarationRanges (owner, out ranges)) - return false; - - return RangesSize (ranges) > 0; - } - - public Collection ReadSecurityDeclarations (ISecurityDeclarationProvider owner) - { - InitializeSecurityDeclarations (); - - Range [] ranges; - if (!metadata.TryGetSecurityDeclarationRanges (owner, out ranges)) - return new Collection (); - - var security_declarations = new Collection (RangesSize (ranges)); - - for (int i = 0; i < ranges.Length; i++) - ReadSecurityDeclarationRange (ranges [i], security_declarations); - - metadata.RemoveSecurityDeclarationRange (owner); - - return security_declarations; - } - - void ReadSecurityDeclarationRange (Range range, Collection security_declarations) - { - if (!MoveTo (Table.DeclSecurity, range.Start)) - return; - - for (int i = 0; i < range.Length; i++) { - var action = (SecurityAction)ReadUInt16 (); - ReadMetadataToken (CodedIndex.HasDeclSecurity); - var signature = ReadBlobIndex (); - - security_declarations.Add (new SecurityDeclaration (action, signature, module)); - } - } - - public byte [] ReadSecurityDeclarationBlob (uint signature) - { - return ReadBlob (signature); - } - - public void ReadSecurityDeclarationSignature (SecurityDeclaration declaration) - { - var signature = declaration.signature; - var reader = ReadSignature (signature); - - if (reader.buffer [reader.position] != '.') { - ReadXmlSecurityDeclaration (signature, declaration); - return; - } - - reader.position++; - var count = reader.ReadCompressedUInt32 (); - var attributes = new Collection ((int)count); - - for (int i = 0; i < count; i++) - attributes.Add (reader.ReadSecurityAttribute ()); - - declaration.security_attributes = attributes; - } - - void ReadXmlSecurityDeclaration (uint signature, SecurityDeclaration declaration) - { - var attributes = new Collection (1); - - var attribute = new SecurityAttribute ( - module.TypeSystem.LookupType ("System.Security.Permissions", "PermissionSetAttribute")); - - attribute.properties = new Collection (1); - attribute.properties.Add ( - new CustomAttributeNamedArgument ( - "XML", - new CustomAttributeArgument ( - module.TypeSystem.String, - ReadUnicodeStringBlob (signature)))); - - attributes.Add (attribute); - - declaration.security_attributes = attributes; - } - - public Collection ReadExportedTypes () - { - var length = MoveTo (Table.ExportedType); - if (length == 0) - return new Collection (); - - var exported_types = new Collection (length); - - for (int i = 1; i <= length; i++) { - var attributes = (TypeAttributes)ReadUInt32 (); - var identifier = ReadUInt32 (); - var name = ReadString (); - var @namespace = ReadString (); - var implementation = ReadMetadataToken (CodedIndex.Implementation); - - ExportedType declaring_type = null; - IMetadataScope scope = null; - - switch (implementation.TokenType) { - case TokenType.AssemblyRef: - case TokenType.File: - scope = GetExportedTypeScope (implementation); - break; - case TokenType.ExportedType: - // FIXME: if the table is not properly sorted - declaring_type = exported_types [(int)implementation.RID - 1]; - break; - } - - var exported_type = new ExportedType (@namespace, name, module, scope) { - Attributes = attributes, - Identifier = (int)identifier, - DeclaringType = declaring_type, - }; - exported_type.token = new MetadataToken (TokenType.ExportedType, i); - - exported_types.Add (exported_type); - } - - return exported_types; - } - - IMetadataScope GetExportedTypeScope (MetadataToken token) - { - var position = this.position; - IMetadataScope scope; - - switch (token.TokenType) { - case TokenType.AssemblyRef: - InitializeAssemblyReferences (); - scope = metadata.GetAssemblyNameReference (token.RID); - break; - case TokenType.File: - InitializeModuleReferences (); - scope = GetModuleReferenceFromFile (token); - break; - default: - throw new NotSupportedException (); - } - - this.position = position; - return scope; - } - - ModuleReference GetModuleReferenceFromFile (MetadataToken token) - { - if (!MoveTo (Table.File, token.RID)) - return null; - - ReadUInt32 (); - var file_name = ReadString (); - var modules = module.ModuleReferences; - - ModuleReference reference; - for (int i = 0; i < modules.Count; i++) { - reference = modules [i]; - if (reference.Name == file_name) - return reference; - } - - reference = new ModuleReference (file_name); - modules.Add (reference); - return reference; - } - - void InitializeDocuments () - { - if (metadata.Documents != null) - return; - - int length = MoveTo (Table.Document); - - var documents = metadata.Documents = new Document [length]; - - for (uint i = 1; i <= length; i++) { - var name_index = ReadBlobIndex (); - var hash_algorithm = ReadGuid (); - var hash = ReadBlob (); - var language = ReadGuid (); - - var signature = ReadSignature (name_index); - var name = signature.ReadDocumentName (); - - documents [i - 1] = new Document (name) { - HashAlgorithmGuid = hash_algorithm, - Hash = hash, - LanguageGuid = language, - token = new MetadataToken (TokenType.Document, i), - }; - } - } - - public Collection ReadSequencePoints (MethodDefinition method) - { - InitializeDocuments (); - - if (!MoveTo (Table.MethodDebugInformation, method.MetadataToken.RID)) - return new Collection (0); - - var document_index = ReadTableIndex (Table.Document); - var signature = ReadBlobIndex (); - if (signature == 0) - return new Collection (0); - - var document = GetDocument (document_index); - var reader = ReadSignature (signature); - - return reader.ReadSequencePoints (document); - } - - public Document GetDocument (uint rid) - { - var document = metadata.GetDocument (rid); - if (document == null) - return null; - - document.custom_infos = GetCustomDebugInformation (document); - return document; - } - - void InitializeLocalScopes () - { - if (metadata.LocalScopes != null) - return; - - InitializeMethods (); - - int length = MoveTo (Table.LocalScope); - - metadata.LocalScopes = new Dictionary>> (); - - for (uint i = 1; i <= length; i++) { - var method = ReadTableIndex (Table.Method); - var import = ReadTableIndex (Table.ImportScope); - var variables = ReadListRange (i, Table.LocalScope, Table.LocalVariable); - var constants = ReadListRange (i, Table.LocalScope, Table.LocalConstant); - var scope_start = ReadUInt32 (); - var scope_length = ReadUInt32 (); - - metadata.SetLocalScopes (method, AddMapping (metadata.LocalScopes, method, new Row (import, variables, constants, scope_start, scope_length, i))); - } - } - - public ScopeDebugInformation ReadScope (MethodDefinition method) - { - InitializeLocalScopes (); - InitializeImportScopes (); - - Collection> records; - if (!metadata.TryGetLocalScopes (method, out records)) - return null; - - var method_scope = null as ScopeDebugInformation; - - for (int i = 0; i < records.Count; i++) { - var scope = ReadLocalScope (records [i]); - - if (i == 0) { - method_scope = scope; - continue; - } - - if (!AddScope (method_scope.scopes, scope)) - method_scope.Scopes.Add (scope); - } - - return method_scope; - } - - static bool AddScope (Collection scopes, ScopeDebugInformation scope) - { - if (scopes.IsNullOrEmpty ()) - return false; - - foreach (var sub_scope in scopes) { - if (sub_scope.HasScopes && AddScope (sub_scope.Scopes, scope)) - return true; - - if (scope.Start.Offset >= sub_scope.Start.Offset && scope.End.Offset <= sub_scope.End.Offset) { - sub_scope.Scopes.Add (scope); - return true; - } - } - - return false; - } - - ScopeDebugInformation ReadLocalScope (Row record) - { - var scope = new ScopeDebugInformation { - start = new InstructionOffset ((int)record.Col4), - end = new InstructionOffset ((int)(record.Col4 + record.Col5)), - token = new MetadataToken (TokenType.LocalScope, record.Col6), - }; - - if (record.Col1 > 0) - scope.import = metadata.GetImportScope (record.Col1); - - if (record.Col2.Length > 0) { - scope.variables = new Collection ((int)record.Col2.Length); - for (uint i = 0; i < record.Col2.Length; i++) { - var variable = ReadLocalVariable (record.Col2.Start + i); - if (variable != null) - scope.variables.Add (variable); - } - } - - if (record.Col3.Length > 0) { - scope.constants = new Collection ((int)record.Col3.Length); - for (uint i = 0; i < record.Col3.Length; i++) { - var constant = ReadLocalConstant (record.Col3.Start + i); - if (constant != null) - scope.constants.Add (constant); - } - } - - return scope; - } - - VariableDebugInformation ReadLocalVariable (uint rid) - { - if (!MoveTo (Table.LocalVariable, rid)) - return null; - - var attributes = (VariableAttributes)ReadUInt16 (); - var index = ReadUInt16 (); - var name = ReadString (); - - var variable = new VariableDebugInformation (index, name) { Attributes = attributes, token = new MetadataToken (TokenType.LocalVariable, rid) }; - variable.custom_infos = GetCustomDebugInformation (variable); - return variable; - } - - ConstantDebugInformation ReadLocalConstant (uint rid) - { - if (!MoveTo (Table.LocalConstant, rid)) - return null; - - var name = ReadString (); - var signature = ReadSignature (ReadBlobIndex ()); - var type = signature.ReadTypeSignature (); - - object value; - if (type.etype == ElementType.String) { - if (signature.CanReadMore () && signature.buffer [signature.position] != 0xff) { - var bytes = signature.ReadBytes ((int)(signature.sig_length - (signature.position - signature.start))); - value = Encoding.Unicode.GetString (bytes, 0, bytes.Length); - } else - value = null; - } else if (type.IsTypeOf ("System", "Decimal")) { - var b = signature.ReadByte (); - value = new decimal (signature.ReadInt32 (), signature.ReadInt32 (), signature.ReadInt32 (), (b & 0x80) != 0, (byte)(b & 0x7f)); - } else if (type.IsTypeOf ("System", "DateTime")) { - value = new DateTime (signature.ReadInt64 ()); - } else if (type.etype == ElementType.Object || type.etype == ElementType.None || type.etype == ElementType.Class || type.etype == ElementType.Array || type.etype == ElementType.GenericInst) { - value = null; - } else - value = signature.ReadConstantSignature (type.etype); - - var constant = new ConstantDebugInformation (name, type, value) { token = new MetadataToken (TokenType.LocalConstant, rid) }; - constant.custom_infos = GetCustomDebugInformation (constant); - return constant; - } - - void InitializeImportScopes () - { - if (metadata.ImportScopes != null) - return; - - var length = MoveTo (Table.ImportScope); - - metadata.ImportScopes = new ImportDebugInformation [length]; - - for (int i = 1; i <= length; i++) { - ReadTableIndex (Table.ImportScope); - - var import = new ImportDebugInformation (); - import.token = new MetadataToken (TokenType.ImportScope, i); - - var signature = ReadSignature (ReadBlobIndex ()); - while (signature.CanReadMore ()) - import.Targets.Add (ReadImportTarget (signature)); - - metadata.ImportScopes [i - 1] = import; - } - - MoveTo (Table.ImportScope); - - for (int i = 0; i < length; i++) { - var parent = ReadTableIndex (Table.ImportScope); - - ReadBlobIndex (); - - if (parent != 0) - metadata.ImportScopes [i].Parent = metadata.GetImportScope (parent); - } - } - - public string ReadUTF8StringBlob (uint signature) - { - return ReadStringBlob (signature, Encoding.UTF8); - } - - string ReadUnicodeStringBlob (uint signature) - { - return ReadStringBlob (signature, Encoding.Unicode); - } - - string ReadStringBlob (uint signature, Encoding encoding) - { - byte [] blob; - int index, count; - - GetBlobView (signature, out blob, out index, out count); - if (count == 0) - return string.Empty; - - return encoding.GetString (blob, index, count); - } - - ImportTarget ReadImportTarget (SignatureReader signature) - { - AssemblyNameReference reference = null; - string @namespace = null; - string alias = null; - TypeReference type = null; - - var kind = (ImportTargetKind)signature.ReadCompressedUInt32 (); - switch (kind) { - case ImportTargetKind.ImportNamespace: - @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - break; - case ImportTargetKind.ImportNamespaceInAssembly: - reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ()); - @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - break; - case ImportTargetKind.ImportType: - type = signature.ReadTypeToken (); - break; - case ImportTargetKind.ImportXmlNamespaceWithAlias: - alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - break; - case ImportTargetKind.ImportAlias: - alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - break; - case ImportTargetKind.DefineAssemblyAlias: - alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ()); - break; - case ImportTargetKind.DefineNamespaceAlias: - alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - break; - case ImportTargetKind.DefineNamespaceInAssemblyAlias: - alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ()); - @namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - break; - case ImportTargetKind.DefineTypeAlias: - alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ()); - type = signature.ReadTypeToken (); - break; - } - - return new ImportTarget (kind) { - alias = alias, - type = type, - @namespace = @namespace, - reference = reference, - }; - } - - void InitializeStateMachineMethods () - { - if (metadata.StateMachineMethods != null) - return; - - var length = MoveTo (Table.StateMachineMethod); - - metadata.StateMachineMethods = new Dictionary (length); - - for (int i = 0; i < length; i++) - metadata.StateMachineMethods.Add (ReadTableIndex (Table.Method), ReadTableIndex (Table.Method)); - } - - public MethodDefinition ReadStateMachineKickoffMethod (MethodDefinition method) - { - InitializeStateMachineMethods (); - - uint rid; - if (!metadata.TryGetStateMachineKickOffMethod (method, out rid)) - return null; - - return GetMethodDefinition (rid); - } - - void InitializeCustomDebugInformations () - { - if (metadata.CustomDebugInformations != null) - return; - - var length = MoveTo (Table.CustomDebugInformation); - - metadata.CustomDebugInformations = new Dictionary []> (); - - for (uint i = 1; i <= length; i++) { - var token = ReadMetadataToken (CodedIndex.HasCustomDebugInformation); - var info = new Row (ReadGuid (), ReadBlobIndex (), i); - - Row [] infos; - metadata.CustomDebugInformations.TryGetValue (token, out infos); - metadata.CustomDebugInformations [token] = infos.Add (info); - } - } - - public Collection GetCustomDebugInformation (ICustomDebugInformationProvider provider) - { - InitializeCustomDebugInformations (); - - Row [] rows; - if (!metadata.CustomDebugInformations.TryGetValue (provider.MetadataToken, out rows)) - return null; - - var infos = new Collection (rows.Length); - - for (int i = 0; i < rows.Length; i++) { - if (rows [i].Col1 == StateMachineScopeDebugInformation.KindIdentifier) { - var signature = ReadSignature (rows [i].Col2); - var scopes = new Collection (); - - while (signature.CanReadMore ()) { - var start = signature.ReadInt32 (); - var end = start + signature.ReadInt32 (); - scopes.Add (new StateMachineScope (start, end)); - } - - var state_machine = new StateMachineScopeDebugInformation (); - state_machine.scopes = scopes; - - infos.Add (state_machine); - } else if (rows [i].Col1 == AsyncMethodBodyDebugInformation.KindIdentifier) { - var signature = ReadSignature (rows [i].Col2); - - var catch_offset = signature.ReadInt32 () - 1; - var yields = new Collection (); - var resumes = new Collection (); - var resume_methods = new Collection (); - - while (signature.CanReadMore ()) { - yields.Add (new InstructionOffset (signature.ReadInt32 ())); - resumes.Add (new InstructionOffset (signature.ReadInt32 ())); - resume_methods.Add (GetMethodDefinition (signature.ReadCompressedUInt32 ())); - } - - var async_body = new AsyncMethodBodyDebugInformation (catch_offset); - async_body.yields = yields; - async_body.resumes = resumes; - async_body.resume_methods = resume_methods; - - infos.Add (async_body); - } else if (rows [i].Col1 == EmbeddedSourceDebugInformation.KindIdentifier) { - infos.Add (new EmbeddedSourceDebugInformation (rows [i].Col2, this)); - } else if (rows [i].Col1 == SourceLinkDebugInformation.KindIdentifier) { - infos.Add (new SourceLinkDebugInformation (Encoding.UTF8.GetString (ReadBlob (rows [i].Col2)))); - } else { - infos.Add (new BinaryCustomDebugInformation (rows [i].Col1, ReadBlob (rows [i].Col2))); - } - - infos [i].token = new MetadataToken (TokenType.CustomDebugInformation, rows [i].Col3); - } - - return infos; - } - - public byte [] ReadRawEmbeddedSourceDebugInformation (uint index) - { - var signature = ReadSignature (index); - return signature.ReadBytes ((int)signature.sig_length); - } - - public Row ReadEmbeddedSourceDebugInformation (uint index) - { - var signature = ReadSignature (index); - var format = signature.ReadInt32 (); - var length = signature.sig_length - 4; - - if (format == 0) { - return new Row (signature.ReadBytes ((int)length), false); - } else if (format > 0) { - var compressed_stream = new MemoryStream (signature.ReadBytes ((int)length)); - var decompressed_document = new byte [format]; // if positive, format is the decompressed length of the document - var decompressed_stream = new MemoryStream (decompressed_document); - - using (var deflate_stream = new DeflateStream (compressed_stream, CompressionMode.Decompress, leaveOpen: true)) - deflate_stream.CopyTo (decompressed_stream); - - return new Row (decompressed_document, true); - } else - throw new NotSupportedException (); - } - } - - sealed class SignatureReader : ByteBuffer { - - readonly MetadataReader reader; - readonly internal uint start, sig_length; - - TypeSystem TypeSystem { - get { return reader.module.TypeSystem; } - } - - public SignatureReader (uint blob, MetadataReader reader) - : base (reader.image.BlobHeap.data) - { - this.reader = reader; - this.position = (int)blob; - this.sig_length = ReadCompressedUInt32 (); - this.start = (uint)this.position; - } - - MetadataToken ReadTypeTokenSignature () - { - return CodedIndex.TypeDefOrRef.GetMetadataToken (ReadCompressedUInt32 ()); - } - - GenericParameter GetGenericParameter (GenericParameterType type, uint var) - { - var context = reader.context; - int index = (int)var; - - if (context == null) - return GetUnboundGenericParameter (type, index); - - IGenericParameterProvider provider; - - switch (type) { - case GenericParameterType.Type: - provider = context.Type; - break; - case GenericParameterType.Method: - provider = context.Method; - break; - default: - throw new NotSupportedException (); - } - - if (!context.IsDefinition) - CheckGenericContext (provider, index); - - if (index >= provider.GenericParameters.Count) - return GetUnboundGenericParameter (type, index); - - return provider.GenericParameters [index]; - } - - GenericParameter GetUnboundGenericParameter (GenericParameterType type, int index) - { - return new GenericParameter (index, type, reader.module); - } - - static void CheckGenericContext (IGenericParameterProvider owner, int index) - { - var owner_parameters = owner.GenericParameters; - - for (int i = owner_parameters.Count; i <= index; i++) - owner_parameters.Add (new GenericParameter (owner)); - } - - public void ReadGenericInstanceSignature (IGenericParameterProvider provider, IGenericInstance instance, uint arity) - { - if (!provider.IsDefinition) - CheckGenericContext (provider, (int)arity - 1); - - var instance_arguments = instance.GenericArguments; - - for (int i = 0; i < arity; i++) - instance_arguments.Add (ReadTypeSignature ()); - } - - ArrayType ReadArrayTypeSignature () - { - var array = new ArrayType (ReadTypeSignature ()); - - var rank = ReadCompressedUInt32 (); - - var sizes = new uint [ReadCompressedUInt32 ()]; - for (int i = 0; i < sizes.Length; i++) - sizes [i] = ReadCompressedUInt32 (); - - var low_bounds = new int [ReadCompressedUInt32 ()]; - for (int i = 0; i < low_bounds.Length; i++) - low_bounds [i] = ReadCompressedInt32 (); - - array.Dimensions.Clear (); - - for (int i = 0; i < rank; i++) { - int? lower = null, upper = null; - - if (i < low_bounds.Length) - lower = low_bounds [i]; - - if (i < sizes.Length) - upper = lower + (int)sizes [i] - 1; - - array.Dimensions.Add (new ArrayDimension (lower, upper)); - } - - return array; - } - - TypeReference GetTypeDefOrRef (MetadataToken token) - { - return reader.GetTypeDefOrRef (token); - } - - public TypeReference ReadTypeSignature () - { - return ReadTypeSignature ((ElementType)ReadByte ()); - } - - public TypeReference ReadTypeToken () - { - return GetTypeDefOrRef (ReadTypeTokenSignature ()); - } - - TypeReference ReadTypeSignature (ElementType etype) - { - switch (etype) { - case ElementType.ValueType: { - var value_type = GetTypeDefOrRef (ReadTypeTokenSignature ()); - value_type.KnownValueType (); - return value_type; - } - case ElementType.Class: - return GetTypeDefOrRef (ReadTypeTokenSignature ()); - case ElementType.Ptr: - return new PointerType (ReadTypeSignature ()); - case ElementType.FnPtr: { - var fptr = new FunctionPointerType (); - ReadMethodSignature (fptr); - return fptr; - } - case ElementType.ByRef: - return new ByReferenceType (ReadTypeSignature ()); - case ElementType.Pinned: - return new PinnedType (ReadTypeSignature ()); - case ElementType.SzArray: - return new ArrayType (ReadTypeSignature ()); - case ElementType.Array: - return ReadArrayTypeSignature (); - case ElementType.CModOpt: - return new OptionalModifierType ( - GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ()); - case ElementType.CModReqD: - return new RequiredModifierType ( - GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ()); - case ElementType.Sentinel: - return new SentinelType (ReadTypeSignature ()); - case ElementType.Var: - return GetGenericParameter (GenericParameterType.Type, ReadCompressedUInt32 ()); - case ElementType.MVar: - return GetGenericParameter (GenericParameterType.Method, ReadCompressedUInt32 ()); - case ElementType.GenericInst: { - var is_value_type = ReadByte () == (byte)ElementType.ValueType; - var element_type = GetTypeDefOrRef (ReadTypeTokenSignature ()); - - var arity = ReadCompressedUInt32 (); - var generic_instance = new GenericInstanceType (element_type, (int)arity); - - ReadGenericInstanceSignature (element_type, generic_instance, arity); - - if (is_value_type) { - generic_instance.KnownValueType (); - element_type.GetElementType ().KnownValueType (); - } - - return generic_instance; - } - case ElementType.Object: return TypeSystem.Object; - case ElementType.Void: return TypeSystem.Void; - case ElementType.TypedByRef: return TypeSystem.TypedReference; - case ElementType.I: return TypeSystem.IntPtr; - case ElementType.U: return TypeSystem.UIntPtr; - default: return GetPrimitiveType (etype); - } - } - - public void ReadMethodSignature (IMethodSignature method) - { - var calling_convention = ReadByte (); - - const byte has_this = 0x20; - const byte explicit_this = 0x40; - - if ((calling_convention & has_this) != 0) { - method.HasThis = true; - calling_convention = (byte)(calling_convention & ~has_this); - } - - if ((calling_convention & explicit_this) != 0) { - method.ExplicitThis = true; - calling_convention = (byte)(calling_convention & ~explicit_this); - } - - method.CallingConvention = (MethodCallingConvention)calling_convention; - - var generic_context = method as MethodReference; - if (generic_context != null && !generic_context.DeclaringType.IsArray) - reader.context = generic_context; - - if ((calling_convention & 0x10) != 0) { - var arity = ReadCompressedUInt32 (); - - if (generic_context != null && !generic_context.IsDefinition) - CheckGenericContext (generic_context, (int)arity - 1); - } - - var param_count = ReadCompressedUInt32 (); - - method.MethodReturnType.ReturnType = ReadTypeSignature (); - - if (param_count == 0) - return; - - Collection parameters; - - var method_ref = method as MethodReference; - if (method_ref != null) - parameters = method_ref.parameters = new ParameterDefinitionCollection (method, (int)param_count); - else - parameters = method.Parameters; - - for (int i = 0; i < param_count; i++) - parameters.Add (new ParameterDefinition (ReadTypeSignature ())); - } - - public object ReadConstantSignature (ElementType type) - { - return ReadPrimitiveValue (type); - } - - public void ReadCustomAttributeConstructorArguments (CustomAttribute attribute, Collection parameters) - { - var count = parameters.Count; - if (count == 0) - return; - - attribute.arguments = new Collection (count); - - for (int i = 0; i < count; i++) - attribute.arguments.Add ( - ReadCustomAttributeFixedArgument (parameters [i].ParameterType)); - } - - CustomAttributeArgument ReadCustomAttributeFixedArgument (TypeReference type) - { - if (type.IsArray) - return ReadCustomAttributeFixedArrayArgument ((ArrayType)type); - - return ReadCustomAttributeElement (type); - } - - public void ReadCustomAttributeNamedArguments (ushort count, ref Collection fields, ref Collection properties) - { - for (int i = 0; i < count; i++) { - if (!CanReadMore ()) - return; - ReadCustomAttributeNamedArgument (ref fields, ref properties); - } - } - - void ReadCustomAttributeNamedArgument (ref Collection fields, ref Collection properties) - { - var kind = ReadByte (); - var type = ReadCustomAttributeFieldOrPropType (); - var name = ReadUTF8String (); - - Collection container; - switch (kind) { - case 0x53: - container = GetCustomAttributeNamedArgumentCollection (ref fields); - break; - case 0x54: - container = GetCustomAttributeNamedArgumentCollection (ref properties); - break; - default: - throw new NotSupportedException (); - } - - container.Add (new CustomAttributeNamedArgument (name, ReadCustomAttributeFixedArgument (type))); - } - - static Collection GetCustomAttributeNamedArgumentCollection (ref Collection collection) - { - if (collection != null) - return collection; - - return collection = new Collection (); - } - - CustomAttributeArgument ReadCustomAttributeFixedArrayArgument (ArrayType type) - { - var length = ReadUInt32 (); - - if (length == 0xffffffff) - return new CustomAttributeArgument (type, null); - - if (length == 0) - return new CustomAttributeArgument (type, Empty.Array); - - var arguments = new CustomAttributeArgument [length]; - var element_type = type.ElementType; - - for (int i = 0; i < length; i++) - arguments [i] = ReadCustomAttributeElement (element_type); - - return new CustomAttributeArgument (type, arguments); - } - - CustomAttributeArgument ReadCustomAttributeElement (TypeReference type) - { - if (type.IsArray) - return ReadCustomAttributeFixedArrayArgument ((ArrayType)type); - - return new CustomAttributeArgument ( - type, - type.etype == ElementType.Object - ? ReadCustomAttributeElement (ReadCustomAttributeFieldOrPropType ()) - : ReadCustomAttributeElementValue (type)); - } - - object ReadCustomAttributeElementValue (TypeReference type) - { - var etype = type.etype; - - switch (etype) { - case ElementType.String: - return ReadUTF8String (); - case ElementType.None: - if (type.IsTypeOf ("System", "Type")) - return ReadTypeReference (); - - return ReadCustomAttributeEnum (type); - default: - return ReadPrimitiveValue (etype); - } - } - - object ReadPrimitiveValue (ElementType type) - { - switch (type) { - case ElementType.Boolean: - return ReadByte () == 1; - case ElementType.I1: - return (sbyte)ReadByte (); - case ElementType.U1: - return ReadByte (); - case ElementType.Char: - return (char)ReadUInt16 (); - case ElementType.I2: - return ReadInt16 (); - case ElementType.U2: - return ReadUInt16 (); - case ElementType.I4: - return ReadInt32 (); - case ElementType.U4: - return ReadUInt32 (); - case ElementType.I8: - return ReadInt64 (); - case ElementType.U8: - return ReadUInt64 (); - case ElementType.R4: - return ReadSingle (); - case ElementType.R8: - return ReadDouble (); - default: - throw new NotImplementedException (type.ToString ()); - } - } - - TypeReference GetPrimitiveType (ElementType etype) - { - switch (etype) { - case ElementType.Boolean: - return TypeSystem.Boolean; - case ElementType.Char: - return TypeSystem.Char; - case ElementType.I1: - return TypeSystem.SByte; - case ElementType.U1: - return TypeSystem.Byte; - case ElementType.I2: - return TypeSystem.Int16; - case ElementType.U2: - return TypeSystem.UInt16; - case ElementType.I4: - return TypeSystem.Int32; - case ElementType.U4: - return TypeSystem.UInt32; - case ElementType.I8: - return TypeSystem.Int64; - case ElementType.U8: - return TypeSystem.UInt64; - case ElementType.R4: - return TypeSystem.Single; - case ElementType.R8: - return TypeSystem.Double; - case ElementType.String: - return TypeSystem.String; - default: - throw new NotImplementedException (etype.ToString ()); - } - } - - TypeReference ReadCustomAttributeFieldOrPropType () - { - var etype = (ElementType)ReadByte (); - - switch (etype) { - case ElementType.Boxed: - return TypeSystem.Object; - case ElementType.SzArray: - return new ArrayType (ReadCustomAttributeFieldOrPropType ()); - case ElementType.Enum: - return ReadTypeReference (); - case ElementType.Type: - return TypeSystem.LookupType ("System", "Type"); - default: - return GetPrimitiveType (etype); - } - } - - public TypeReference ReadTypeReference () - { - return TypeParser.ParseType (reader.module, ReadUTF8String ()); - } - - object ReadCustomAttributeEnum (TypeReference enum_type) - { - var type = enum_type.CheckedResolve (); - if (!type.IsEnum) - throw new ArgumentException (); - - return ReadCustomAttributeElementValue (type.GetEnumUnderlyingType ()); - } - - public SecurityAttribute ReadSecurityAttribute () - { - var attribute = new SecurityAttribute (ReadTypeReference ()); - - ReadCompressedUInt32 (); - - ReadCustomAttributeNamedArguments ( - (ushort)ReadCompressedUInt32 (), - ref attribute.fields, - ref attribute.properties); - - return attribute; - } - - public MarshalInfo ReadMarshalInfo () - { - var native = ReadNativeType (); - switch (native) { - case NativeType.Array: { - var array = new ArrayMarshalInfo (); - if (CanReadMore ()) - array.element_type = ReadNativeType (); - if (CanReadMore ()) - array.size_parameter_index = (int)ReadCompressedUInt32 (); - if (CanReadMore ()) - array.size = (int)ReadCompressedUInt32 (); - if (CanReadMore ()) - array.size_parameter_multiplier = (int)ReadCompressedUInt32 (); - return array; - } - case NativeType.SafeArray: { - var array = new SafeArrayMarshalInfo (); - if (CanReadMore ()) - array.element_type = ReadVariantType (); - return array; - } - case NativeType.FixedArray: { - var array = new FixedArrayMarshalInfo (); - if (CanReadMore ()) - array.size = (int)ReadCompressedUInt32 (); - if (CanReadMore ()) - array.element_type = ReadNativeType (); - return array; - } - case NativeType.FixedSysString: { - var sys_string = new FixedSysStringMarshalInfo (); - if (CanReadMore ()) - sys_string.size = (int)ReadCompressedUInt32 (); - return sys_string; - } - case NativeType.CustomMarshaler: { - var marshaler = new CustomMarshalInfo (); - var guid_value = ReadUTF8String (); - marshaler.guid = !string.IsNullOrEmpty (guid_value) ? new Guid (guid_value) : Guid.Empty; - marshaler.unmanaged_type = ReadUTF8String (); - marshaler.managed_type = ReadTypeReference (); - marshaler.cookie = ReadUTF8String (); - return marshaler; - } - default: - return new MarshalInfo (native); - } - } - - NativeType ReadNativeType () - { - return (NativeType)ReadByte (); - } - - VariantType ReadVariantType () - { - return (VariantType)ReadByte (); - } - - string ReadUTF8String () - { - if (buffer [position] == 0xff) { - position++; - return null; - } - - var length = (int)ReadCompressedUInt32 (); - if (length == 0) - return string.Empty; - - if (position + length > buffer.Length) - return string.Empty; - - var @string = Encoding.UTF8.GetString (buffer, position, length); - - position += length; - return @string; - } - - public string ReadDocumentName () - { - var separator = (char)buffer [position]; - position++; - - var builder = new StringBuilder (); - for (int i = 0; CanReadMore (); i++) { - if (i > 0 && separator != 0) - builder.Append (separator); - - uint part = ReadCompressedUInt32 (); - if (part != 0) - builder.Append (reader.ReadUTF8StringBlob (part)); - } - - return builder.ToString (); - } - - public Collection ReadSequencePoints (Document document) - { - ReadCompressedUInt32 (); // local_sig_token - - if (document == null) - document = reader.GetDocument (ReadCompressedUInt32 ()); - - var offset = 0; - var start_line = 0; - var start_column = 0; - var first_non_hidden = true; - - //there's about 5 compressed int32's per sequenec points. we don't know exactly how many - //but let's take a conservative guess so we dont end up reallocating the sequence_points collection - //as it grows. - var bytes_remaining_for_sequencepoints = sig_length - (position - start); - var estimated_sequencepoint_amount = (int)bytes_remaining_for_sequencepoints / 5; - var sequence_points = new Collection (estimated_sequencepoint_amount); - - for (var i = 0; CanReadMore (); i++) { - var delta_il = (int)ReadCompressedUInt32 (); - if (i > 0 && delta_il == 0) { - document = reader.GetDocument (ReadCompressedUInt32 ()); - continue; - } - - offset += delta_il; - - var delta_lines = (int)ReadCompressedUInt32 (); - var delta_columns = delta_lines == 0 - ? (int)ReadCompressedUInt32 () - : ReadCompressedInt32 (); - - if (delta_lines == 0 && delta_columns == 0) { - sequence_points.Add (new SequencePoint (offset, document) { - StartLine = 0xfeefee, - EndLine = 0xfeefee, - StartColumn = 0, - EndColumn = 0, - }); - continue; - } - - if (first_non_hidden) { - start_line = (int)ReadCompressedUInt32 (); - start_column = (int)ReadCompressedUInt32 (); - } else { - start_line += ReadCompressedInt32 (); - start_column += ReadCompressedInt32 (); - } - - sequence_points.Add (new SequencePoint (offset, document) { - StartLine = start_line, - StartColumn = start_column, - EndLine = start_line + delta_lines, - EndColumn = start_column + delta_columns, - }); - first_non_hidden = false; - } - - return sequence_points; - } - - public bool CanReadMore () - { - return (position - start) < sig_length; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyReader.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyReader.cs.meta deleted file mode 100644 index 810883e..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyReader.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d8fb74d16029713429e831cb3b5b0861 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyWriter.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyWriter.cs deleted file mode 100644 index 5d74689..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyWriter.cs +++ /dev/null @@ -1,3336 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Cil; -using MonoFN.Cecil.Metadata; -using MonoFN.Cecil.PE; -using MonoFN.Collections.Generic; -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Text; -using BlobIndex = System.UInt32; -using CodedRID = System.UInt32; -using GuidIndex = System.UInt32; -using RID = System.UInt32; -using RVA = System.UInt32; -using StringIndex = System.UInt32; - -namespace MonoFN.Cecil { - - using AssemblyRefRow = Row; - using AssemblyRow = Row; - using ClassLayoutRow = Row; - using ConstantRow = Row; - using CustomAttributeRow = Row; - using CustomDebugInformationRow = Row; - using DeclSecurityRow = Row; - using DocumentRow = Row; - using EventMapRow = Row; - using EventRow = Row; - using ExportedTypeRow = Row; - using FieldLayoutRow = Row; - using FieldMarshalRow = Row; - using FieldRow = Row; - using FieldRVARow = Row; - using FileRow = Row; - using GenericParamConstraintRow = Row; - using GenericParamRow = Row; - using ImplMapRow = Row; - using ImportScopeRow = Row; - using InterfaceImplRow = Row; - using LocalConstantRow = Row; - using LocalScopeRow = Row; - using LocalVariableRow = Row; - using ManifestResourceRow = Row; - using MemberRefRow = Row; - using MethodDebugInformationRow = Row; - using MethodImplRow = Row; - using MethodRow = Row; - using MethodSemanticsRow = Row; - using MethodSpecRow = Row; - using ModuleRow = Row; - using NestedClassRow = Row; - using ParamRow = Row; - using PropertyMapRow = Row; - using PropertyRow = Row; - using StateMachineMethodRow = Row; - using TypeDefRow = Row; - using TypeRefRow = Row; - - static class ModuleWriter { - - public static void WriteModule (ModuleDefinition module, Disposable stream, WriterParameters parameters) - { - using (stream) - Write (module, stream, parameters); - } - - static void Write (ModuleDefinition module, Disposable stream, WriterParameters parameters) - { - if ((module.Attributes & ModuleAttributes.ILOnly) == 0) - throw new NotSupportedException ("Writing mixed-mode assemblies is not supported"); - - if (module.HasImage && module.ReadingMode == ReadingMode.Deferred) { - var immediate_reader = new ImmediateModuleReader (module.Image); - immediate_reader.ReadModule (module, resolve_attributes: false); - immediate_reader.ReadSymbols (module); - } - - module.MetadataSystem.Clear (); - - if (module.symbol_reader != null) - module.symbol_reader.Dispose (); - - var name = module.assembly != null && module.kind != ModuleKind.NetModule ? module.assembly.Name : null; - var fq_name = stream.value.GetFileName (); - var timestamp = parameters.Timestamp ?? module.timestamp; - var symbol_writer_provider = parameters.SymbolWriterProvider; - - if (symbol_writer_provider == null && parameters.WriteSymbols) - symbol_writer_provider = new DefaultSymbolWriterProvider (); - - if (parameters.HasStrongNameKey && name != null) { - name.PublicKey = CryptoService.GetPublicKey (parameters); - module.Attributes |= ModuleAttributes.StrongNameSigned; - } - - if (parameters.DeterministicMvid) - module.Mvid = Guid.Empty; - - var metadata = new MetadataBuilder (module, fq_name, timestamp, symbol_writer_provider); - try { - module.metadata_builder = metadata; - - using (var symbol_writer = GetSymbolWriter (module, fq_name, symbol_writer_provider, parameters)) { - metadata.SetSymbolWriter (symbol_writer); - BuildMetadata (module, metadata); - - if (parameters.DeterministicMvid) - metadata.ComputeDeterministicMvid (); - - var writer = ImageWriter.CreateWriter (module, metadata, stream); - stream.value.SetLength (0); - writer.WriteImage (); - - if (parameters.HasStrongNameKey) - CryptoService.StrongName (stream.value, writer, parameters); - } - } - finally { - module.metadata_builder = null; - } - } - - static void BuildMetadata (ModuleDefinition module, MetadataBuilder metadata) - { - if (!module.HasImage) { - metadata.BuildMetadata (); - return; - } - - module.Read (metadata, (builder, _) => { - builder.BuildMetadata (); - return builder; - }); - } - - static ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fq_name, ISymbolWriterProvider symbol_writer_provider, WriterParameters parameters) - { - if (symbol_writer_provider == null) - return null; - - if (parameters.SymbolStream != null) - return symbol_writer_provider.GetSymbolWriter (module, parameters.SymbolStream); - - return symbol_writer_provider.GetSymbolWriter (module, fq_name); - } - } - - abstract class MetadataTable { - - public abstract int Length { get; } - - public bool IsLarge { - get { return Length > ushort.MaxValue; } - } - - public abstract void Write (TableHeapBuffer buffer); - public abstract void Sort (); - } - - abstract class OneRowTable : MetadataTable where TRow : struct { - - internal TRow row; - - public sealed override int Length { - get { return 1; } - } - - public sealed override void Sort () - { - } - } - - abstract class MetadataTable : MetadataTable where TRow : struct { - - internal TRow [] rows = new TRow [2]; - internal int length; - - public sealed override int Length { - get { return length; } - } - - public int AddRow (TRow row) - { - if (rows.Length == length) - Grow (); - - rows [length++] = row; - return length; - } - - void Grow () - { - var rows = new TRow [this.rows.Length * 2]; - Array.Copy (this.rows, rows, this.rows.Length); - this.rows = rows; - } - - public override void Sort () - { - } - } - - abstract class SortedTable : MetadataTable, IComparer where TRow : struct { - - public sealed override void Sort () - { - MergeSort.Sort (rows, 0, this.length, this); - } - - protected static int Compare (uint x, uint y) - { - return x == y ? 0 : x > y ? 1 : -1; - } - - public abstract int Compare (TRow x, TRow y); - } - - sealed class ModuleTable : OneRowTable { - - public override void Write (TableHeapBuffer buffer) - { - buffer.WriteUInt16 (0); // Generation - buffer.WriteString (row.Col1); // Name - buffer.WriteGuid (row.Col2); // Mvid - buffer.WriteUInt16 (0); // EncId - buffer.WriteUInt16 (0); // EncBaseId - } - } - - sealed class TypeRefTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteCodedRID ( - rows [i].Col1, CodedIndex.ResolutionScope); // Scope - buffer.WriteString (rows [i].Col2); // Name - buffer.WriteString (rows [i].Col3); // Namespace - } - } - } - - sealed class TypeDefTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt32 ((uint)rows [i].Col1); // Attributes - buffer.WriteString (rows [i].Col2); // Name - buffer.WriteString (rows [i].Col3); // Namespace - buffer.WriteCodedRID ( - rows [i].Col4, CodedIndex.TypeDefOrRef); // Extends - buffer.WriteRID (rows [i].Col5, Table.Field); // FieldList - buffer.WriteRID (rows [i].Col6, Table.Method); // MethodList - } - } - } - - sealed class FieldTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt16 ((ushort)rows [i].Col1); // Attributes - buffer.WriteString (rows [i].Col2); // Name - buffer.WriteBlob (rows [i].Col3); // Signature - } - } - } - - sealed class MethodTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt32 (rows [i].Col1); // RVA - buffer.WriteUInt16 ((ushort)rows [i].Col2); // ImplFlags - buffer.WriteUInt16 ((ushort)rows [i].Col3); // Flags - buffer.WriteString (rows [i].Col4); // Name - buffer.WriteBlob (rows [i].Col5); // Signature - buffer.WriteRID (rows [i].Col6, Table.Param); // ParamList - } - } - } - - sealed class ParamTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt16 ((ushort)rows [i].Col1); // Attributes - buffer.WriteUInt16 (rows [i].Col2); // Sequence - buffer.WriteString (rows [i].Col3); // Name - } - } - } - - sealed class InterfaceImplTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Class - buffer.WriteCodedRID (rows [i].Col2, CodedIndex.TypeDefOrRef); // Interface - } - } - - /*public override int Compare (InterfaceImplRow x, InterfaceImplRow y) - { - return (int) (x.Col1 == y.Col1 ? y.Col2 - x.Col2 : x.Col1 - y.Col1); - }*/ - } - - sealed class MemberRefTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteCodedRID (rows [i].Col1, CodedIndex.MemberRefParent); - buffer.WriteString (rows [i].Col2); - buffer.WriteBlob (rows [i].Col3); - } - } - } - - sealed class ConstantTable : SortedTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt16 ((ushort)rows [i].Col1); - buffer.WriteCodedRID (rows [i].Col2, CodedIndex.HasConstant); - buffer.WriteBlob (rows [i].Col3); - } - } - - public override int Compare (ConstantRow x, ConstantRow y) - { - return Compare (x.Col2, y.Col2); - } - } - - sealed class CustomAttributeTable : SortedTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasCustomAttribute); // Parent - buffer.WriteCodedRID (rows [i].Col2, CodedIndex.CustomAttributeType); // Type - buffer.WriteBlob (rows [i].Col3); - } - } - - public override int Compare (CustomAttributeRow x, CustomAttributeRow y) - { - return Compare (x.Col1, y.Col1); - } - } - - sealed class FieldMarshalTable : SortedTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasFieldMarshal); - buffer.WriteBlob (rows [i].Col2); - } - } - - public override int Compare (FieldMarshalRow x, FieldMarshalRow y) - { - return Compare (x.Col1, y.Col1); - } - } - - sealed class DeclSecurityTable : SortedTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt16 ((ushort)rows [i].Col1); - buffer.WriteCodedRID (rows [i].Col2, CodedIndex.HasDeclSecurity); - buffer.WriteBlob (rows [i].Col3); - } - } - - public override int Compare (DeclSecurityRow x, DeclSecurityRow y) - { - return Compare (x.Col2, y.Col2); - } - } - - sealed class ClassLayoutTable : SortedTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt16 (rows [i].Col1); // PackingSize - buffer.WriteUInt32 (rows [i].Col2); // ClassSize - buffer.WriteRID (rows [i].Col3, Table.TypeDef); // Parent - } - } - - public override int Compare (ClassLayoutRow x, ClassLayoutRow y) - { - return Compare (x.Col3, y.Col3); - } - } - - sealed class FieldLayoutTable : SortedTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt32 (rows [i].Col1); // Offset - buffer.WriteRID (rows [i].Col2, Table.Field); // Parent - } - } - - public override int Compare (FieldLayoutRow x, FieldLayoutRow y) - { - return Compare (x.Col2, y.Col2); - } - } - - sealed class StandAloneSigTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) - buffer.WriteBlob (rows [i]); - } - } - - sealed class EventMapTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Parent - buffer.WriteRID (rows [i].Col2, Table.Event); // EventList - } - } - } - - sealed class EventTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt16 ((ushort)rows [i].Col1); // Flags - buffer.WriteString (rows [i].Col2); // Name - buffer.WriteCodedRID (rows [i].Col3, CodedIndex.TypeDefOrRef); // EventType - } - } - } - - sealed class PropertyMapTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Parent - buffer.WriteRID (rows [i].Col2, Table.Property); // PropertyList - } - } - } - - sealed class PropertyTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt16 ((ushort)rows [i].Col1); // Flags - buffer.WriteString (rows [i].Col2); // Name - buffer.WriteBlob (rows [i].Col3); // Type - } - } - } - - sealed class MethodSemanticsTable : SortedTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt16 ((ushort)rows [i].Col1); // Flags - buffer.WriteRID (rows [i].Col2, Table.Method); // Method - buffer.WriteCodedRID (rows [i].Col3, CodedIndex.HasSemantics); // Association - } - } - - public override int Compare (MethodSemanticsRow x, MethodSemanticsRow y) - { - return Compare (x.Col3, y.Col3); - } - } - - sealed class MethodImplTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Class - buffer.WriteCodedRID (rows [i].Col2, CodedIndex.MethodDefOrRef); // MethodBody - buffer.WriteCodedRID (rows [i].Col3, CodedIndex.MethodDefOrRef); // MethodDeclaration - } - } - } - - sealed class ModuleRefTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) - buffer.WriteString (rows [i]); // Name - } - } - - sealed class TypeSpecTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) - buffer.WriteBlob (rows [i]); // Signature - } - } - - sealed class ImplMapTable : SortedTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt16 ((ushort)rows [i].Col1); // Flags - buffer.WriteCodedRID (rows [i].Col2, CodedIndex.MemberForwarded); // MemberForwarded - buffer.WriteString (rows [i].Col3); // ImportName - buffer.WriteRID (rows [i].Col4, Table.ModuleRef); // ImportScope - } - } - - public override int Compare (ImplMapRow x, ImplMapRow y) - { - return Compare (x.Col2, y.Col2); - } - } - - sealed class FieldRVATable : SortedTable { - - internal int position; - - public override void Write (TableHeapBuffer buffer) - { - position = buffer.position; - for (int i = 0; i < length; i++) { - buffer.WriteUInt32 (rows [i].Col1); // RVA - buffer.WriteRID (rows [i].Col2, Table.Field); // Field - } - } - - public override int Compare (FieldRVARow x, FieldRVARow y) - { - return Compare (x.Col2, y.Col2); - } - } - - sealed class AssemblyTable : OneRowTable { - - public override void Write (TableHeapBuffer buffer) - { - buffer.WriteUInt32 ((uint)row.Col1); // AssemblyHashAlgorithm - buffer.WriteUInt16 (row.Col2); // MajorVersion - buffer.WriteUInt16 (row.Col3); // MinorVersion - buffer.WriteUInt16 (row.Col4); // Build - buffer.WriteUInt16 (row.Col5); // Revision - buffer.WriteUInt32 ((uint)row.Col6); // Flags - buffer.WriteBlob (row.Col7); // PublicKey - buffer.WriteString (row.Col8); // Name - buffer.WriteString (row.Col9); // Culture - } - } - - sealed class AssemblyRefTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt16 (rows [i].Col1); // MajorVersion - buffer.WriteUInt16 (rows [i].Col2); // MinorVersion - buffer.WriteUInt16 (rows [i].Col3); // Build - buffer.WriteUInt16 (rows [i].Col4); // Revision - buffer.WriteUInt32 ((uint)rows [i].Col5); // Flags - buffer.WriteBlob (rows [i].Col6); // PublicKeyOrToken - buffer.WriteString (rows [i].Col7); // Name - buffer.WriteString (rows [i].Col8); // Culture - buffer.WriteBlob (rows [i].Col9); // Hash - } - } - } - - sealed class FileTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt32 ((uint)rows [i].Col1); - buffer.WriteString (rows [i].Col2); - buffer.WriteBlob (rows [i].Col3); - } - } - } - - sealed class ExportedTypeTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt32 ((uint)rows [i].Col1); - buffer.WriteUInt32 (rows [i].Col2); - buffer.WriteString (rows [i].Col3); - buffer.WriteString (rows [i].Col4); - buffer.WriteCodedRID (rows [i].Col5, CodedIndex.Implementation); - } - } - } - - sealed class ManifestResourceTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt32 (rows [i].Col1); - buffer.WriteUInt32 ((uint)rows [i].Col2); - buffer.WriteString (rows [i].Col3); - buffer.WriteCodedRID (rows [i].Col4, CodedIndex.Implementation); - } - } - } - - sealed class NestedClassTable : SortedTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteRID (rows [i].Col1, Table.TypeDef); // NestedClass - buffer.WriteRID (rows [i].Col2, Table.TypeDef); // EnclosingClass - } - } - - public override int Compare (NestedClassRow x, NestedClassRow y) - { - return Compare (x.Col1, y.Col1); - } - } - - sealed class GenericParamTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt16 (rows [i].Col1); // Number - buffer.WriteUInt16 ((ushort)rows [i].Col2); // Flags - buffer.WriteCodedRID (rows [i].Col3, CodedIndex.TypeOrMethodDef); // Owner - buffer.WriteString (rows [i].Col4); // Name - } - } - } - - sealed class MethodSpecTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteCodedRID (rows [i].Col1, CodedIndex.MethodDefOrRef); // Method - buffer.WriteBlob (rows [i].Col2); // Instantiation - } - } - } - - sealed class GenericParamConstraintTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteRID (rows [i].Col1, Table.GenericParam); // Owner - buffer.WriteCodedRID (rows [i].Col2, CodedIndex.TypeDefOrRef); // Constraint - } - } - } - - sealed class DocumentTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteBlob (rows [i].Col1); // Name - buffer.WriteGuid (rows [i].Col2); // HashAlgorithm - buffer.WriteBlob (rows [i].Col3); // Hash - buffer.WriteGuid (rows [i].Col4); // Language - } - } - } - - sealed class MethodDebugInformationTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteRID (rows [i].Col1, Table.Document); // Document - buffer.WriteBlob (rows [i].Col2); // SequencePoints - } - } - } - - sealed class LocalScopeTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteRID (rows [i].Col1, Table.Method); // Method - buffer.WriteRID (rows [i].Col2, Table.ImportScope); // ImportScope - buffer.WriteRID (rows [i].Col3, Table.LocalVariable); // VariableList - buffer.WriteRID (rows [i].Col4, Table.LocalConstant); // ConstantList - buffer.WriteUInt32 (rows [i].Col5); // StartOffset - buffer.WriteUInt32 (rows [i].Col6); // Length - } - } - } - - sealed class LocalVariableTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteUInt16 ((ushort)rows [i].Col1); // Attributes - buffer.WriteUInt16 (rows [i].Col2); // Index - buffer.WriteString (rows [i].Col3); // Name - } - } - } - - sealed class LocalConstantTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteString (rows [i].Col1); // Name - buffer.WriteBlob (rows [i].Col2); // Signature - } - } - } - - sealed class ImportScopeTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteRID (rows [i].Col1, Table.ImportScope); // Parent - buffer.WriteBlob (rows [i].Col2); // Imports - } - } - } - - sealed class StateMachineMethodTable : MetadataTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteRID (rows [i].Col1, Table.Method); // MoveNextMethod - buffer.WriteRID (rows [i].Col2, Table.Method); // KickoffMethod - } - } - } - - sealed class CustomDebugInformationTable : SortedTable { - - public override void Write (TableHeapBuffer buffer) - { - for (int i = 0; i < length; i++) { - buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasCustomDebugInformation); // Parent - buffer.WriteGuid (rows [i].Col2); // Kind - buffer.WriteBlob (rows [i].Col3); // Value - } - } - - public override int Compare (CustomDebugInformationRow x, CustomDebugInformationRow y) - { - return Compare (x.Col1, y.Col1); - } - } - - sealed class MetadataBuilder { - - readonly internal ModuleDefinition module; - readonly internal ISymbolWriterProvider symbol_writer_provider; - internal ISymbolWriter symbol_writer; - readonly internal TextMap text_map; - readonly internal string fq_name; - readonly internal uint timestamp; - - readonly Dictionary type_ref_map; - readonly Dictionary type_spec_map; - readonly Dictionary member_ref_map; - readonly Dictionary method_spec_map; - readonly Collection generic_parameters; - - readonly internal CodeWriter code; - readonly internal DataBuffer data; - readonly internal ResourceBuffer resources; - readonly internal StringHeapBuffer string_heap; - readonly internal GuidHeapBuffer guid_heap; - readonly internal UserStringHeapBuffer user_string_heap; - readonly internal BlobHeapBuffer blob_heap; - readonly internal TableHeapBuffer table_heap; - readonly internal PdbHeapBuffer pdb_heap; - - internal MetadataToken entry_point; - - internal RID type_rid = 1; - internal RID field_rid = 1; - internal RID method_rid = 1; - internal RID param_rid = 1; - internal RID property_rid = 1; - internal RID event_rid = 1; - internal RID local_variable_rid = 1; - internal RID local_constant_rid = 1; - - readonly TypeRefTable type_ref_table; - readonly TypeDefTable type_def_table; - readonly FieldTable field_table; - readonly MethodTable method_table; - readonly ParamTable param_table; - readonly InterfaceImplTable iface_impl_table; - readonly MemberRefTable member_ref_table; - readonly ConstantTable constant_table; - readonly CustomAttributeTable custom_attribute_table; - readonly DeclSecurityTable declsec_table; - readonly StandAloneSigTable standalone_sig_table; - readonly EventMapTable event_map_table; - readonly EventTable event_table; - readonly PropertyMapTable property_map_table; - readonly PropertyTable property_table; - readonly TypeSpecTable typespec_table; - readonly MethodSpecTable method_spec_table; - - internal MetadataBuilder metadata_builder; - - readonly DocumentTable document_table; - readonly MethodDebugInformationTable method_debug_information_table; - readonly LocalScopeTable local_scope_table; - readonly LocalVariableTable local_variable_table; - readonly LocalConstantTable local_constant_table; - readonly ImportScopeTable import_scope_table; - readonly StateMachineMethodTable state_machine_method_table; - readonly CustomDebugInformationTable custom_debug_information_table; - - readonly Dictionary import_scope_map; - readonly Dictionary document_map; - - public MetadataBuilder (ModuleDefinition module, string fq_name, uint timestamp, ISymbolWriterProvider symbol_writer_provider) - { - this.module = module; - this.text_map = CreateTextMap (); - this.fq_name = fq_name; - this.timestamp = timestamp; - this.symbol_writer_provider = symbol_writer_provider; - - this.code = new CodeWriter (this); - this.data = new DataBuffer (); - this.resources = new ResourceBuffer (); - this.string_heap = new StringHeapBuffer (); - this.guid_heap = new GuidHeapBuffer (); - this.user_string_heap = new UserStringHeapBuffer (); - this.blob_heap = new BlobHeapBuffer (); - this.table_heap = new TableHeapBuffer (module, this); - - this.type_ref_table = GetTable (Table.TypeRef); - this.type_def_table = GetTable (Table.TypeDef); - this.field_table = GetTable (Table.Field); - this.method_table = GetTable (Table.Method); - this.param_table = GetTable (Table.Param); - this.iface_impl_table = GetTable (Table.InterfaceImpl); - this.member_ref_table = GetTable (Table.MemberRef); - this.constant_table = GetTable (Table.Constant); - this.custom_attribute_table = GetTable (Table.CustomAttribute); - this.declsec_table = GetTable (Table.DeclSecurity); - this.standalone_sig_table = GetTable (Table.StandAloneSig); - this.event_map_table = GetTable (Table.EventMap); - this.event_table = GetTable (Table.Event); - this.property_map_table = GetTable (Table.PropertyMap); - this.property_table = GetTable (Table.Property); - this.typespec_table = GetTable (Table.TypeSpec); - this.method_spec_table = GetTable (Table.MethodSpec); - - var row_equality_comparer = new RowEqualityComparer (); - type_ref_map = new Dictionary (row_equality_comparer); - type_spec_map = new Dictionary (); - member_ref_map = new Dictionary (row_equality_comparer); - method_spec_map = new Dictionary (row_equality_comparer); - generic_parameters = new Collection (); - - this.document_table = GetTable (Table.Document); - this.method_debug_information_table = GetTable (Table.MethodDebugInformation); - this.local_scope_table = GetTable (Table.LocalScope); - this.local_variable_table = GetTable (Table.LocalVariable); - this.local_constant_table = GetTable (Table.LocalConstant); - this.import_scope_table = GetTable (Table.ImportScope); - this.state_machine_method_table = GetTable (Table.StateMachineMethod); - this.custom_debug_information_table = GetTable (Table.CustomDebugInformation); - - this.document_map = new Dictionary (StringComparer.Ordinal); - this.import_scope_map = new Dictionary (row_equality_comparer); - } - - public MetadataBuilder (ModuleDefinition module, PortablePdbWriterProvider writer_provider) - { - this.module = module; - this.text_map = new TextMap (); - this.symbol_writer_provider = writer_provider; - - this.string_heap = new StringHeapBuffer (); - this.guid_heap = new GuidHeapBuffer (); - this.user_string_heap = new UserStringHeapBuffer (); - this.blob_heap = new BlobHeapBuffer (); - this.table_heap = new TableHeapBuffer (module, this); - this.pdb_heap = new PdbHeapBuffer (); - - this.document_table = GetTable (Table.Document); - this.method_debug_information_table = GetTable (Table.MethodDebugInformation); - this.local_scope_table = GetTable (Table.LocalScope); - this.local_variable_table = GetTable (Table.LocalVariable); - this.local_constant_table = GetTable (Table.LocalConstant); - this.import_scope_table = GetTable (Table.ImportScope); - this.state_machine_method_table = GetTable (Table.StateMachineMethod); - this.custom_debug_information_table = GetTable (Table.CustomDebugInformation); - - var row_equality_comparer = new RowEqualityComparer (); - - this.document_map = new Dictionary (); - this.import_scope_map = new Dictionary (row_equality_comparer); - } - - public void SetSymbolWriter (ISymbolWriter writer) - { - symbol_writer = writer; - - if (symbol_writer == null && module.HasImage && module.Image.HasDebugTables ()) - symbol_writer = new PortablePdbWriter (this, module); - } - - TextMap CreateTextMap () - { - var map = new TextMap (); - map.AddMap (TextSegment.ImportAddressTable, module.Architecture == TargetArchitecture.I386 ? 8 : 0); - map.AddMap (TextSegment.CLIHeader, 0x48, 8); - return map; - } - - TTable GetTable (Table table) where TTable : MetadataTable, new() - { - return table_heap.GetTable (table); - } - - uint GetStringIndex (string @string) - { - if (string.IsNullOrEmpty (@string)) - return 0; - - return string_heap.GetStringIndex (@string); - } - - uint GetGuidIndex (Guid guid) - { - return guid_heap.GetGuidIndex (guid); - } - - uint GetBlobIndex (ByteBuffer blob) - { - if (blob.length == 0) - return 0; - - return blob_heap.GetBlobIndex (blob); - } - - uint GetBlobIndex (byte [] blob) - { - if (blob.IsNullOrEmpty ()) - return 0; - - return GetBlobIndex (new ByteBuffer (blob)); - } - - public void BuildMetadata () - { - BuildModule (); - - table_heap.string_offsets = string_heap.WriteStrings (); - table_heap.ComputeTableInformations (); - table_heap.WriteTableHeap (); - } - - void BuildModule () - { - var table = GetTable (Table.Module); - table.row.Col1 = GetStringIndex (module.Name); - table.row.Col2 = GetGuidIndex (module.Mvid); - - var assembly = module.Assembly; - - if (module.kind != ModuleKind.NetModule && assembly != null) - BuildAssembly (); - - if (module.HasAssemblyReferences) - AddAssemblyReferences (); - - if (module.HasModuleReferences) - AddModuleReferences (); - - if (module.HasResources) - AddResources (); - - if (module.HasExportedTypes) - AddExportedTypes (); - - BuildTypes (); - - if (module.kind != ModuleKind.NetModule && assembly != null) { - if (assembly.HasCustomAttributes) - AddCustomAttributes (assembly); - - if (assembly.HasSecurityDeclarations) - AddSecurityDeclarations (assembly); - } - - if (module.HasCustomAttributes) - AddCustomAttributes (module); - - if (module.EntryPoint != null) - entry_point = LookupToken (module.EntryPoint); - } - - void BuildAssembly () - { - var assembly = module.Assembly; - var name = assembly.Name; - - var table = GetTable (Table.Assembly); - - table.row = new AssemblyRow ( - name.HashAlgorithm, - (ushort)name.Version.Major, - (ushort)name.Version.Minor, - (ushort)name.Version.Build, - (ushort)name.Version.Revision, - name.Attributes, - GetBlobIndex (name.PublicKey), - GetStringIndex (name.Name), - GetStringIndex (name.Culture)); - - if (assembly.Modules.Count > 1) - BuildModules (); - } - - void BuildModules () - { - var modules = this.module.Assembly.Modules; - var table = GetTable (Table.File); - - for (int i = 0; i < modules.Count; i++) { - var module = modules [i]; - if (module.IsMain) - continue; - -#if NET_CORE - throw new NotSupportedException (); -#else - var parameters = new WriterParameters { - SymbolWriterProvider = symbol_writer_provider, - }; - - var file_name = GetModuleFileName (module.Name); - module.Write (file_name, parameters); - - var hash = CryptoService.ComputeHash (file_name); - - table.AddRow (new FileRow ( - FileAttributes.ContainsMetaData, - GetStringIndex (module.Name), - GetBlobIndex (hash))); -#endif - } - } - -#if !NET_CORE - string GetModuleFileName (string name) - { - if (string.IsNullOrEmpty (name)) - throw new NotSupportedException (); - - var path = Path.GetDirectoryName (fq_name); - return Path.Combine (path, name); - } -#endif - - void AddAssemblyReferences () - { - var references = module.AssemblyReferences; - var table = GetTable (Table.AssemblyRef); - - if (module.IsWindowsMetadata ()) - module.Projections.RemoveVirtualReferences (references); - - for (int i = 0; i < references.Count; i++) { - var reference = references [i]; - - var key_or_token = reference.PublicKey.IsNullOrEmpty () - ? reference.PublicKeyToken - : reference.PublicKey; - - var version = reference.Version; - - var rid = table.AddRow (new AssemblyRefRow ( - (ushort)version.Major, - (ushort)version.Minor, - (ushort)version.Build, - (ushort)version.Revision, - reference.Attributes, - GetBlobIndex (key_or_token), - GetStringIndex (reference.Name), - GetStringIndex (reference.Culture), - GetBlobIndex (reference.Hash))); - - reference.token = new MetadataToken (TokenType.AssemblyRef, rid); - } - - if (module.IsWindowsMetadata ()) - module.Projections.AddVirtualReferences (references); - } - - void AddModuleReferences () - { - var references = module.ModuleReferences; - var table = GetTable (Table.ModuleRef); - - for (int i = 0; i < references.Count; i++) { - var reference = references [i]; - - reference.token = new MetadataToken ( - TokenType.ModuleRef, - table.AddRow (GetStringIndex (reference.Name))); - } - } - - void AddResources () - { - var resources = module.Resources; - var table = GetTable (Table.ManifestResource); - - for (int i = 0; i < resources.Count; i++) { - var resource = resources [i]; - - var row = new ManifestResourceRow ( - 0, - resource.Attributes, - GetStringIndex (resource.Name), - 0); - - switch (resource.ResourceType) { - case ResourceType.Embedded: - row.Col1 = AddEmbeddedResource ((EmbeddedResource)resource); - break; - case ResourceType.Linked: - row.Col4 = CodedIndex.Implementation.CompressMetadataToken ( - new MetadataToken ( - TokenType.File, - AddLinkedResource ((LinkedResource)resource))); - break; - case ResourceType.AssemblyLinked: - row.Col4 = CodedIndex.Implementation.CompressMetadataToken ( - ((AssemblyLinkedResource)resource).Assembly.MetadataToken); - break; - default: - throw new NotSupportedException (); - } - - table.AddRow (row); - } - } - - uint AddLinkedResource (LinkedResource resource) - { - var table = GetTable (Table.File); - var hash = resource.Hash; - - if (hash.IsNullOrEmpty ()) - hash = CryptoService.ComputeHash (resource.File); - - return (uint)table.AddRow (new FileRow ( - FileAttributes.ContainsNoMetaData, - GetStringIndex (resource.File), - GetBlobIndex (hash))); - } - - uint AddEmbeddedResource (EmbeddedResource resource) - { - return resources.AddResource (resource.GetResourceData ()); - } - - void AddExportedTypes () - { - var exported_types = module.ExportedTypes; - var table = GetTable (Table.ExportedType); - - for (int i = 0; i < exported_types.Count; i++) { - var exported_type = exported_types [i]; - - var rid = table.AddRow (new ExportedTypeRow ( - exported_type.Attributes, - (uint)exported_type.Identifier, - GetStringIndex (exported_type.Name), - GetStringIndex (exported_type.Namespace), - MakeCodedRID (GetExportedTypeScope (exported_type), CodedIndex.Implementation))); - - exported_type.token = new MetadataToken (TokenType.ExportedType, rid); - } - } - - MetadataToken GetExportedTypeScope (ExportedType exported_type) - { - if (exported_type.DeclaringType != null) - return exported_type.DeclaringType.MetadataToken; - - var scope = exported_type.Scope; - switch (scope.MetadataToken.TokenType) { - case TokenType.AssemblyRef: - return scope.MetadataToken; - case TokenType.ModuleRef: - var file_table = GetTable (Table.File); - for (int i = 0; i < file_table.length; i++) - if (file_table.rows [i].Col2 == GetStringIndex (scope.Name)) - return new MetadataToken (TokenType.File, i + 1); - - break; - } - - throw new NotSupportedException (); - } - - void BuildTypes () - { - if (!module.HasTypes) - return; - - AttachTokens (); - AddTypes (); - AddGenericParameters (); - } - - void AttachTokens () - { - var types = module.Types; - - for (int i = 0; i < types.Count; i++) - AttachTypeToken (types [i]); - } - - void AttachTypeToken (TypeDefinition type) - { - var treatment = WindowsRuntimeProjections.RemoveProjection (type); - - type.token = new MetadataToken (TokenType.TypeDef, type_rid++); - type.fields_range.Start = field_rid; - type.methods_range.Start = method_rid; - - if (type.HasFields) - AttachFieldsToken (type); - - if (type.HasMethods) - AttachMethodsToken (type); - - if (type.HasNestedTypes) - AttachNestedTypesToken (type); - - WindowsRuntimeProjections.ApplyProjection (type, treatment); - } - - void AttachNestedTypesToken (TypeDefinition type) - { - var nested_types = type.NestedTypes; - for (int i = 0; i < nested_types.Count; i++) - AttachTypeToken (nested_types [i]); - } - - void AttachFieldsToken (TypeDefinition type) - { - var fields = type.Fields; - type.fields_range.Length = (uint)fields.Count; - for (int i = 0; i < fields.Count; i++) - fields [i].token = new MetadataToken (TokenType.Field, field_rid++); - } - - void AttachMethodsToken (TypeDefinition type) - { - var methods = type.Methods; - type.methods_range.Length = (uint)methods.Count; - for (int i = 0; i < methods.Count; i++) - methods [i].token = new MetadataToken (TokenType.Method, method_rid++); - } - - MetadataToken GetTypeToken (TypeReference type) - { - if (type == null) - return MetadataToken.Zero; - - if (type.IsDefinition) - return type.token; - - if (type.IsTypeSpecification ()) - return GetTypeSpecToken (type); - - return GetTypeRefToken (type); - } - - MetadataToken GetTypeSpecToken (TypeReference type) - { - var row = GetBlobIndex (GetTypeSpecSignature (type)); - - MetadataToken token; - if (type_spec_map.TryGetValue (row, out token)) - return token; - - return AddTypeSpecification (type, row); - } - - MetadataToken AddTypeSpecification (TypeReference type, uint row) - { - type.token = new MetadataToken (TokenType.TypeSpec, typespec_table.AddRow (row)); - - var token = type.token; - type_spec_map.Add (row, token); - return token; - } - - MetadataToken GetTypeRefToken (TypeReference type) - { - var projection = WindowsRuntimeProjections.RemoveProjection (type); - - var row = CreateTypeRefRow (type); - - MetadataToken token; - if (!type_ref_map.TryGetValue (row, out token)) - token = AddTypeReference (type, row); - - WindowsRuntimeProjections.ApplyProjection (type, projection); - - return token; - } - - TypeRefRow CreateTypeRefRow (TypeReference type) - { - var scope_token = GetScopeToken (type); - - return new TypeRefRow ( - MakeCodedRID (scope_token, CodedIndex.ResolutionScope), - GetStringIndex (type.Name), - GetStringIndex (type.Namespace)); - } - - MetadataToken GetScopeToken (TypeReference type) - { - if (type.IsNested) - return GetTypeRefToken (type.DeclaringType); - - var scope = type.Scope; - - if (scope == null) - return MetadataToken.Zero; - - return scope.MetadataToken; - } - - static CodedRID MakeCodedRID (IMetadataTokenProvider provider, CodedIndex index) - { - return MakeCodedRID (provider.MetadataToken, index); - } - - static CodedRID MakeCodedRID (MetadataToken token, CodedIndex index) - { - return index.CompressMetadataToken (token); - } - - MetadataToken AddTypeReference (TypeReference type, TypeRefRow row) - { - type.token = new MetadataToken (TokenType.TypeRef, type_ref_table.AddRow (row)); - - var token = type.token; - type_ref_map.Add (row, token); - return token; - } - - void AddTypes () - { - var types = module.Types; - - for (int i = 0; i < types.Count; i++) - AddType (types [i]); - } - - void AddType (TypeDefinition type) - { - var treatment = WindowsRuntimeProjections.RemoveProjection (type); - - type_def_table.AddRow (new TypeDefRow ( - type.Attributes, - GetStringIndex (type.Name), - GetStringIndex (type.Namespace), - MakeCodedRID (GetTypeToken (type.BaseType), CodedIndex.TypeDefOrRef), - type.fields_range.Start, - type.methods_range.Start)); - - if (type.HasGenericParameters) - AddGenericParameters (type); - - if (type.HasInterfaces) - AddInterfaces (type); - - if (type.HasLayoutInfo) - AddLayoutInfo (type); - - if (type.HasFields) - AddFields (type); - - if (type.HasMethods) - AddMethods (type); - - if (type.HasProperties) - AddProperties (type); - - if (type.HasEvents) - AddEvents (type); - - if (type.HasCustomAttributes) - AddCustomAttributes (type); - - if (type.HasSecurityDeclarations) - AddSecurityDeclarations (type); - - if (type.HasNestedTypes) - AddNestedTypes (type); - - WindowsRuntimeProjections.ApplyProjection (type, treatment); - } - - void AddGenericParameters (IGenericParameterProvider owner) - { - var parameters = owner.GenericParameters; - - for (int i = 0; i < parameters.Count; i++) - generic_parameters.Add (parameters [i]); - } - - sealed class GenericParameterComparer : IComparer { - - public int Compare (GenericParameter a, GenericParameter b) - { - var a_owner = MakeCodedRID (a.Owner, CodedIndex.TypeOrMethodDef); - var b_owner = MakeCodedRID (b.Owner, CodedIndex.TypeOrMethodDef); - if (a_owner == b_owner) { - var a_pos = a.Position; - var b_pos = b.Position; - return a_pos == b_pos ? 0 : a_pos > b_pos ? 1 : -1; - } - - return a_owner > b_owner ? 1 : -1; - } - } - - void AddGenericParameters () - { - var items = this.generic_parameters.items; - var size = this.generic_parameters.size; - Array.Sort (items, 0, size, new GenericParameterComparer ()); - - var generic_param_table = GetTable (Table.GenericParam); - var generic_param_constraint_table = GetTable (Table.GenericParamConstraint); - - for (int i = 0; i < size; i++) { - var generic_parameter = items [i]; - - var rid = generic_param_table.AddRow (new GenericParamRow ( - (ushort)generic_parameter.Position, - generic_parameter.Attributes, - MakeCodedRID (generic_parameter.Owner, CodedIndex.TypeOrMethodDef), - GetStringIndex (generic_parameter.Name))); - - generic_parameter.token = new MetadataToken (TokenType.GenericParam, rid); - - if (generic_parameter.HasConstraints) - AddConstraints (generic_parameter, generic_param_constraint_table); - - if (generic_parameter.HasCustomAttributes) - AddCustomAttributes (generic_parameter); - } - } - - void AddConstraints (GenericParameter generic_parameter, GenericParamConstraintTable table) - { - var constraints = generic_parameter.Constraints; - - var gp_rid = generic_parameter.token.RID; - - for (int i = 0; i < constraints.Count; i++) { - var constraint = constraints [i]; - - var rid = table.AddRow (new GenericParamConstraintRow ( - gp_rid, - MakeCodedRID (GetTypeToken (constraint.ConstraintType), CodedIndex.TypeDefOrRef))); - - constraint.token = new MetadataToken (TokenType.GenericParamConstraint, rid); - - if (constraint.HasCustomAttributes) - AddCustomAttributes (constraint); - } - } - - void AddInterfaces (TypeDefinition type) - { - var interfaces = type.Interfaces; - var type_rid = type.token.RID; - - for (int i = 0; i < interfaces.Count; i++) { - var iface_impl = interfaces [i]; - - var rid = iface_impl_table.AddRow (new InterfaceImplRow ( - type_rid, - MakeCodedRID (GetTypeToken (iface_impl.InterfaceType), CodedIndex.TypeDefOrRef))); - - iface_impl.token = new MetadataToken (TokenType.InterfaceImpl, rid); - - if (iface_impl.HasCustomAttributes) - AddCustomAttributes (iface_impl); - } - } - - void AddLayoutInfo (TypeDefinition type) - { - var table = GetTable (Table.ClassLayout); - - table.AddRow (new ClassLayoutRow ( - (ushort)type.PackingSize, - (uint)type.ClassSize, - type.token.RID)); - } - - void AddNestedTypes (TypeDefinition type) - { - var nested_types = type.NestedTypes; - var nested_table = GetTable (Table.NestedClass); - - for (int i = 0; i < nested_types.Count; i++) { - var nested = nested_types [i]; - AddType (nested); - nested_table.AddRow (new NestedClassRow (nested.token.RID, type.token.RID)); - } - } - - void AddFields (TypeDefinition type) - { - var fields = type.Fields; - - for (int i = 0; i < fields.Count; i++) - AddField (fields [i]); - } - - void AddField (FieldDefinition field) - { - var projection = WindowsRuntimeProjections.RemoveProjection (field); - - field_table.AddRow (new FieldRow ( - field.Attributes, - GetStringIndex (field.Name), - GetBlobIndex (GetFieldSignature (field)))); - - if (!field.InitialValue.IsNullOrEmpty ()) - AddFieldRVA (field); - - if (field.HasLayoutInfo) - AddFieldLayout (field); - - if (field.HasCustomAttributes) - AddCustomAttributes (field); - - if (field.HasConstant) - AddConstant (field, field.FieldType); - - if (field.HasMarshalInfo) - AddMarshalInfo (field); - - WindowsRuntimeProjections.ApplyProjection (field, projection); - } - - void AddFieldRVA (FieldDefinition field) - { - var table = GetTable (Table.FieldRVA); - table.AddRow (new FieldRVARow ( - data.AddData (field.InitialValue), - field.token.RID)); - } - - void AddFieldLayout (FieldDefinition field) - { - var table = GetTable (Table.FieldLayout); - table.AddRow (new FieldLayoutRow ((uint)field.Offset, field.token.RID)); - } - - void AddMethods (TypeDefinition type) - { - var methods = type.Methods; - - for (int i = 0; i < methods.Count; i++) - AddMethod (methods [i]); - } - - void AddMethod (MethodDefinition method) - { - var projection = WindowsRuntimeProjections.RemoveProjection (method); - - method_table.AddRow (new MethodRow ( - method.HasBody ? code.WriteMethodBody (method) : 0, - method.ImplAttributes, - method.Attributes, - GetStringIndex (method.Name), - GetBlobIndex (GetMethodSignature (method)), - param_rid)); - - AddParameters (method); - - if (method.HasGenericParameters) - AddGenericParameters (method); - - if (method.IsPInvokeImpl) - AddPInvokeInfo (method); - - if (method.HasCustomAttributes) - AddCustomAttributes (method); - - if (method.HasSecurityDeclarations) - AddSecurityDeclarations (method); - - if (method.HasOverrides) - AddOverrides (method); - - WindowsRuntimeProjections.ApplyProjection (method, projection); - } - - void AddParameters (MethodDefinition method) - { - var return_parameter = method.MethodReturnType.parameter; - - if (return_parameter != null && RequiresParameterRow (return_parameter)) - AddParameter (0, return_parameter, param_table); - - if (!method.HasParameters) - return; - - var parameters = method.Parameters; - - for (int i = 0; i < parameters.Count; i++) { - var parameter = parameters [i]; - if (!RequiresParameterRow (parameter)) - continue; - - AddParameter ((ushort)(i + 1), parameter, param_table); - } - } - - void AddPInvokeInfo (MethodDefinition method) - { - var pinvoke = method.PInvokeInfo; - if (pinvoke == null) - return; - - var table = GetTable (Table.ImplMap); - table.AddRow (new ImplMapRow ( - pinvoke.Attributes, - MakeCodedRID (method, CodedIndex.MemberForwarded), - GetStringIndex (pinvoke.EntryPoint), - pinvoke.Module.MetadataToken.RID)); - } - - void AddOverrides (MethodDefinition method) - { - var overrides = method.Overrides; - var table = GetTable (Table.MethodImpl); - - for (int i = 0; i < overrides.Count; i++) { - table.AddRow (new MethodImplRow ( - method.DeclaringType.token.RID, - MakeCodedRID (method, CodedIndex.MethodDefOrRef), - MakeCodedRID (LookupToken (overrides [i]), CodedIndex.MethodDefOrRef))); - } - } - - static bool RequiresParameterRow (ParameterDefinition parameter) - { - return !string.IsNullOrEmpty (parameter.Name) - || parameter.Attributes != ParameterAttributes.None - || parameter.HasMarshalInfo - || parameter.HasConstant - || parameter.HasCustomAttributes; - } - - void AddParameter (ushort sequence, ParameterDefinition parameter, ParamTable table) - { - table.AddRow (new ParamRow ( - parameter.Attributes, - sequence, - GetStringIndex (parameter.Name))); - - parameter.token = new MetadataToken (TokenType.Param, param_rid++); - - if (parameter.HasCustomAttributes) - AddCustomAttributes (parameter); - - if (parameter.HasConstant) - AddConstant (parameter, parameter.ParameterType); - - if (parameter.HasMarshalInfo) - AddMarshalInfo (parameter); - } - - void AddMarshalInfo (IMarshalInfoProvider owner) - { - var table = GetTable (Table.FieldMarshal); - - table.AddRow (new FieldMarshalRow ( - MakeCodedRID (owner, CodedIndex.HasFieldMarshal), - GetBlobIndex (GetMarshalInfoSignature (owner)))); - } - - void AddProperties (TypeDefinition type) - { - var properties = type.Properties; - - property_map_table.AddRow (new PropertyMapRow (type.token.RID, property_rid)); - - for (int i = 0; i < properties.Count; i++) - AddProperty (properties [i]); - } - - void AddProperty (PropertyDefinition property) - { - property_table.AddRow (new PropertyRow ( - property.Attributes, - GetStringIndex (property.Name), - GetBlobIndex (GetPropertySignature (property)))); - property.token = new MetadataToken (TokenType.Property, property_rid++); - - var method = property.GetMethod; - if (method != null) - AddSemantic (MethodSemanticsAttributes.Getter, property, method); - - method = property.SetMethod; - if (method != null) - AddSemantic (MethodSemanticsAttributes.Setter, property, method); - - if (property.HasOtherMethods) - AddOtherSemantic (property, property.OtherMethods); - - if (property.HasCustomAttributes) - AddCustomAttributes (property); - - if (property.HasConstant) - AddConstant (property, property.PropertyType); - } - - void AddOtherSemantic (IMetadataTokenProvider owner, Collection others) - { - for (int i = 0; i < others.Count; i++) - AddSemantic (MethodSemanticsAttributes.Other, owner, others [i]); - } - - void AddEvents (TypeDefinition type) - { - var events = type.Events; - - event_map_table.AddRow (new EventMapRow (type.token.RID, event_rid)); - - for (int i = 0; i < events.Count; i++) - AddEvent (events [i]); - } - - void AddEvent (EventDefinition @event) - { - event_table.AddRow (new EventRow ( - @event.Attributes, - GetStringIndex (@event.Name), - MakeCodedRID (GetTypeToken (@event.EventType), CodedIndex.TypeDefOrRef))); - @event.token = new MetadataToken (TokenType.Event, event_rid++); - - var method = @event.AddMethod; - if (method != null) - AddSemantic (MethodSemanticsAttributes.AddOn, @event, method); - - method = @event.InvokeMethod; - if (method != null) - AddSemantic (MethodSemanticsAttributes.Fire, @event, method); - - method = @event.RemoveMethod; - if (method != null) - AddSemantic (MethodSemanticsAttributes.RemoveOn, @event, method); - - if (@event.HasOtherMethods) - AddOtherSemantic (@event, @event.OtherMethods); - - if (@event.HasCustomAttributes) - AddCustomAttributes (@event); - } - - void AddSemantic (MethodSemanticsAttributes semantics, IMetadataTokenProvider provider, MethodDefinition method) - { - method.SemanticsAttributes = semantics; - var table = GetTable (Table.MethodSemantics); - - table.AddRow (new MethodSemanticsRow ( - semantics, - method.token.RID, - MakeCodedRID (provider, CodedIndex.HasSemantics))); - } - - void AddConstant (IConstantProvider owner, TypeReference type) - { - var constant = owner.Constant; - var etype = GetConstantType (type, constant); - - constant_table.AddRow (new ConstantRow ( - etype, - MakeCodedRID (owner.MetadataToken, CodedIndex.HasConstant), - GetBlobIndex (GetConstantSignature (etype, constant)))); - } - - static ElementType GetConstantType (TypeReference constant_type, object constant) - { - if (constant == null) - return ElementType.Class; - - var etype = constant_type.etype; - switch (etype) { - case ElementType.None: - var type = constant_type.CheckedResolve (); - if (type.IsEnum) - return GetConstantType (type.GetEnumUnderlyingType (), constant); - - return ElementType.Class; - case ElementType.String: - return ElementType.String; - case ElementType.Object: - return GetConstantType (constant.GetType ()); - case ElementType.Array: - case ElementType.SzArray: - case ElementType.MVar: - case ElementType.Var: - return ElementType.Class; - case ElementType.GenericInst: - var generic_instance = (GenericInstanceType)constant_type; - if (generic_instance.ElementType.IsTypeOf ("System", "Nullable`1")) - return GetConstantType (generic_instance.GenericArguments [0], constant); - - return GetConstantType (((TypeSpecification)constant_type).ElementType, constant); - case ElementType.CModOpt: - case ElementType.CModReqD: - case ElementType.ByRef: - case ElementType.Sentinel: - return GetConstantType (((TypeSpecification)constant_type).ElementType, constant); - case ElementType.Boolean: - case ElementType.Char: - case ElementType.I: - case ElementType.I1: - case ElementType.I2: - case ElementType.I4: - case ElementType.I8: - case ElementType.U: - case ElementType.U1: - case ElementType.U2: - case ElementType.U4: - case ElementType.U8: - case ElementType.R4: - case ElementType.R8: - return GetConstantType (constant.GetType ()); - default: - return etype; - } - } - - static ElementType GetConstantType (Type type) - { - switch (Type.GetTypeCode (type)) { - case TypeCode.Boolean: - return ElementType.Boolean; - case TypeCode.Byte: - return ElementType.U1; - case TypeCode.SByte: - return ElementType.I1; - case TypeCode.Char: - return ElementType.Char; - case TypeCode.Int16: - return ElementType.I2; - case TypeCode.UInt16: - return ElementType.U2; - case TypeCode.Int32: - return ElementType.I4; - case TypeCode.UInt32: - return ElementType.U4; - case TypeCode.Int64: - return ElementType.I8; - case TypeCode.UInt64: - return ElementType.U8; - case TypeCode.Single: - return ElementType.R4; - case TypeCode.Double: - return ElementType.R8; - case TypeCode.String: - return ElementType.String; - default: - throw new NotSupportedException (type.FullName); - } - } - - void AddCustomAttributes (ICustomAttributeProvider owner) - { - var custom_attributes = owner.CustomAttributes; - - for (int i = 0; i < custom_attributes.Count; i++) { - var attribute = custom_attributes [i]; - - var projection = WindowsRuntimeProjections.RemoveProjection (attribute); - - custom_attribute_table.AddRow (new CustomAttributeRow ( - MakeCodedRID (owner, CodedIndex.HasCustomAttribute), - MakeCodedRID (LookupToken (attribute.Constructor), CodedIndex.CustomAttributeType), - GetBlobIndex (GetCustomAttributeSignature (attribute)))); - - WindowsRuntimeProjections.ApplyProjection (attribute, projection); - } - } - - void AddSecurityDeclarations (ISecurityDeclarationProvider owner) - { - var declarations = owner.SecurityDeclarations; - - for (int i = 0; i < declarations.Count; i++) { - var declaration = declarations [i]; - - declsec_table.AddRow (new DeclSecurityRow ( - declaration.Action, - MakeCodedRID (owner, CodedIndex.HasDeclSecurity), - GetBlobIndex (GetSecurityDeclarationSignature (declaration)))); - } - } - - MetadataToken GetMemberRefToken (MemberReference member) - { - var row = CreateMemberRefRow (member); - - MetadataToken token; - if (!member_ref_map.TryGetValue (row, out token)) - token = AddMemberReference (member, row); - - return token; - } - - MemberRefRow CreateMemberRefRow (MemberReference member) - { - return new MemberRefRow ( - MakeCodedRID (GetTypeToken (member.DeclaringType), CodedIndex.MemberRefParent), - GetStringIndex (member.Name), - GetBlobIndex (GetMemberRefSignature (member))); - } - - MetadataToken AddMemberReference (MemberReference member, MemberRefRow row) - { - member.token = new MetadataToken (TokenType.MemberRef, member_ref_table.AddRow (row)); - - var token = member.token; - member_ref_map.Add (row, token); - return token; - } - - MetadataToken GetMethodSpecToken (MethodSpecification method_spec) - { - var row = CreateMethodSpecRow (method_spec); - - MetadataToken token; - if (method_spec_map.TryGetValue (row, out token)) - return token; - - AddMethodSpecification (method_spec, row); - - return method_spec.token; - } - - void AddMethodSpecification (MethodSpecification method_spec, MethodSpecRow row) - { - method_spec.token = new MetadataToken (TokenType.MethodSpec, method_spec_table.AddRow (row)); - method_spec_map.Add (row, method_spec.token); - } - - MethodSpecRow CreateMethodSpecRow (MethodSpecification method_spec) - { - return new MethodSpecRow ( - MakeCodedRID (LookupToken (method_spec.ElementMethod), CodedIndex.MethodDefOrRef), - GetBlobIndex (GetMethodSpecSignature (method_spec))); - } - - SignatureWriter CreateSignatureWriter () - { - return new SignatureWriter (this); - } - - SignatureWriter GetMethodSpecSignature (MethodSpecification method_spec) - { - if (!method_spec.IsGenericInstance) - throw new NotSupportedException (); - - var generic_instance = (GenericInstanceMethod)method_spec; - - var signature = CreateSignatureWriter (); - signature.WriteByte (0x0a); - - signature.WriteGenericInstanceSignature (generic_instance); - - return signature; - } - - public uint AddStandAloneSignature (uint signature) - { - return (uint)standalone_sig_table.AddRow (signature); - } - - public uint GetLocalVariableBlobIndex (Collection variables) - { - return GetBlobIndex (GetVariablesSignature (variables)); - } - - public uint GetCallSiteBlobIndex (CallSite call_site) - { - return GetBlobIndex (GetMethodSignature (call_site)); - } - - public uint GetConstantTypeBlobIndex (TypeReference constant_type) - { - return GetBlobIndex (GetConstantTypeSignature (constant_type)); - } - - SignatureWriter GetVariablesSignature (Collection variables) - { - var signature = CreateSignatureWriter (); - signature.WriteByte (0x7); - signature.WriteCompressedUInt32 ((uint)variables.Count); - for (int i = 0; i < variables.Count; i++) - signature.WriteTypeSignature (variables [i].VariableType); - return signature; - } - - SignatureWriter GetConstantTypeSignature (TypeReference constant_type) - { - var signature = CreateSignatureWriter (); - signature.WriteByte (0x6); - signature.WriteTypeSignature (constant_type); - return signature; - } - - SignatureWriter GetFieldSignature (FieldReference field) - { - var signature = CreateSignatureWriter (); - signature.WriteByte (0x6); - signature.WriteTypeSignature (field.FieldType); - return signature; - } - - SignatureWriter GetMethodSignature (IMethodSignature method) - { - var signature = CreateSignatureWriter (); - signature.WriteMethodSignature (method); - return signature; - } - - SignatureWriter GetMemberRefSignature (MemberReference member) - { - var field = member as FieldReference; - if (field != null) - return GetFieldSignature (field); - - var method = member as MethodReference; - if (method != null) - return GetMethodSignature (method); - - throw new NotSupportedException (); - } - - SignatureWriter GetPropertySignature (PropertyDefinition property) - { - var signature = CreateSignatureWriter (); - byte calling_convention = 0x8; - if (property.HasThis) - calling_convention |= 0x20; - - uint param_count = 0; - Collection parameters = null; - - if (property.HasParameters) { - parameters = property.Parameters; - param_count = (uint)parameters.Count; - } - - signature.WriteByte (calling_convention); - signature.WriteCompressedUInt32 (param_count); - signature.WriteTypeSignature (property.PropertyType); - - if (param_count == 0) - return signature; - - for (int i = 0; i < param_count; i++) - signature.WriteTypeSignature (parameters [i].ParameterType); - - return signature; - } - - SignatureWriter GetTypeSpecSignature (TypeReference type) - { - var signature = CreateSignatureWriter (); - signature.WriteTypeSignature (type); - return signature; - } - - SignatureWriter GetConstantSignature (ElementType type, object value) - { - var signature = CreateSignatureWriter (); - - switch (type) { - case ElementType.Array: - case ElementType.SzArray: - case ElementType.Class: - case ElementType.Object: - case ElementType.None: - case ElementType.Var: - case ElementType.MVar: - signature.WriteInt32 (0); - break; - case ElementType.String: - signature.WriteConstantString ((string)value); - break; - default: - signature.WriteConstantPrimitive (value); - break; - } - - return signature; - } - - SignatureWriter GetCustomAttributeSignature (CustomAttribute attribute) - { - var signature = CreateSignatureWriter (); - if (!attribute.resolved) { - signature.WriteBytes (attribute.GetBlob ()); - return signature; - } - - signature.WriteUInt16 (0x0001); - - signature.WriteCustomAttributeConstructorArguments (attribute); - - signature.WriteCustomAttributeNamedArguments (attribute); - - return signature; - } - - SignatureWriter GetSecurityDeclarationSignature (SecurityDeclaration declaration) - { - var signature = CreateSignatureWriter (); - - if (!declaration.resolved) - signature.WriteBytes (declaration.GetBlob ()); - else if (module.Runtime < TargetRuntime.Net_2_0) - signature.WriteXmlSecurityDeclaration (declaration); - else - signature.WriteSecurityDeclaration (declaration); - - return signature; - } - - SignatureWriter GetMarshalInfoSignature (IMarshalInfoProvider owner) - { - var signature = CreateSignatureWriter (); - - signature.WriteMarshalInfo (owner.MarshalInfo); - - return signature; - } - - static Exception CreateForeignMemberException (MemberReference member) - { - return new ArgumentException (string.Format ("Member '{0}' is declared in another module and needs to be imported", member)); - } - - public MetadataToken LookupToken (IMetadataTokenProvider provider) - { - if (provider == null) - throw new ArgumentNullException (); - - if (metadata_builder != null) - return metadata_builder.LookupToken (provider); - - var member = provider as MemberReference; - if (member == null || member.Module != module) - throw CreateForeignMemberException (member); - - var token = provider.MetadataToken; - - switch (token.TokenType) { - case TokenType.TypeDef: - case TokenType.Method: - case TokenType.Field: - case TokenType.Event: - case TokenType.Property: - return token; - case TokenType.TypeRef: - case TokenType.TypeSpec: - case TokenType.GenericParam: - return GetTypeToken ((TypeReference)provider); - case TokenType.MethodSpec: - return GetMethodSpecToken ((MethodSpecification)provider); - case TokenType.MemberRef: - return GetMemberRefToken (member); - default: - throw new NotSupportedException (); - } - } - - public void AddMethodDebugInformation (MethodDebugInformation method_info) - { - if (method_info.HasSequencePoints) - AddSequencePoints (method_info); - - if (method_info.Scope != null) - AddLocalScope (method_info, method_info.Scope); - - if (method_info.StateMachineKickOffMethod != null) - AddStateMachineMethod (method_info); - - AddCustomDebugInformations (method_info.Method); - } - - void AddStateMachineMethod (MethodDebugInformation method_info) - { - state_machine_method_table.AddRow (new StateMachineMethodRow (method_info.Method.MetadataToken.RID, method_info.StateMachineKickOffMethod.MetadataToken.RID)); - } - - void AddLocalScope (MethodDebugInformation method_info, ScopeDebugInformation scope) - { - var rid = local_scope_table.AddRow (new LocalScopeRow ( - method_info.Method.MetadataToken.RID, - scope.import != null ? AddImportScope (scope.import) : 0, - local_variable_rid, - local_constant_rid, - (uint)scope.Start.Offset, - (uint)((scope.End.IsEndOfMethod ? method_info.code_size : scope.End.Offset) - scope.Start.Offset))); - - scope.token = new MetadataToken (TokenType.LocalScope, rid); - - AddCustomDebugInformations (scope); - - if (scope.HasVariables) - AddLocalVariables (scope); - - if (scope.HasConstants) - AddLocalConstants (scope); - - for (int i = 0; i < scope.Scopes.Count; i++) - AddLocalScope (method_info, scope.Scopes [i]); - } - - void AddLocalVariables (ScopeDebugInformation scope) - { - for (int i = 0; i < scope.Variables.Count; i++) { - var variable = scope.Variables [i]; - local_variable_table.AddRow (new LocalVariableRow (variable.Attributes, (ushort)variable.Index, GetStringIndex (variable.Name))); - variable.token = new MetadataToken (TokenType.LocalVariable, local_variable_rid); - local_variable_rid++; - - AddCustomDebugInformations (variable); - } - } - - void AddLocalConstants (ScopeDebugInformation scope) - { - for (int i = 0; i < scope.Constants.Count; i++) { - var constant = scope.Constants [i]; - local_constant_table.AddRow (new LocalConstantRow (GetStringIndex (constant.Name), GetBlobIndex (GetConstantSignature (constant)))); - constant.token = new MetadataToken (TokenType.LocalConstant, local_constant_rid); - local_constant_rid++; - } - } - - SignatureWriter GetConstantSignature (ConstantDebugInformation constant) - { - var type = constant.ConstantType; - - var signature = CreateSignatureWriter (); - signature.WriteTypeSignature (type); - - if (type.IsTypeOf ("System", "Decimal")) { - var bits = decimal.GetBits ((decimal)constant.Value); - - var low = (uint)bits [0]; - var mid = (uint)bits [1]; - var high = (uint)bits [2]; - - var scale = (byte)(bits [3] >> 16); - var negative = (bits [3] & 0x80000000) != 0; - - signature.WriteByte ((byte)(scale | (negative ? 0x80 : 0x00))); - signature.WriteUInt32 (low); - signature.WriteUInt32 (mid); - signature.WriteUInt32 (high); - - return signature; - } - - if (type.IsTypeOf ("System", "DateTime")) { - var date = (DateTime)constant.Value; - signature.WriteInt64 (date.Ticks); - return signature; - } - - signature.WriteBytes (GetConstantSignature (type.etype, constant.Value)); - - return signature; - } - - public void AddCustomDebugInformations (ICustomDebugInformationProvider provider) - { - if (!provider.HasCustomDebugInformations) - return; - - var custom_infos = provider.CustomDebugInformations; - - for (int i = 0; i < custom_infos.Count; i++) { - var custom_info = custom_infos [i]; - switch (custom_info.Kind) { - case CustomDebugInformationKind.Binary: - var binary_info = (BinaryCustomDebugInformation)custom_info; - AddCustomDebugInformation (provider, binary_info, GetBlobIndex (binary_info.Data)); - break; - case CustomDebugInformationKind.AsyncMethodBody: - AddAsyncMethodBodyDebugInformation (provider, (AsyncMethodBodyDebugInformation)custom_info); - break; - case CustomDebugInformationKind.StateMachineScope: - AddStateMachineScopeDebugInformation (provider, (StateMachineScopeDebugInformation)custom_info); - break; - case CustomDebugInformationKind.EmbeddedSource: - AddEmbeddedSourceDebugInformation (provider, (EmbeddedSourceDebugInformation)custom_info); - break; - case CustomDebugInformationKind.SourceLink: - AddSourceLinkDebugInformation (provider, (SourceLinkDebugInformation)custom_info); - break; - default: - throw new NotImplementedException (); - } - } - } - - void AddStateMachineScopeDebugInformation (ICustomDebugInformationProvider provider, StateMachineScopeDebugInformation state_machine_scope) - { - var method_info = ((MethodDefinition)provider).DebugInformation; - - var signature = CreateSignatureWriter (); - - var scopes = state_machine_scope.Scopes; - - for (int i = 0; i < scopes.Count; i++) { - var scope = scopes [i]; - signature.WriteUInt32 ((uint)scope.Start.Offset); - - var end_offset = scope.End.IsEndOfMethod - ? method_info.code_size - : scope.End.Offset; - - signature.WriteUInt32 ((uint)(end_offset - scope.Start.Offset)); - } - - AddCustomDebugInformation (provider, state_machine_scope, signature); - } - - void AddAsyncMethodBodyDebugInformation (ICustomDebugInformationProvider provider, AsyncMethodBodyDebugInformation async_method) - { - var signature = CreateSignatureWriter (); - signature.WriteUInt32 ((uint)async_method.catch_handler.Offset + 1); - - if (!async_method.yields.IsNullOrEmpty ()) { - for (int i = 0; i < async_method.yields.Count; i++) { - signature.WriteUInt32 ((uint)async_method.yields [i].Offset); - signature.WriteUInt32 ((uint)async_method.resumes [i].Offset); - signature.WriteCompressedUInt32 (async_method.resume_methods [i].MetadataToken.RID); - } - } - - AddCustomDebugInformation (provider, async_method, signature); - } - - void AddEmbeddedSourceDebugInformation (ICustomDebugInformationProvider provider, EmbeddedSourceDebugInformation embedded_source) - { - var signature = CreateSignatureWriter (); - - if (!embedded_source.resolved) { - signature.WriteBytes (embedded_source.ReadRawEmbeddedSourceDebugInformation ()); - AddCustomDebugInformation (provider, embedded_source, signature); - return; - } - - var content = embedded_source.content ?? Empty.Array; - if (embedded_source.compress) { - signature.WriteInt32 (content.Length); - - var decompressed_stream = new MemoryStream (content); - var content_stream = new MemoryStream (); - - using (var compress_stream = new DeflateStream (content_stream, CompressionMode.Compress, leaveOpen: true)) - decompressed_stream.CopyTo (compress_stream); - - signature.WriteBytes (content_stream.ToArray ()); - } else { - signature.WriteInt32 (0); - signature.WriteBytes (content); - } - - AddCustomDebugInformation (provider, embedded_source, signature); - } - - void AddSourceLinkDebugInformation (ICustomDebugInformationProvider provider, SourceLinkDebugInformation source_link) - { - var signature = CreateSignatureWriter (); - signature.WriteBytes (Encoding.UTF8.GetBytes (source_link.content)); - - AddCustomDebugInformation (provider, source_link, signature); - } - - void AddCustomDebugInformation (ICustomDebugInformationProvider provider, CustomDebugInformation custom_info, SignatureWriter signature) - { - AddCustomDebugInformation (provider, custom_info, GetBlobIndex (signature)); - } - - void AddCustomDebugInformation (ICustomDebugInformationProvider provider, CustomDebugInformation custom_info, uint blob_index) - { - var rid = custom_debug_information_table.AddRow (new CustomDebugInformationRow ( - MakeCodedRID (provider.MetadataToken, CodedIndex.HasCustomDebugInformation), - GetGuidIndex (custom_info.Identifier), - blob_index)); - - custom_info.token = new MetadataToken (TokenType.CustomDebugInformation, rid); - } - - uint AddImportScope (ImportDebugInformation import) - { - uint parent = 0; - if (import.Parent != null) - parent = AddImportScope (import.Parent); - - uint targets_index = 0; - if (import.HasTargets) { - var signature = CreateSignatureWriter (); - - for (int i = 0; i < import.Targets.Count; i++) - AddImportTarget (import.Targets [i], signature); - - targets_index = GetBlobIndex (signature); - } - - var row = new ImportScopeRow (parent, targets_index); - - MetadataToken import_token; - if (import_scope_map.TryGetValue (row, out import_token)) - return import_token.RID; - - import_token = new MetadataToken (TokenType.ImportScope, import_scope_table.AddRow (row)); - import_scope_map.Add (row, import_token); - - return import_token.RID; - } - - void AddImportTarget (ImportTarget target, SignatureWriter signature) - { - signature.WriteCompressedUInt32 ((uint)target.kind); - - switch (target.kind) { - case ImportTargetKind.ImportNamespace: - signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace)); - break; - case ImportTargetKind.ImportNamespaceInAssembly: - signature.WriteCompressedUInt32 (target.reference.MetadataToken.RID); - signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace)); - break; - case ImportTargetKind.ImportType: - signature.WriteTypeToken (target.type); - break; - case ImportTargetKind.ImportXmlNamespaceWithAlias: - signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias)); - signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace)); - break; - case ImportTargetKind.ImportAlias: - signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias)); - break; - case ImportTargetKind.DefineAssemblyAlias: - signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias)); - signature.WriteCompressedUInt32 (target.reference.MetadataToken.RID); - break; - case ImportTargetKind.DefineNamespaceAlias: - signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias)); - signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace)); - break; - case ImportTargetKind.DefineNamespaceInAssemblyAlias: - signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias)); - signature.WriteCompressedUInt32 (target.reference.MetadataToken.RID); - signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace)); - break; - case ImportTargetKind.DefineTypeAlias: - signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias)); - signature.WriteTypeToken (target.type); - break; - } - } - - uint GetUTF8StringBlobIndex (string s) - { - return GetBlobIndex (Encoding.UTF8.GetBytes (s)); - } - - public MetadataToken GetDocumentToken (Document document) - { - MetadataToken token; - if (document_map.TryGetValue (document.Url, out token)) - return token; - - token = new MetadataToken (TokenType.Document, document_table.AddRow ( - new DocumentRow (GetBlobIndex (GetDocumentNameSignature (document)), - GetGuidIndex (document.HashAlgorithm.ToGuid ()), - GetBlobIndex (document.Hash), - GetGuidIndex (document.Language.ToGuid ())))); - - document.token = token; - - AddCustomDebugInformations (document); - - document_map.Add (document.Url, token); - - return token; - } - - SignatureWriter GetDocumentNameSignature (Document document) - { - var name = document.Url; - var signature = CreateSignatureWriter (); - - char separator; - if (!TryGetDocumentNameSeparator (name, out separator)) { - signature.WriteByte (0); - signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (name)); - return signature; - } - - signature.WriteByte ((byte)separator); - var parts = name.Split (new [] { separator }); - for (int i = 0; i < parts.Length; i++) { - if (parts [i] == String.Empty) - signature.WriteCompressedUInt32 (0); - else - signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (parts [i])); - } - - return signature; - } - - static bool TryGetDocumentNameSeparator (string path, out char separator) - { - const char unix = '/'; - const char win = '\\'; - const char zero = (char)0; - - separator = zero; - if (string.IsNullOrEmpty (path)) - return false; - - int unix_count = 0; - int win_count = 0; - - for (int i = 0; i < path.Length; i++) { - if (path [i] == unix) - unix_count++; - else if (path [i] == win) - win_count++; - } - - if (unix_count == 0 && win_count == 0) - return false; - - if (unix_count >= win_count) { - separator = unix; - return true; - } - - separator = win; - return true; - } - - void AddSequencePoints (MethodDebugInformation info) - { - var rid = info.Method.MetadataToken.RID; - - Document document; - if (info.TryGetUniqueDocument (out document)) - method_debug_information_table.rows [rid - 1].Col1 = GetDocumentToken (document).RID; - - var signature = CreateSignatureWriter (); - signature.WriteSequencePoints (info); - - method_debug_information_table.rows [rid - 1].Col2 = GetBlobIndex (signature); - } - - public void ComputeDeterministicMvid () - { - var guid = CryptoService.ComputeGuid (CryptoService.ComputeHash ( - data, - resources, - string_heap, - user_string_heap, - blob_heap, - table_heap, - code)); - - var position = guid_heap.position; - guid_heap.position = 0; - guid_heap.WriteBytes (guid.ToByteArray ()); - guid_heap.position = position; - - module.Mvid = guid; - } - } - - sealed class SignatureWriter : ByteBuffer { - - readonly MetadataBuilder metadata; - - public SignatureWriter (MetadataBuilder metadata) - : base (6) - { - this.metadata = metadata; - } - - public void WriteElementType (ElementType element_type) - { - WriteByte ((byte)element_type); - } - - public void WriteUTF8String (string @string) - { - if (@string == null) { - WriteByte (0xff); - return; - } - - var bytes = Encoding.UTF8.GetBytes (@string); - WriteCompressedUInt32 ((uint)bytes.Length); - WriteBytes (bytes); - } - - public void WriteMethodSignature (IMethodSignature method) - { - byte calling_convention = (byte)method.CallingConvention; - if (method.HasThis) - calling_convention |= 0x20; - if (method.ExplicitThis) - calling_convention |= 0x40; - - var generic_provider = method as IGenericParameterProvider; - var generic_arity = generic_provider != null && generic_provider.HasGenericParameters - ? generic_provider.GenericParameters.Count - : 0; - - if (generic_arity > 0) - calling_convention |= 0x10; - - var param_count = method.HasParameters ? method.Parameters.Count : 0; - - WriteByte (calling_convention); - - if (generic_arity > 0) - WriteCompressedUInt32 ((uint)generic_arity); - - WriteCompressedUInt32 ((uint)param_count); - WriteTypeSignature (method.ReturnType); - - if (param_count == 0) - return; - - var parameters = method.Parameters; - - for (int i = 0; i < param_count; i++) - WriteTypeSignature (parameters [i].ParameterType); - } - - uint MakeTypeDefOrRefCodedRID (TypeReference type) - { - return CodedIndex.TypeDefOrRef.CompressMetadataToken (metadata.LookupToken (type)); - } - - public void WriteTypeToken (TypeReference type) - { - WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (type)); - } - - public void WriteTypeSignature (TypeReference type) - { - if (type == null) - throw new ArgumentNullException (); - - var etype = type.etype; - - switch (etype) { - case ElementType.MVar: - case ElementType.Var: { - var generic_parameter = (GenericParameter)type; - - WriteElementType (etype); - var position = generic_parameter.Position; - if (position == -1) - throw new NotSupportedException (); - - WriteCompressedUInt32 ((uint)position); - break; - } - - case ElementType.GenericInst: { - var generic_instance = (GenericInstanceType)type; - WriteElementType (ElementType.GenericInst); - WriteElementType (generic_instance.IsValueType ? ElementType.ValueType : ElementType.Class); - WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (generic_instance.ElementType)); - - WriteGenericInstanceSignature (generic_instance); - break; - } - - case ElementType.Ptr: - case ElementType.ByRef: - case ElementType.Pinned: - case ElementType.Sentinel: { - var type_spec = (TypeSpecification)type; - WriteElementType (etype); - WriteTypeSignature (type_spec.ElementType); - break; - } - - case ElementType.FnPtr: { - var fptr = (FunctionPointerType)type; - WriteElementType (ElementType.FnPtr); - WriteMethodSignature (fptr); - break; - } - - case ElementType.CModOpt: - case ElementType.CModReqD: { - var modifier = (IModifierType)type; - WriteModifierSignature (etype, modifier); - break; - } - - case ElementType.Array: { - var array = (ArrayType)type; - if (!array.IsVector) { - WriteArrayTypeSignature (array); - break; - } - - WriteElementType (ElementType.SzArray); - WriteTypeSignature (array.ElementType); - break; - } - - case ElementType.None: { - WriteElementType (type.IsValueType ? ElementType.ValueType : ElementType.Class); - WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (type)); - break; - } - - default: - if (!TryWriteElementType (type)) - throw new NotSupportedException (); - - break; - - } - } - - void WriteArrayTypeSignature (ArrayType array) - { - WriteElementType (ElementType.Array); - WriteTypeSignature (array.ElementType); - - var dimensions = array.Dimensions; - var rank = dimensions.Count; - - WriteCompressedUInt32 ((uint)rank); - - var sized = 0; - var lbounds = 0; - - for (int i = 0; i < rank; i++) { - var dimension = dimensions [i]; - - if (dimension.UpperBound.HasValue) { - sized++; - lbounds++; - } else if (dimension.LowerBound.HasValue) - lbounds++; - } - - var sizes = new int [sized]; - var low_bounds = new int [lbounds]; - - for (int i = 0; i < lbounds; i++) { - var dimension = dimensions [i]; - low_bounds [i] = dimension.LowerBound.GetValueOrDefault (); - if (dimension.UpperBound.HasValue) - sizes [i] = dimension.UpperBound.Value - low_bounds [i] + 1; - } - - WriteCompressedUInt32 ((uint)sized); - for (int i = 0; i < sized; i++) - WriteCompressedUInt32 ((uint)sizes [i]); - - WriteCompressedUInt32 ((uint)lbounds); - for (int i = 0; i < lbounds; i++) - WriteCompressedInt32 (low_bounds [i]); - } - - public void WriteGenericInstanceSignature (IGenericInstance instance) - { - var generic_arguments = instance.GenericArguments; - var arity = generic_arguments.Count; - - WriteCompressedUInt32 ((uint)arity); - for (int i = 0; i < arity; i++) - WriteTypeSignature (generic_arguments [i]); - } - - void WriteModifierSignature (ElementType element_type, IModifierType type) - { - WriteElementType (element_type); - WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (type.ModifierType)); - WriteTypeSignature (type.ElementType); - } - - bool TryWriteElementType (TypeReference type) - { - var element = type.etype; - - if (element == ElementType.None) - return false; - - WriteElementType (element); - return true; - } - - public void WriteConstantString (string value) - { - if (value != null) - WriteBytes (Encoding.Unicode.GetBytes (value)); - else - WriteByte (0xff); - } - - public void WriteConstantPrimitive (object value) - { - WritePrimitiveValue (value); - } - - public void WriteCustomAttributeConstructorArguments (CustomAttribute attribute) - { - if (!attribute.HasConstructorArguments) - return; - - var arguments = attribute.ConstructorArguments; - var parameters = attribute.Constructor.Parameters; - - if (parameters.Count != arguments.Count) - throw new InvalidOperationException (); - - for (int i = 0; i < arguments.Count; i++) - WriteCustomAttributeFixedArgument (parameters [i].ParameterType, arguments [i]); - } - - void WriteCustomAttributeFixedArgument (TypeReference type, CustomAttributeArgument argument) - { - if (type.IsArray) { - WriteCustomAttributeFixedArrayArgument ((ArrayType)type, argument); - return; - } - - WriteCustomAttributeElement (type, argument); - } - - void WriteCustomAttributeFixedArrayArgument (ArrayType type, CustomAttributeArgument argument) - { - var values = argument.Value as CustomAttributeArgument []; - - if (values == null) { - WriteUInt32 (0xffffffff); - return; - } - - WriteInt32 (values.Length); - - if (values.Length == 0) - return; - - var element_type = type.ElementType; - - for (int i = 0; i < values.Length; i++) - WriteCustomAttributeElement (element_type, values [i]); - } - - void WriteCustomAttributeElement (TypeReference type, CustomAttributeArgument argument) - { - if (type.IsArray) { - WriteCustomAttributeFixedArrayArgument ((ArrayType)type, argument); - return; - } - - if (type.etype == ElementType.Object) { - argument = (CustomAttributeArgument)argument.Value; - type = argument.Type; - - WriteCustomAttributeFieldOrPropType (type); - WriteCustomAttributeElement (type, argument); - return; - } - - WriteCustomAttributeValue (type, argument.Value); - } - - void WriteCustomAttributeValue (TypeReference type, object value) - { - var etype = type.etype; - - switch (etype) { - case ElementType.String: - var @string = (string)value; - if (@string == null) - WriteByte (0xff); - else - WriteUTF8String (@string); - break; - case ElementType.None: - if (type.IsTypeOf ("System", "Type")) - WriteCustomAttributeTypeValue ((TypeReference)value); - else - WriteCustomAttributeEnumValue (type, value); - break; - default: - WritePrimitiveValue (value); - break; - } - } - - private void WriteCustomAttributeTypeValue (TypeReference value) - { - var typeDefinition = value as TypeDefinition; - - if (typeDefinition != null) { - TypeDefinition outermostDeclaringType = typeDefinition; - while (outermostDeclaringType.DeclaringType != null) - outermostDeclaringType = outermostDeclaringType.DeclaringType; - - // In CLR .winmd files, custom attribute arguments reference unmangled type names (rather than Name) - if (WindowsRuntimeProjections.IsClrImplementationType (outermostDeclaringType)) { - WindowsRuntimeProjections.Project (outermostDeclaringType); - WriteTypeReference (value); - WindowsRuntimeProjections.RemoveProjection (outermostDeclaringType); - return; - } - } - - WriteTypeReference (value); - } - - void WritePrimitiveValue (object value) - { - if (value == null) - throw new ArgumentNullException (); - - switch (Type.GetTypeCode (value.GetType ())) { - case TypeCode.Boolean: - WriteByte ((byte)(((bool)value) ? 1 : 0)); - break; - case TypeCode.Byte: - WriteByte ((byte)value); - break; - case TypeCode.SByte: - WriteSByte ((sbyte)value); - break; - case TypeCode.Int16: - WriteInt16 ((short)value); - break; - case TypeCode.UInt16: - WriteUInt16 ((ushort)value); - break; - case TypeCode.Char: - WriteInt16 ((short)(char)value); - break; - case TypeCode.Int32: - WriteInt32 ((int)value); - break; - case TypeCode.UInt32: - WriteUInt32 ((uint)value); - break; - case TypeCode.Single: - WriteSingle ((float)value); - break; - case TypeCode.Int64: - WriteInt64 ((long)value); - break; - case TypeCode.UInt64: - WriteUInt64 ((ulong)value); - break; - case TypeCode.Double: - WriteDouble ((double)value); - break; - default: - throw new NotSupportedException (value.GetType ().FullName); - } - } - - void WriteCustomAttributeEnumValue (TypeReference enum_type, object value) - { - var type = enum_type.CheckedResolve (); - if (!type.IsEnum) - throw new ArgumentException (); - - WriteCustomAttributeValue (type.GetEnumUnderlyingType (), value); - } - - void WriteCustomAttributeFieldOrPropType (TypeReference type) - { - if (type.IsArray) { - var array = (ArrayType)type; - WriteElementType (ElementType.SzArray); - WriteCustomAttributeFieldOrPropType (array.ElementType); - return; - } - - var etype = type.etype; - - switch (etype) { - case ElementType.Object: - WriteElementType (ElementType.Boxed); - return; - case ElementType.None: - if (type.IsTypeOf ("System", "Type")) - WriteElementType (ElementType.Type); - else { - WriteElementType (ElementType.Enum); - WriteTypeReference (type); - } - return; - default: - WriteElementType (etype); - return; - } - } - - public void WriteCustomAttributeNamedArguments (CustomAttribute attribute) - { - var count = GetNamedArgumentCount (attribute); - - WriteUInt16 ((ushort)count); - - if (count == 0) - return; - - WriteICustomAttributeNamedArguments (attribute); - } - - static int GetNamedArgumentCount (ICustomAttribute attribute) - { - int count = 0; - - if (attribute.HasFields) - count += attribute.Fields.Count; - - if (attribute.HasProperties) - count += attribute.Properties.Count; - - return count; - } - - void WriteICustomAttributeNamedArguments (ICustomAttribute attribute) - { - if (attribute.HasFields) - WriteCustomAttributeNamedArguments (0x53, attribute.Fields); - - if (attribute.HasProperties) - WriteCustomAttributeNamedArguments (0x54, attribute.Properties); - } - - void WriteCustomAttributeNamedArguments (byte kind, Collection named_arguments) - { - for (int i = 0; i < named_arguments.Count; i++) - WriteCustomAttributeNamedArgument (kind, named_arguments [i]); - } - - void WriteCustomAttributeNamedArgument (byte kind, CustomAttributeNamedArgument named_argument) - { - var argument = named_argument.Argument; - - WriteByte (kind); - WriteCustomAttributeFieldOrPropType (argument.Type); - WriteUTF8String (named_argument.Name); - WriteCustomAttributeFixedArgument (argument.Type, argument); - } - - void WriteSecurityAttribute (SecurityAttribute attribute) - { - WriteTypeReference (attribute.AttributeType); - - var count = GetNamedArgumentCount (attribute); - - if (count == 0) { - WriteCompressedUInt32 (1); // length - WriteCompressedUInt32 (0); // count - return; - } - - var buffer = new SignatureWriter (metadata); - buffer.WriteCompressedUInt32 ((uint)count); - buffer.WriteICustomAttributeNamedArguments (attribute); - - WriteCompressedUInt32 ((uint)buffer.length); - WriteBytes (buffer); - } - - public void WriteSecurityDeclaration (SecurityDeclaration declaration) - { - WriteByte ((byte)'.'); - - var attributes = declaration.security_attributes; - if (attributes == null) - throw new NotSupportedException (); - - WriteCompressedUInt32 ((uint)attributes.Count); - - for (int i = 0; i < attributes.Count; i++) - WriteSecurityAttribute (attributes [i]); - } - - public void WriteXmlSecurityDeclaration (SecurityDeclaration declaration) - { - var xml = GetXmlSecurityDeclaration (declaration); - if (xml == null) - throw new NotSupportedException (); - - WriteBytes (Encoding.Unicode.GetBytes (xml)); - } - - static string GetXmlSecurityDeclaration (SecurityDeclaration declaration) - { - if (declaration.security_attributes == null || declaration.security_attributes.Count != 1) - return null; - - var attribute = declaration.security_attributes [0]; - - if (!attribute.AttributeType.IsTypeOf ("System.Security.Permissions", "PermissionSetAttribute")) - return null; - - if (attribute.properties == null || attribute.properties.Count != 1) - return null; - - var property = attribute.properties [0]; - if (property.Name != "XML") - return null; - - return (string)property.Argument.Value; - } - - void WriteTypeReference (TypeReference type) - { - WriteUTF8String (TypeParser.ToParseable (type, top_level: false)); - } - - public void WriteMarshalInfo (MarshalInfo marshal_info) - { - WriteNativeType (marshal_info.native); - - switch (marshal_info.native) { - case NativeType.Array: { - var array = (ArrayMarshalInfo)marshal_info; - if (array.element_type != NativeType.None) - WriteNativeType (array.element_type); - if (array.size_parameter_index > -1) - WriteCompressedUInt32 ((uint)array.size_parameter_index); - if (array.size > -1) - WriteCompressedUInt32 ((uint)array.size); - if (array.size_parameter_multiplier > -1) - WriteCompressedUInt32 ((uint)array.size_parameter_multiplier); - return; - } - case NativeType.SafeArray: { - var array = (SafeArrayMarshalInfo)marshal_info; - if (array.element_type != VariantType.None) - WriteVariantType (array.element_type); - return; - } - case NativeType.FixedArray: { - var array = (FixedArrayMarshalInfo)marshal_info; - if (array.size > -1) - WriteCompressedUInt32 ((uint)array.size); - if (array.element_type != NativeType.None) - WriteNativeType (array.element_type); - return; - } - case NativeType.FixedSysString: - var sys_string = (FixedSysStringMarshalInfo)marshal_info; - if (sys_string.size > -1) - WriteCompressedUInt32 ((uint)sys_string.size); - return; - case NativeType.CustomMarshaler: - var marshaler = (CustomMarshalInfo)marshal_info; - WriteUTF8String (marshaler.guid != Guid.Empty ? marshaler.guid.ToString () : string.Empty); - WriteUTF8String (marshaler.unmanaged_type); - WriteTypeReference (marshaler.managed_type); - WriteUTF8String (marshaler.cookie); - return; - } - } - - void WriteNativeType (NativeType native) - { - WriteByte ((byte)native); - } - - void WriteVariantType (VariantType variant) - { - WriteByte ((byte)variant); - } - - public void WriteSequencePoints (MethodDebugInformation info) - { - var start_line = -1; - var start_column = -1; - - WriteCompressedUInt32 (info.local_var_token.RID); - - Document previous_document; - if (!info.TryGetUniqueDocument (out previous_document)) - previous_document = null; - - for (int i = 0; i < info.SequencePoints.Count; i++) { - var sequence_point = info.SequencePoints [i]; - - var document = sequence_point.Document; - if (previous_document != document) { - var document_token = metadata.GetDocumentToken (document); - - if (previous_document != null) - WriteCompressedUInt32 (0); - - WriteCompressedUInt32 (document_token.RID); - previous_document = document; - } - - if (i > 0) - WriteCompressedUInt32 ((uint)(sequence_point.Offset - info.SequencePoints [i - 1].Offset)); - else - WriteCompressedUInt32 ((uint)sequence_point.Offset); - - if (sequence_point.IsHidden) { - WriteInt16 (0); - continue; - } - - var delta_lines = sequence_point.EndLine - sequence_point.StartLine; - var delta_columns = sequence_point.EndColumn - sequence_point.StartColumn; - - WriteCompressedUInt32 ((uint)delta_lines); - - if (delta_lines == 0) - WriteCompressedUInt32 ((uint)delta_columns); - else - WriteCompressedInt32 (delta_columns); - - if (start_line < 0) { - WriteCompressedUInt32 ((uint)sequence_point.StartLine); - WriteCompressedUInt32 ((uint)sequence_point.StartColumn); - } else { - WriteCompressedInt32 (sequence_point.StartLine - start_line); - WriteCompressedInt32 (sequence_point.StartColumn - start_column); - } - - start_line = sequence_point.StartLine; - start_column = sequence_point.StartColumn; - } - } - } - - static partial class Mixin { - - public static bool TryGetUniqueDocument (this MethodDebugInformation info, out Document document) - { - document = info.SequencePoints [0].Document; - - for (int i = 1; i < info.SequencePoints.Count; i++) { - var sequence_point = info.SequencePoints [i]; - if (sequence_point.Document != document) - return false; - } - - return true; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyWriter.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyWriter.cs.meta deleted file mode 100644 index a25718a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/AssemblyWriter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9a88ce645df13da4aa9eca43f013f6ae -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/BaseAssemblyResolver.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/BaseAssemblyResolver.cs deleted file mode 100644 index cb3c16a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/BaseAssemblyResolver.cs +++ /dev/null @@ -1,406 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; - -namespace MonoFN.Cecil { - - public delegate AssemblyDefinition AssemblyResolveEventHandler (object sender, AssemblyNameReference reference); - - public sealed class AssemblyResolveEventArgs : EventArgs { - - readonly AssemblyNameReference reference; - - public AssemblyNameReference AssemblyReference { - get { return reference; } - } - - public AssemblyResolveEventArgs (AssemblyNameReference reference) - { - this.reference = reference; - } - } - -#if !NET_CORE - [Serializable] -#endif - public sealed class AssemblyResolutionException : FileNotFoundException { - - readonly AssemblyNameReference reference; - - public AssemblyNameReference AssemblyReference { - get { return reference; } - } - - public AssemblyResolutionException (AssemblyNameReference reference) - : this (reference, null) - { - } - - public AssemblyResolutionException (AssemblyNameReference reference, Exception innerException) - : base (string.Format ("Failed to resolve assembly: '{0}'", reference), innerException) - { - this.reference = reference; - } - -#if !NET_CORE - AssemblyResolutionException ( - System.Runtime.Serialization.SerializationInfo info, - System.Runtime.Serialization.StreamingContext context) - : base (info, context) - { - } -#endif - } - - public abstract class BaseAssemblyResolver : IAssemblyResolver { - - static readonly bool on_mono = Type.GetType ("MonoFN.Runtime") != null; - - readonly Collection directories; - -#if NET_CORE - // Maps file names of available trusted platform assemblies to their full paths. - // Internal for testing. - internal static readonly Lazy> TrustedPlatformAssemblies = new Lazy> (CreateTrustedPlatformAssemblyMap); -#else - Collection gac_paths; -#endif - - public void AddSearchDirectory (string directory) - { - directories.Add (directory); - } - - public void RemoveSearchDirectory (string directory) - { - directories.Remove (directory); - } - - public string [] GetSearchDirectories () - { - var directories = new string [this.directories.size]; - Array.Copy (this.directories.items, directories, directories.Length); - return directories; - } - - public event AssemblyResolveEventHandler ResolveFailure; - - protected BaseAssemblyResolver () - { - directories = new Collection (2) { ".", "bin" }; - } - - AssemblyDefinition GetAssembly (string file, ReaderParameters parameters) - { - if (parameters.AssemblyResolver == null) - parameters.AssemblyResolver = this; - - return ModuleDefinition.ReadModule (file, parameters).Assembly; - } - - public virtual AssemblyDefinition Resolve (AssemblyNameReference name) - { - return Resolve (name, new ReaderParameters ()); - } - - public virtual AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters) - { - Mixin.CheckName (name); - Mixin.CheckParameters (parameters); - - var assembly = SearchDirectory (name, directories, parameters); - if (assembly != null) - return assembly; - - if (name.IsRetargetable) { - // if the reference is retargetable, zero it - name = new AssemblyNameReference (name.Name, Mixin.ZeroVersion) { - PublicKeyToken = Empty.Array, - }; - } - -#if NET_CORE - assembly = SearchTrustedPlatformAssemblies (name, parameters); - if (assembly != null) - return assembly; -#else - var framework_dir = Path.GetDirectoryName (typeof (object).Module.FullyQualifiedName); - var framework_dirs = on_mono - ? new [] { framework_dir, Path.Combine (framework_dir, "Facades") } - : new [] { framework_dir }; - - if (IsZero (name.Version)) { - assembly = SearchDirectory (name, framework_dirs, parameters); - if (assembly != null) - return assembly; - } - - if (name.Name == "mscorlib") { - assembly = GetCorlib (name, parameters); - if (assembly != null) - return assembly; - } - - assembly = GetAssemblyInGac (name, parameters); - if (assembly != null) - return assembly; - - assembly = SearchDirectory (name, framework_dirs, parameters); - if (assembly != null) - return assembly; -#endif - if (ResolveFailure != null) { - assembly = ResolveFailure (this, name); - if (assembly != null) - return assembly; - } - - throw new AssemblyResolutionException (name); - } - -#if NET_CORE - AssemblyDefinition SearchTrustedPlatformAssemblies (AssemblyNameReference name, ReaderParameters parameters) - { - if (name.IsWindowsRuntime) - return null; - - if (TrustedPlatformAssemblies.Value.TryGetValue (name.Name, out string path)) - return GetAssembly (path, parameters); - - return null; - } - - static Dictionary CreateTrustedPlatformAssemblyMap () - { - var result = new Dictionary (StringComparer.OrdinalIgnoreCase); - - string paths; - - try { - paths = (string) AppDomain.CurrentDomain.GetData ("TRUSTED_PLATFORM_ASSEMBLIES"); - } catch { - paths = null; - } - - if (paths == null) - return result; - - foreach (var path in paths.Split (Path.PathSeparator)) - if (string.Equals (Path.GetExtension (path), ".dll", StringComparison.OrdinalIgnoreCase)) - result [Path.GetFileNameWithoutExtension (path)] = path; - - return result; - } -#endif - - protected virtual AssemblyDefinition SearchDirectory (AssemblyNameReference name, IEnumerable directories, ReaderParameters parameters) - { - var extensions = name.IsWindowsRuntime ? new [] { ".winmd", ".dll" } : new [] { ".exe", ".dll" }; - foreach (var directory in directories) { - foreach (var extension in extensions) { - string file = Path.Combine (directory, name.Name + extension); - if (!File.Exists (file)) - continue; - try { - return GetAssembly (file, parameters); - } - catch (System.BadImageFormatException) { - continue; - } - } - } - - return null; - } - - static bool IsZero (Version version) - { - return version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0; - } - -#if !NET_CORE - AssemblyDefinition GetCorlib (AssemblyNameReference reference, ReaderParameters parameters) - { - var version = reference.Version; - var corlib = typeof (object).Assembly.GetName (); - if (corlib.Version == version || IsZero (version)) - return GetAssembly (typeof (object).Module.FullyQualifiedName, parameters); - - var path = Directory.GetParent ( - Directory.GetParent ( - typeof (object).Module.FullyQualifiedName).FullName - ).FullName; - - if (on_mono) { - if (version.Major == 1) - path = Path.Combine (path, "1.0"); - else if (version.Major == 2) { - if (version.MajorRevision == 5) - path = Path.Combine (path, "2.1"); - else - path = Path.Combine (path, "2.0"); - } else if (version.Major == 4) - path = Path.Combine (path, "4.0"); - else - throw new NotSupportedException ("Version not supported: " + version); - } else { - switch (version.Major) { - case 1: - if (version.MajorRevision == 3300) - path = Path.Combine (path, "v1.0.3705"); - else - path = Path.Combine (path, "v1.1.4322"); - break; - case 2: - path = Path.Combine (path, "v2.0.50727"); - break; - case 4: - path = Path.Combine (path, "v4.0.30319"); - break; - default: - throw new NotSupportedException ("Version not supported: " + version); - } - } - - var file = Path.Combine (path, "mscorlib.dll"); - if (File.Exists (file)) - return GetAssembly (file, parameters); - - if (on_mono && Directory.Exists (path + "-api")) { - file = Path.Combine (path + "-api", "mscorlib.dll"); - if (File.Exists (file)) - return GetAssembly (file, parameters); - } - - return null; - } - - static Collection GetGacPaths () - { - if (on_mono) - return GetDefaultMonoGacPaths (); - - var paths = new Collection (2); - var windir = Environment.GetEnvironmentVariable ("WINDIR"); - if (windir == null) - return paths; - - paths.Add (Path.Combine (windir, "assembly")); - paths.Add (Path.Combine (windir, Path.Combine ("Microsoft.NET", "assembly"))); - return paths; - } - - static Collection GetDefaultMonoGacPaths () - { - var paths = new Collection (1); - var gac = GetCurrentMonoGac (); - if (gac != null) - paths.Add (gac); - - var gac_paths_env = Environment.GetEnvironmentVariable ("MONO_GAC_PREFIX"); - if (string.IsNullOrEmpty (gac_paths_env)) - return paths; - - var prefixes = gac_paths_env.Split (Path.PathSeparator); - foreach (var prefix in prefixes) { - if (string.IsNullOrEmpty (prefix)) - continue; - - var gac_path = Path.Combine (Path.Combine (Path.Combine (prefix, "lib"), "mono"), "gac"); - if (Directory.Exists (gac_path) && !paths.Contains (gac)) - paths.Add (gac_path); - } - - return paths; - } - - static string GetCurrentMonoGac () - { - return Path.Combine ( - Directory.GetParent ( - Path.GetDirectoryName (typeof (object).Module.FullyQualifiedName)).FullName, - "gac"); - } - - AssemblyDefinition GetAssemblyInGac (AssemblyNameReference reference, ReaderParameters parameters) - { - if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0) - return null; - - if (gac_paths == null) - gac_paths = GetGacPaths (); - - if (on_mono) - return GetAssemblyInMonoGac (reference, parameters); - - return GetAssemblyInNetGac (reference, parameters); - } - - AssemblyDefinition GetAssemblyInMonoGac (AssemblyNameReference reference, ReaderParameters parameters) - { - for (int i = 0; i < gac_paths.Count; i++) { - var gac_path = gac_paths [i]; - var file = GetAssemblyFile (reference, string.Empty, gac_path); - if (File.Exists (file)) - return GetAssembly (file, parameters); - } - - return null; - } - - AssemblyDefinition GetAssemblyInNetGac (AssemblyNameReference reference, ReaderParameters parameters) - { - var gacs = new [] { "GAC_MSIL", "GAC_32", "GAC_64", "GAC" }; - var prefixes = new [] { string.Empty, "v4.0_" }; - - for (int i = 0; i < gac_paths.Count; i++) { - for (int j = 0; j < gacs.Length; j++) { - var gac = Path.Combine (gac_paths [i], gacs [j]); - var file = GetAssemblyFile (reference, prefixes [i], gac); - if (Directory.Exists (gac) && File.Exists (file)) - return GetAssembly (file, parameters); - } - } - - return null; - } - - static string GetAssemblyFile (AssemblyNameReference reference, string prefix, string gac) - { - var gac_folder = new StringBuilder () - .Append (prefix) - .Append (reference.Version) - .Append ("__"); - - for (int i = 0; i < reference.PublicKeyToken.Length; i++) - gac_folder.Append (reference.PublicKeyToken [i].ToString ("x2")); - - return Path.Combine ( - Path.Combine ( - Path.Combine (gac, reference.Name), gac_folder.ToString ()), - reference.Name + ".dll"); - } -#endif - public void Dispose () - { - Dispose (true); - GC.SuppressFinalize (this); - } - - protected virtual void Dispose (bool disposing) - { - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/BaseAssemblyResolver.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/BaseAssemblyResolver.cs.meta deleted file mode 100644 index 87211a6..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/BaseAssemblyResolver.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4ab1d53794ef7444c81e276b5a3a5c2b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CallSite.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CallSite.cs deleted file mode 100644 index 34e8ac7..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CallSite.cs +++ /dev/null @@ -1,105 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; -using System.Text; - -namespace MonoFN.Cecil { - - public sealed class CallSite : IMethodSignature { - - readonly MethodReference signature; - - public bool HasThis { - get { return signature.HasThis; } - set { signature.HasThis = value; } - } - - public bool ExplicitThis { - get { return signature.ExplicitThis; } - set { signature.ExplicitThis = value; } - } - - public MethodCallingConvention CallingConvention { - get { return signature.CallingConvention; } - set { signature.CallingConvention = value; } - } - - public bool HasParameters { - get { return signature.HasParameters; } - } - - public Collection Parameters { - get { return signature.Parameters; } - } - - public TypeReference ReturnType { - get { return signature.MethodReturnType.ReturnType; } - set { signature.MethodReturnType.ReturnType = value; } - } - - public MethodReturnType MethodReturnType { - get { return signature.MethodReturnType; } - } - - public string Name { - get { return string.Empty; } - set { throw new InvalidOperationException (); } - } - - public string Namespace { - get { return string.Empty; } - set { throw new InvalidOperationException (); } - } - - public ModuleDefinition Module { - get { return ReturnType.Module; } - } - - public IMetadataScope Scope { - get { return signature.ReturnType.Scope; } - } - - public MetadataToken MetadataToken { - get { return signature.token; } - set { signature.token = value; } - } - - public string FullName { - get { - var signature = new StringBuilder (); - signature.Append (ReturnType.FullName); - this.MethodSignatureFullName (signature); - return signature.ToString (); - } - } - - internal CallSite () - { - this.signature = new MethodReference (); - this.signature.token = new MetadataToken (TokenType.Signature, 0); - } - - public CallSite (TypeReference returnType) - : this () - { - if (returnType == null) - throw new ArgumentNullException ("returnType"); - - this.signature.ReturnType = returnType; - } - - public override string ToString () - { - return FullName; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CallSite.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CallSite.cs.meta deleted file mode 100644 index 8eac3ae..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CallSite.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 087823dce9623d348927f193f95a1807 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Consts.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Consts.cs deleted file mode 100644 index 54f90e6..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Consts.cs +++ /dev/null @@ -1,4 +0,0 @@ -static class Consts { - public const string AssemblyName = "MonoFN.Cecil"; - public const string PublicKey = "00240000048000009400000006020000002400005253413100040000010001002b5c9f7f04346c324a3176f8d3ee823bbf2d60efdbc35f86fd9e65ea3e6cd11bcdcba3a353e55133c8ac5c4caaba581b2c6dfff2cc2d0edc43959ddb86b973300a479a82419ef489c3225f1fe429a708507bd515835160e10bc743d20ca33ab9570cfd68d479fcf0bc797a763bec5d1000f0159ef619e709d915975e87beebaf"; -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Consts.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Consts.cs.meta deleted file mode 100644 index 2491449..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Consts.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: da413e0e98056364a9512beb26e9aea5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CustomAttribute.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CustomAttribute.cs deleted file mode 100644 index d9bda73..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CustomAttribute.cs +++ /dev/null @@ -1,221 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; -using System.Diagnostics; -using System.Threading; - -namespace MonoFN.Cecil { - - public struct CustomAttributeArgument { - - readonly TypeReference type; - readonly object value; - - public TypeReference Type { - get { return type; } - } - - public object Value { - get { return value; } - } - - public CustomAttributeArgument (TypeReference type, object value) - { - Mixin.CheckType (type); - this.type = type; - this.value = value; - } - } - - public struct CustomAttributeNamedArgument { - - readonly string name; - readonly CustomAttributeArgument argument; - - public string Name { - get { return name; } - } - - public CustomAttributeArgument Argument { - get { return argument; } - } - - public CustomAttributeNamedArgument (string name, CustomAttributeArgument argument) - { - Mixin.CheckName (name); - this.name = name; - this.argument = argument; - } - } - - public interface ICustomAttribute { - - TypeReference AttributeType { get; } - - bool HasFields { get; } - bool HasProperties { get; } - bool HasConstructorArguments { get; } - Collection Fields { get; } - Collection Properties { get; } - Collection ConstructorArguments { get; } - } - - [DebuggerDisplay ("{AttributeType}")] - public sealed class CustomAttribute : ICustomAttribute { - - internal CustomAttributeValueProjection projection; - readonly internal uint signature; - internal bool resolved; - MethodReference constructor; - byte [] blob; - internal Collection arguments; - internal Collection fields; - internal Collection properties; - - public MethodReference Constructor { - get { return constructor; } - set { constructor = value; } - } - - public TypeReference AttributeType { - get { return constructor.DeclaringType; } - } - - public bool IsResolved { - get { return resolved; } - } - - public bool HasConstructorArguments { - get { - Resolve (); - - return !arguments.IsNullOrEmpty (); - } - } - - public Collection ConstructorArguments { - get { - Resolve (); - - if (arguments == null) - Interlocked.CompareExchange (ref arguments, new Collection (), null); - - return arguments; - } - } - - public bool HasFields { - get { - Resolve (); - - return !fields.IsNullOrEmpty (); - } - } - - public Collection Fields { - get { - Resolve (); - - if (fields == null) - Interlocked.CompareExchange (ref fields, new Collection (), null); - - return fields; - } - } - - public bool HasProperties { - get { - Resolve (); - - return !properties.IsNullOrEmpty (); - } - } - - public Collection Properties { - get { - Resolve (); - - if (properties == null) - Interlocked.CompareExchange (ref properties, new Collection (), null); - - return properties; - } - } - - internal bool HasImage { - get { return constructor != null && constructor.HasImage; } - } - - internal ModuleDefinition Module { - get { return constructor.Module; } - } - - internal CustomAttribute (uint signature, MethodReference constructor) - { - this.signature = signature; - this.constructor = constructor; - this.resolved = false; - } - - public CustomAttribute (MethodReference constructor) - { - this.constructor = constructor; - this.resolved = true; - } - - public CustomAttribute (MethodReference constructor, byte [] blob) - { - this.constructor = constructor; - this.resolved = false; - this.blob = blob; - } - - public byte [] GetBlob () - { - if (blob != null) - return blob; - - if (!HasImage) - throw new NotSupportedException (); - - return Module.Read (ref blob, this, (attribute, reader) => reader.ReadCustomAttributeBlob (attribute.signature)); - } - - void Resolve () - { - if (resolved || !HasImage) - return; - - lock (Module.SyncRoot) { - if (resolved) - return; - - Module.Read (this, (attribute, reader) => { - try { - reader.ReadCustomAttributeSignature (attribute); - resolved = true; - } - catch (ResolutionException) { - if (arguments != null) - arguments.Clear (); - if (fields != null) - fields.Clear (); - if (properties != null) - properties.Clear (); - - resolved = false; - } - }); - } - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CustomAttribute.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CustomAttribute.cs.meta deleted file mode 100644 index d60edbe..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/CustomAttribute.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 91db4bc8250b4b949bf262a196c9c0c9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/DefaultAssemblyResolver.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/DefaultAssemblyResolver.cs deleted file mode 100644 index 6bbcf96..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/DefaultAssemblyResolver.cs +++ /dev/null @@ -1,61 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; -using System.Collections.Generic; - -namespace MonoFN.Cecil { - - public class DefaultAssemblyResolver : BaseAssemblyResolver { - - readonly IDictionary cache; - - public DefaultAssemblyResolver () - { - cache = new Dictionary (StringComparer.Ordinal); - } - - public override AssemblyDefinition Resolve (AssemblyNameReference name) - { - Mixin.CheckName (name); - - AssemblyDefinition assembly; - if (cache.TryGetValue (name.FullName, out assembly)) - return assembly; - - assembly = base.Resolve (name); - cache [name.FullName] = assembly; - - return assembly; - } - - protected void RegisterAssembly (AssemblyDefinition assembly) - { - if (assembly == null) - throw new ArgumentNullException ("assembly"); - - var name = assembly.Name.FullName; - if (cache.ContainsKey (name)) - return; - - cache [name] = assembly; - } - - protected override void Dispose (bool disposing) - { - foreach (var assembly in cache.Values) - assembly.Dispose (); - - cache.Clear (); - - base.Dispose (disposing); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/DefaultAssemblyResolver.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/DefaultAssemblyResolver.cs.meta deleted file mode 100644 index 75e60fb..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/DefaultAssemblyResolver.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5390b4f18cb83c046baaaa937fec06a7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EmbeddedResource.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EmbeddedResource.cs deleted file mode 100644 index 693283e..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EmbeddedResource.cs +++ /dev/null @@ -1,98 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; -using System.IO; - -namespace MonoFN.Cecil { - - public sealed class EmbeddedResource : Resource { - - readonly MetadataReader reader; - - uint? offset; - byte [] data; - Stream stream; - - public override ResourceType ResourceType { - get { return ResourceType.Embedded; } - } - - public EmbeddedResource (string name, ManifestResourceAttributes attributes, byte [] data) : - base (name, attributes) - { - this.data = data; - } - - public EmbeddedResource (string name, ManifestResourceAttributes attributes, Stream stream) : - base (name, attributes) - { - this.stream = stream; - } - - internal EmbeddedResource (string name, ManifestResourceAttributes attributes, uint offset, MetadataReader reader) - : base (name, attributes) - { - this.offset = offset; - this.reader = reader; - } - - public Stream GetResourceStream () - { - if (stream != null) - return stream; - - if (data != null) - return new MemoryStream (data); - - if (offset.HasValue) - return new MemoryStream (reader.GetManagedResource (offset.Value)); - - throw new InvalidOperationException (); - } - - public byte [] GetResourceData () - { - if (stream != null) - return ReadStream (stream); - - if (data != null) - return data; - - if (offset.HasValue) - return reader.GetManagedResource (offset.Value); - - throw new InvalidOperationException (); - } - - static byte [] ReadStream (Stream stream) - { - int read; - - if (stream.CanSeek) { - var length = (int)stream.Length; - var data = new byte [length]; - int offset = 0; - - while ((read = stream.Read (data, offset, length - offset)) > 0) - offset += read; - - return data; - } - - var buffer = new byte [1024 * 8]; - var memory = new MemoryStream (); - while ((read = stream.Read (buffer, 0, buffer.Length)) > 0) - memory.Write (buffer, 0, read); - - return memory.ToArray (); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EmbeddedResource.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EmbeddedResource.cs.meta deleted file mode 100644 index d7d8b36..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EmbeddedResource.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b5874acd8fee1b4499a3249dd4648428 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventAttributes.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventAttributes.cs deleted file mode 100644 index 7be266a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventAttributes.cs +++ /dev/null @@ -1,21 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - [Flags] - public enum EventAttributes : ushort { - None = 0x0000, - SpecialName = 0x0200, // Event is special - RTSpecialName = 0x0400 // CLI provides 'special' behavior, depending upon the name of the event - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventAttributes.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventAttributes.cs.meta deleted file mode 100644 index 11259a6..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventAttributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 20c18be3d45bbf84d82732fd16751df3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventDefinition.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventDefinition.cs deleted file mode 100644 index 28776b5..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventDefinition.cs +++ /dev/null @@ -1,156 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System.Threading; - -namespace MonoFN.Cecil { - - public sealed class EventDefinition : EventReference, IMemberDefinition { - - ushort attributes; - - Collection custom_attributes; - - internal MethodDefinition add_method; - internal MethodDefinition invoke_method; - internal MethodDefinition remove_method; - internal Collection other_methods; - - public EventAttributes Attributes { - get { return (EventAttributes)attributes; } - set { attributes = (ushort)value; } - } - - public MethodDefinition AddMethod { - get { - if (add_method != null) - return add_method; - - InitializeMethods (); - return add_method; - } - set { add_method = value; } - } - - public MethodDefinition InvokeMethod { - get { - if (invoke_method != null) - return invoke_method; - - InitializeMethods (); - return invoke_method; - } - set { invoke_method = value; } - } - - public MethodDefinition RemoveMethod { - get { - if (remove_method != null) - return remove_method; - - InitializeMethods (); - return remove_method; - } - set { remove_method = value; } - } - - public bool HasOtherMethods { - get { - if (other_methods != null) - return other_methods.Count > 0; - - InitializeMethods (); - return !other_methods.IsNullOrEmpty (); - } - } - - public Collection OtherMethods { - get { - if (other_methods != null) - return other_methods; - - InitializeMethods (); - - if (other_methods == null) - Interlocked.CompareExchange (ref other_methods, new Collection (), null); - - return other_methods; - } - } - - public bool HasCustomAttributes { - get { - if (custom_attributes != null) - return custom_attributes.Count > 0; - - return this.GetHasCustomAttributes (Module); - } - } - - public Collection CustomAttributes { - get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); } - } - - #region EventAttributes - - public bool IsSpecialName { - get { return attributes.GetAttributes ((ushort)EventAttributes.SpecialName); } - set { attributes = attributes.SetAttributes ((ushort)EventAttributes.SpecialName, value); } - } - - public bool IsRuntimeSpecialName { - get { return attributes.GetAttributes ((ushort)EventAttributes.RTSpecialName); } - set { attributes = attributes.SetAttributes ((ushort)EventAttributes.RTSpecialName, value); } - } - - #endregion - - public new TypeDefinition DeclaringType { - get { return (TypeDefinition)base.DeclaringType; } - set { base.DeclaringType = value; } - } - - public override bool IsDefinition { - get { return true; } - } - - public EventDefinition (string name, EventAttributes attributes, TypeReference eventType) - : base (name, eventType) - { - this.attributes = (ushort)attributes; - this.token = new MetadataToken (TokenType.Event); - } - - void InitializeMethods () - { - var module = this.Module; - if (module == null) - return; - - lock (module.SyncRoot) { - if (add_method != null - || invoke_method != null - || remove_method != null) - return; - - if (!module.HasImage ()) - return; - - module.Read (this, (@event, reader) => reader.ReadMethods (@event)); - } - } - - public override EventDefinition Resolve () - { - return this; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventDefinition.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventDefinition.cs.meta deleted file mode 100644 index c8daf6b..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventDefinition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4b201911ff1f925438edbe5b91275268 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventReference.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventReference.cs deleted file mode 100644 index d188a37..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventReference.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public abstract class EventReference : MemberReference { - - TypeReference event_type; - - public TypeReference EventType { - get { return event_type; } - set { event_type = value; } - } - - public override string FullName { - get { return event_type.FullName + " " + MemberFullName (); } - } - - protected EventReference (string name, TypeReference eventType) - : base (name) - { - Mixin.CheckType (eventType, Mixin.Argument.eventType); - event_type = eventType; - } - - protected override IMemberDefinition ResolveDefinition () - { - return this.Resolve (); - } - - public new abstract EventDefinition Resolve (); - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventReference.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventReference.cs.meta deleted file mode 100644 index 80e4e71..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/EventReference.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 94d9b58b6c4033343b975f6730127514 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ExportedType.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ExportedType.cs deleted file mode 100644 index 68b4410..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ExportedType.cs +++ /dev/null @@ -1,238 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public sealed class ExportedType : IMetadataTokenProvider { - - string @namespace; - string name; - uint attributes; - IMetadataScope scope; - ModuleDefinition module; - int identifier; - ExportedType declaring_type; - internal MetadataToken token; - - public string Namespace { - get { return @namespace; } - set { @namespace = value; } - } - - public string Name { - get { return name; } - set { name = value; } - } - - public TypeAttributes Attributes { - get { return (TypeAttributes)attributes; } - set { attributes = (uint)value; } - } - - public IMetadataScope Scope { - get { - if (declaring_type != null) - return declaring_type.Scope; - - return scope; - } - set { - if (declaring_type != null) { - declaring_type.Scope = value; - return; - } - - scope = value; - } - } - - public ExportedType DeclaringType { - get { return declaring_type; } - set { declaring_type = value; } - } - - public MetadataToken MetadataToken { - get { return token; } - set { token = value; } - } - - public int Identifier { - get { return identifier; } - set { identifier = value; } - } - - #region TypeAttributes - - public bool IsNotPublic { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NotPublic); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NotPublic, value); } - } - - public bool IsPublic { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.Public); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.Public, value); } - } - - public bool IsNestedPublic { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPublic); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPublic, value); } - } - - public bool IsNestedPrivate { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPrivate); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPrivate, value); } - } - - public bool IsNestedFamily { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamily); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamily, value); } - } - - public bool IsNestedAssembly { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedAssembly); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedAssembly, value); } - } - - public bool IsNestedFamilyAndAssembly { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamANDAssem); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamANDAssem, value); } - } - - public bool IsNestedFamilyOrAssembly { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamORAssem); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamORAssem, value); } - } - - public bool IsAutoLayout { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.AutoLayout); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.AutoLayout, value); } - } - - public bool IsSequentialLayout { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.SequentialLayout); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.SequentialLayout, value); } - } - - public bool IsExplicitLayout { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.ExplicitLayout); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.ExplicitLayout, value); } - } - - public bool IsClass { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Class); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Class, value); } - } - - public bool IsInterface { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Interface); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Interface, value); } - } - - public bool IsAbstract { - get { return attributes.GetAttributes ((uint)TypeAttributes.Abstract); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.Abstract, value); } - } - - public bool IsSealed { - get { return attributes.GetAttributes ((uint)TypeAttributes.Sealed); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.Sealed, value); } - } - - public bool IsSpecialName { - get { return attributes.GetAttributes ((uint)TypeAttributes.SpecialName); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.SpecialName, value); } - } - - public bool IsImport { - get { return attributes.GetAttributes ((uint)TypeAttributes.Import); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.Import, value); } - } - - public bool IsSerializable { - get { return attributes.GetAttributes ((uint)TypeAttributes.Serializable); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.Serializable, value); } - } - - public bool IsAnsiClass { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AnsiClass); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AnsiClass, value); } - } - - public bool IsUnicodeClass { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.UnicodeClass); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.UnicodeClass, value); } - } - - public bool IsAutoClass { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AutoClass); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AutoClass, value); } - } - - public bool IsBeforeFieldInit { - get { return attributes.GetAttributes ((uint)TypeAttributes.BeforeFieldInit); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.BeforeFieldInit, value); } - } - - public bool IsRuntimeSpecialName { - get { return attributes.GetAttributes ((uint)TypeAttributes.RTSpecialName); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.RTSpecialName, value); } - } - - public bool HasSecurity { - get { return attributes.GetAttributes ((uint)TypeAttributes.HasSecurity); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.HasSecurity, value); } - } - - #endregion - - public bool IsForwarder { - get { return attributes.GetAttributes ((uint)TypeAttributes.Forwarder); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.Forwarder, value); } - } - - public string FullName { - get { - var fullname = string.IsNullOrEmpty (@namespace) - ? name - : @namespace + '.' + name; - - if (declaring_type != null) - return declaring_type.FullName + "/" + fullname; - - return fullname; - } - } - - public ExportedType (string @namespace, string name, ModuleDefinition module, IMetadataScope scope) - { - this.@namespace = @namespace; - this.name = name; - this.scope = scope; - this.module = module; - } - - public override string ToString () - { - return FullName; - } - - public TypeDefinition Resolve () - { - return module.Resolve (CreateReference ()); - } - - internal TypeReference CreateReference () - { - return new TypeReference (@namespace, name, module, scope) { - DeclaringType = declaring_type != null ? declaring_type.CreateReference () : null, - }; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ExportedType.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ExportedType.cs.meta deleted file mode 100644 index 27b33ff..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ExportedType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b7fa6f0bdd43c0d44a63cd789a765eeb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldAttributes.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldAttributes.cs deleted file mode 100644 index e4afd2c..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldAttributes.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - [Flags] - public enum FieldAttributes : ushort { - FieldAccessMask = 0x0007, - CompilerControlled = 0x0000, // Member not referenceable - Private = 0x0001, // Accessible only by the parent type - FamANDAssem = 0x0002, // Accessible by sub-types only in this assembly - Assembly = 0x0003, // Accessible by anyone in the Assembly - Family = 0x0004, // Accessible only by type and sub-types - FamORAssem = 0x0005, // Accessible by sub-types anywhere, plus anyone in the assembly - Public = 0x0006, // Accessible by anyone who has visibility to this scope field contract attributes - - Static = 0x0010, // Defined on type, else per instance - InitOnly = 0x0020, // Field may only be initialized, not written after init - Literal = 0x0040, // Value is compile time constant - NotSerialized = 0x0080, // Field does not have to be serialized when type is remoted - SpecialName = 0x0200, // Field is special - - // Interop Attributes - PInvokeImpl = 0x2000, // Implementation is forwarded through PInvoke - - // Additional flags - RTSpecialName = 0x0400, // CLI provides 'special' behavior, depending upon the name of the field - HasFieldMarshal = 0x1000, // Field has marshalling information - HasDefault = 0x8000, // Field has default - HasFieldRVA = 0x0100 // Field has RVA - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldAttributes.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldAttributes.cs.meta deleted file mode 100644 index 767a61d..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldAttributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8e9187082e8fc1446a8c2aa12d8f3fa4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldDefinition.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldDefinition.cs deleted file mode 100644 index 73cdbc9..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldDefinition.cs +++ /dev/null @@ -1,281 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; - -namespace MonoFN.Cecil { - - public sealed class FieldDefinition : FieldReference, IMemberDefinition, IConstantProvider, IMarshalInfoProvider { - - ushort attributes; - Collection custom_attributes; - - int offset = Mixin.NotResolvedMarker; - - internal int rva = Mixin.NotResolvedMarker; - byte [] initial_value; - - object constant = Mixin.NotResolved; - - MarshalInfo marshal_info; - - void ResolveLayout () - { - if (offset != Mixin.NotResolvedMarker) - return; - - if (!HasImage) { - offset = Mixin.NoDataMarker; - return; - } - - lock (Module.SyncRoot) { - if (offset != Mixin.NotResolvedMarker) - return; - offset = Module.Read (this, (field, reader) => reader.ReadFieldLayout (field)); - } - } - - public bool HasLayoutInfo { - get { - if (offset >= 0) - return true; - - ResolveLayout (); - - return offset >= 0; - } - } - - public int Offset { - get { - if (offset >= 0) - return offset; - - ResolveLayout (); - - return offset >= 0 ? offset : -1; - } - set { offset = value; } - } - - internal FieldDefinitionProjection WindowsRuntimeProjection { - get { return (FieldDefinitionProjection)projection; } - set { projection = value; } - } - - void ResolveRVA () - { - if (rva != Mixin.NotResolvedMarker) - return; - - if (!HasImage) - return; - - lock (Module.SyncRoot) { - if (rva != Mixin.NotResolvedMarker) - return; - rva = Module.Read (this, (field, reader) => reader.ReadFieldRVA (field)); - } - } - - public int RVA { - get { - if (rva > 0) - return rva; - - ResolveRVA (); - - return rva > 0 ? rva : 0; - } - } - - public byte [] InitialValue { - get { - if (initial_value != null) - return initial_value; - - ResolveRVA (); - - if (initial_value == null) - initial_value = Empty.Array; - - return initial_value; - } - set { - initial_value = value; - HasFieldRVA = !initial_value.IsNullOrEmpty (); - rva = 0; - } - } - - public FieldAttributes Attributes { - get { return (FieldAttributes)attributes; } - set { - if (IsWindowsRuntimeProjection && (ushort)value != attributes) - throw new InvalidOperationException (); - - attributes = (ushort)value; - } - } - - public bool HasConstant { - get { - this.ResolveConstant (ref constant, Module); - - return constant != Mixin.NoValue; - } - set { if (!value) constant = Mixin.NoValue; } - } - - public object Constant { - get { return HasConstant ? constant : null; } - set { constant = value; } - } - - public bool HasCustomAttributes { - get { - if (custom_attributes != null) - return custom_attributes.Count > 0; - - return this.GetHasCustomAttributes (Module); - } - } - - public Collection CustomAttributes { - get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); } - } - - public bool HasMarshalInfo { - get { - if (marshal_info != null) - return true; - - return this.GetHasMarshalInfo (Module); - } - } - - public MarshalInfo MarshalInfo { - get { return marshal_info ?? (this.GetMarshalInfo (ref marshal_info, Module)); } - set { marshal_info = value; } - } - - #region FieldAttributes - - public bool IsCompilerControlled { - get { return attributes.GetMaskedAttributes ((ushort)FieldAttributes.FieldAccessMask, (ushort)FieldAttributes.CompilerControlled); } - set { attributes = attributes.SetMaskedAttributes ((ushort)FieldAttributes.FieldAccessMask, (ushort)FieldAttributes.CompilerControlled, value); } - } - - public bool IsPrivate { - get { return attributes.GetMaskedAttributes ((ushort)FieldAttributes.FieldAccessMask, (ushort)FieldAttributes.Private); } - set { attributes = attributes.SetMaskedAttributes ((ushort)FieldAttributes.FieldAccessMask, (ushort)FieldAttributes.Private, value); } - } - - public bool IsFamilyAndAssembly { - get { return attributes.GetMaskedAttributes ((ushort)FieldAttributes.FieldAccessMask, (ushort)FieldAttributes.FamANDAssem); } - set { attributes = attributes.SetMaskedAttributes ((ushort)FieldAttributes.FieldAccessMask, (ushort)FieldAttributes.FamANDAssem, value); } - } - - public bool IsAssembly { - get { return attributes.GetMaskedAttributes ((ushort)FieldAttributes.FieldAccessMask, (ushort)FieldAttributes.Assembly); } - set { attributes = attributes.SetMaskedAttributes ((ushort)FieldAttributes.FieldAccessMask, (ushort)FieldAttributes.Assembly, value); } - } - - public bool IsFamily { - get { return attributes.GetMaskedAttributes ((ushort)FieldAttributes.FieldAccessMask, (ushort)FieldAttributes.Family); } - set { attributes = attributes.SetMaskedAttributes ((ushort)FieldAttributes.FieldAccessMask, (ushort)FieldAttributes.Family, value); } - } - - public bool IsFamilyOrAssembly { - get { return attributes.GetMaskedAttributes ((ushort)FieldAttributes.FieldAccessMask, (ushort)FieldAttributes.FamORAssem); } - set { attributes = attributes.SetMaskedAttributes ((ushort)FieldAttributes.FieldAccessMask, (ushort)FieldAttributes.FamORAssem, value); } - } - - public bool IsPublic { - get { return attributes.GetMaskedAttributes ((ushort)FieldAttributes.FieldAccessMask, (ushort)FieldAttributes.Public); } - set { attributes = attributes.SetMaskedAttributes ((ushort)FieldAttributes.FieldAccessMask, (ushort)FieldAttributes.Public, value); } - } - - public bool IsStatic { - get { return attributes.GetAttributes ((ushort)FieldAttributes.Static); } - set { attributes = attributes.SetAttributes ((ushort)FieldAttributes.Static, value); } - } - - public bool IsInitOnly { - get { return attributes.GetAttributes ((ushort)FieldAttributes.InitOnly); } - set { attributes = attributes.SetAttributes ((ushort)FieldAttributes.InitOnly, value); } - } - - public bool IsLiteral { - get { return attributes.GetAttributes ((ushort)FieldAttributes.Literal); } - set { attributes = attributes.SetAttributes ((ushort)FieldAttributes.Literal, value); } - } - - public bool IsNotSerialized { - get { return attributes.GetAttributes ((ushort)FieldAttributes.NotSerialized); } - set { attributes = attributes.SetAttributes ((ushort)FieldAttributes.NotSerialized, value); } - } - - public bool IsSpecialName { - get { return attributes.GetAttributes ((ushort)FieldAttributes.SpecialName); } - set { attributes = attributes.SetAttributes ((ushort)FieldAttributes.SpecialName, value); } - } - - public bool IsPInvokeImpl { - get { return attributes.GetAttributes ((ushort)FieldAttributes.PInvokeImpl); } - set { attributes = attributes.SetAttributes ((ushort)FieldAttributes.PInvokeImpl, value); } - } - - public bool IsRuntimeSpecialName { - get { return attributes.GetAttributes ((ushort)FieldAttributes.RTSpecialName); } - set { attributes = attributes.SetAttributes ((ushort)FieldAttributes.RTSpecialName, value); } - } - - public bool HasDefault { - get { return attributes.GetAttributes ((ushort)FieldAttributes.HasDefault); } - set { attributes = attributes.SetAttributes ((ushort)FieldAttributes.HasDefault, value); } - } - - public bool HasFieldRVA { - get { return attributes.GetAttributes ((ushort)FieldAttributes.HasFieldRVA); } - set { attributes = attributes.SetAttributes ((ushort)FieldAttributes.HasFieldRVA, value); } - } - - #endregion - - public override bool IsDefinition { - get { return true; } - } - - public new TypeDefinition DeclaringType { - get { return (TypeDefinition)base.DeclaringType; } - set { base.DeclaringType = value; } - } - - public FieldDefinition (string name, FieldAttributes attributes, TypeReference fieldType) - : base (name, fieldType) - { - this.attributes = (ushort)attributes; - } - - public override FieldDefinition Resolve () - { - return this; - } - } - - static partial class Mixin { - - public const int NotResolvedMarker = -2; - public const int NoDataMarker = -1; - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldDefinition.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldDefinition.cs.meta deleted file mode 100644 index 99dac2a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldDefinition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 00dcb95135f39ec4c923f7923bcc93ed -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldReference.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldReference.cs deleted file mode 100644 index 1e9d3e3..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldReference.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - public class FieldReference : MemberReference { - - TypeReference field_type; - - public TypeReference FieldType { - get { return field_type; } - set { field_type = value; } - } - - public override string FullName { - get { return field_type.FullName + " " + MemberFullName (); } - } - - public override bool ContainsGenericParameter { - get { return field_type.ContainsGenericParameter || base.ContainsGenericParameter; } - } - - internal FieldReference () - { - this.token = new MetadataToken (TokenType.MemberRef); - } - - public FieldReference (string name, TypeReference fieldType) - : base (name) - { - Mixin.CheckType (fieldType, Mixin.Argument.fieldType); - - this.field_type = fieldType; - this.token = new MetadataToken (TokenType.MemberRef); - } - - public FieldReference (string name, TypeReference fieldType, TypeReference declaringType) - : this (name, fieldType) - { - Mixin.CheckType (declaringType, Mixin.Argument.declaringType); - - this.DeclaringType = declaringType; - } - - protected override IMemberDefinition ResolveDefinition () - { - return this.Resolve (); - } - - public new virtual FieldDefinition Resolve () - { - var module = this.Module; - if (module == null) - throw new NotSupportedException (); - - return module.Resolve (this); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldReference.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldReference.cs.meta deleted file mode 100644 index 6f1c541..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FieldReference.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 990be2becde06b4468f79bd17646a47a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FileAttributes.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FileAttributes.cs deleted file mode 100644 index 32715d5..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FileAttributes.cs +++ /dev/null @@ -1,17 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - enum FileAttributes : uint { - ContainsMetaData = 0x0000, // This is not a resource file - ContainsNoMetaData = 0x0001, // This is a resource file or other non-metadata-containing file - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FileAttributes.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FileAttributes.cs.meta deleted file mode 100644 index 58c3fe0..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FileAttributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 56e662d580c0894489669cc8058a2783 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FunctionPointerType.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FunctionPointerType.cs deleted file mode 100644 index 8558c54..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FunctionPointerType.cs +++ /dev/null @@ -1,111 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; -using System.Text; -using MD = MonoFN.Cecil.Metadata; - -namespace MonoFN.Cecil { - - public sealed class FunctionPointerType : TypeSpecification, IMethodSignature { - - readonly MethodReference function; - - public bool HasThis { - get { return function.HasThis; } - set { function.HasThis = value; } - } - - public bool ExplicitThis { - get { return function.ExplicitThis; } - set { function.ExplicitThis = value; } - } - - public MethodCallingConvention CallingConvention { - get { return function.CallingConvention; } - set { function.CallingConvention = value; } - } - - public bool HasParameters { - get { return function.HasParameters; } - } - - public Collection Parameters { - get { return function.Parameters; } - } - - public TypeReference ReturnType { - get { return function.MethodReturnType.ReturnType; } - set { function.MethodReturnType.ReturnType = value; } - } - - public MethodReturnType MethodReturnType { - get { return function.MethodReturnType; } - } - - public override string Name { - get { return function.Name; } - set { throw new InvalidOperationException (); } - } - - public override string Namespace { - get { return string.Empty; } - set { throw new InvalidOperationException (); } - } - - public override ModuleDefinition Module { - get { return ReturnType.Module; } - } - - public override IMetadataScope Scope { - get { return function.ReturnType.Scope; } - set { throw new InvalidOperationException (); } - } - - public override bool IsFunctionPointer { - get { return true; } - } - - public override bool ContainsGenericParameter { - get { return function.ContainsGenericParameter; } - } - - public override string FullName { - get { - var signature = new StringBuilder (); - signature.Append (function.Name); - signature.Append (" "); - signature.Append (function.ReturnType.FullName); - signature.Append (" *"); - this.MethodSignatureFullName (signature); - return signature.ToString (); - } - } - - public FunctionPointerType () - : base (null) - { - this.function = new MethodReference (); - this.function.Name = "method"; - this.etype = MD.ElementType.FnPtr; - } - - public override TypeDefinition Resolve () - { - return null; - } - - public override TypeReference GetElementType () - { - return this; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FunctionPointerType.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FunctionPointerType.cs.meta deleted file mode 100644 index a576fd7..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/FunctionPointerType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 91d84cd146416f945acbfce1b1dbcacb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceMethod.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceMethod.cs deleted file mode 100644 index 64737a9..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceMethod.cs +++ /dev/null @@ -1,77 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System.Text; -using System.Threading; - -namespace MonoFN.Cecil { - - public sealed class GenericInstanceMethod : MethodSpecification, IGenericInstance, IGenericContext { - - Collection arguments; - - public bool HasGenericArguments { - get { return !arguments.IsNullOrEmpty (); } - } - - public Collection GenericArguments { - get { - if (arguments == null) - Interlocked.CompareExchange (ref arguments, new Collection (), null); - - return arguments; - } - } - - public override bool IsGenericInstance { - get { return true; } - } - - IGenericParameterProvider IGenericContext.Method { - get { return ElementMethod; } - } - - IGenericParameterProvider IGenericContext.Type { - get { return ElementMethod.DeclaringType; } - } - - public override bool ContainsGenericParameter { - get { return this.ContainsGenericParameter () || base.ContainsGenericParameter; } - } - - public override string FullName { - get { - var signature = new StringBuilder (); - var method = this.ElementMethod; - signature.Append (method.ReturnType.FullName) - .Append (" ") - .Append (method.DeclaringType.FullName) - .Append ("::") - .Append (method.Name); - this.GenericInstanceFullName (signature); - this.MethodSignatureFullName (signature); - return signature.ToString (); - - } - } - - public GenericInstanceMethod (MethodReference method) - : base (method) - { - } - - internal GenericInstanceMethod (MethodReference method, int arity) - : this (method) - { - this.arguments = new Collection (arity); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceMethod.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceMethod.cs.meta deleted file mode 100644 index cee2434..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceMethod.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fd61b82dc3c653d42a1fc0f4e4c003f8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceType.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceType.cs deleted file mode 100644 index 4f40314..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceType.cs +++ /dev/null @@ -1,75 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; -using System.Text; -using System.Threading; -using MD = MonoFN.Cecil.Metadata; - -namespace MonoFN.Cecil { - - public sealed class GenericInstanceType : TypeSpecification, IGenericInstance, IGenericContext { - - Collection arguments; - - public bool HasGenericArguments { - get { return !arguments.IsNullOrEmpty (); } - } - - public Collection GenericArguments { - get { - if (arguments == null) - Interlocked.CompareExchange (ref arguments, new Collection (), null); - - return arguments; - } - } - - public override TypeReference DeclaringType { - get { return ElementType.DeclaringType; } - set { throw new NotSupportedException (); } - } - - public override string FullName { - get { - var name = new StringBuilder (); - name.Append (base.FullName); - this.GenericInstanceFullName (name); - return name.ToString (); - } - } - - public override bool IsGenericInstance { - get { return true; } - } - - public override bool ContainsGenericParameter { - get { return this.ContainsGenericParameter () || base.ContainsGenericParameter; } - } - - IGenericParameterProvider IGenericContext.Type { - get { return ElementType; } - } - - public GenericInstanceType (TypeReference type) - : base (type) - { - base.IsValueType = type.IsValueType; - this.etype = MD.ElementType.GenericInst; - } - - internal GenericInstanceType (TypeReference type, int arity) - : this (type) - { - this.arguments = new Collection (arity); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceType.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceType.cs.meta deleted file mode 100644 index 3d8278d..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericInstanceType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 536e7e359f0fa6c449a352476e8af197 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameter.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameter.cs deleted file mode 100644 index 6b7ada6..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameter.cs +++ /dev/null @@ -1,360 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Metadata; -using MonoFN.Collections.Generic; -using System; -using System.Threading; - -namespace MonoFN.Cecil { - - public sealed class GenericParameter : TypeReference, ICustomAttributeProvider { - - internal int position; - internal GenericParameterType type; - internal IGenericParameterProvider owner; - - ushort attributes; - GenericParameterConstraintCollection constraints; - Collection custom_attributes; - - public GenericParameterAttributes Attributes { - get { return (GenericParameterAttributes)attributes; } - set { attributes = (ushort)value; } - } - - public int Position { - get { return position; } - } - - public GenericParameterType Type { - get { return type; } - } - - public IGenericParameterProvider Owner { - get { return owner; } - } - - public bool HasConstraints { - get { - if (constraints != null) - return constraints.Count > 0; - - return HasImage && Module.Read (this, (generic_parameter, reader) => reader.HasGenericConstraints (generic_parameter)); - } - } - - public Collection Constraints { - get { - if (constraints != null) - return constraints; - - if (HasImage) - return Module.Read (ref constraints, this, (generic_parameter, reader) => reader.ReadGenericConstraints (generic_parameter)); - - Interlocked.CompareExchange (ref constraints, new GenericParameterConstraintCollection (this), null); - return constraints; - } - } - - public bool HasCustomAttributes { - get { - if (custom_attributes != null) - return custom_attributes.Count > 0; - - return this.GetHasCustomAttributes (Module); - } - } - - public Collection CustomAttributes { - get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); } - } - - public override IMetadataScope Scope { - get { - if (owner == null) - return null; - - return owner.GenericParameterType == GenericParameterType.Method - ? ((MethodReference)owner).DeclaringType.Scope - : ((TypeReference)owner).Scope; - } - set { throw new InvalidOperationException (); } - } - - public override TypeReference DeclaringType { - get { return owner as TypeReference; } - set { throw new InvalidOperationException (); } - } - - public MethodReference DeclaringMethod { - get { return owner as MethodReference; } - } - - public override ModuleDefinition Module { - get { return module ?? owner.Module; } - } - - public override string Name { - get { - if (!string.IsNullOrEmpty (base.Name)) - return base.Name; - - return base.Name = (type == GenericParameterType.Method ? "!!" : "!") + position; - } - } - - public override string Namespace { - get { return string.Empty; } - set { throw new InvalidOperationException (); } - } - - public override string FullName { - get { return Name; } - } - - public override bool IsGenericParameter { - get { return true; } - } - - public override bool ContainsGenericParameter { - get { return true; } - } - - public override MetadataType MetadataType { - get { return (MetadataType)etype; } - } - - #region GenericParameterAttributes - - public bool IsNonVariant { - get { return attributes.GetMaskedAttributes ((ushort)GenericParameterAttributes.VarianceMask, (ushort)GenericParameterAttributes.NonVariant); } - set { attributes = attributes.SetMaskedAttributes ((ushort)GenericParameterAttributes.VarianceMask, (ushort)GenericParameterAttributes.NonVariant, value); } - } - - public bool IsCovariant { - get { return attributes.GetMaskedAttributes ((ushort)GenericParameterAttributes.VarianceMask, (ushort)GenericParameterAttributes.Covariant); } - set { attributes = attributes.SetMaskedAttributes ((ushort)GenericParameterAttributes.VarianceMask, (ushort)GenericParameterAttributes.Covariant, value); } - } - - public bool IsContravariant { - get { return attributes.GetMaskedAttributes ((ushort)GenericParameterAttributes.VarianceMask, (ushort)GenericParameterAttributes.Contravariant); } - set { attributes = attributes.SetMaskedAttributes ((ushort)GenericParameterAttributes.VarianceMask, (ushort)GenericParameterAttributes.Contravariant, value); } - } - - public bool HasReferenceTypeConstraint { - get { return attributes.GetAttributes ((ushort)GenericParameterAttributes.ReferenceTypeConstraint); } - set { attributes = attributes.SetAttributes ((ushort)GenericParameterAttributes.ReferenceTypeConstraint, value); } - } - - public bool HasNotNullableValueTypeConstraint { - get { return attributes.GetAttributes ((ushort)GenericParameterAttributes.NotNullableValueTypeConstraint); } - set { attributes = attributes.SetAttributes ((ushort)GenericParameterAttributes.NotNullableValueTypeConstraint, value); } - } - - public bool HasDefaultConstructorConstraint { - get { return attributes.GetAttributes ((ushort)GenericParameterAttributes.DefaultConstructorConstraint); } - set { attributes = attributes.SetAttributes ((ushort)GenericParameterAttributes.DefaultConstructorConstraint, value); } - } - - #endregion - - public GenericParameter (IGenericParameterProvider owner) - : this (string.Empty, owner) - { - } - - public GenericParameter (string name, IGenericParameterProvider owner) - : base (string.Empty, name) - { - if (owner == null) - throw new ArgumentNullException (); - - this.position = -1; - this.owner = owner; - this.type = owner.GenericParameterType; - this.etype = ConvertGenericParameterType (this.type); - this.token = new MetadataToken (TokenType.GenericParam); - - } - - internal GenericParameter (int position, GenericParameterType type, ModuleDefinition module) - : base (string.Empty, string.Empty) - { - Mixin.CheckModule (module); - - this.position = position; - this.type = type; - this.etype = ConvertGenericParameterType (type); - this.module = module; - this.token = new MetadataToken (TokenType.GenericParam); - } - - static ElementType ConvertGenericParameterType (GenericParameterType type) - { - switch (type) { - case GenericParameterType.Type: - return ElementType.Var; - case GenericParameterType.Method: - return ElementType.MVar; - } - - throw new ArgumentOutOfRangeException (); - } - - public override TypeDefinition Resolve () - { - return null; - } - } - - sealed class GenericParameterCollection : Collection { - - readonly IGenericParameterProvider owner; - - internal GenericParameterCollection (IGenericParameterProvider owner) - { - this.owner = owner; - } - - internal GenericParameterCollection (IGenericParameterProvider owner, int capacity) - : base (capacity) - { - this.owner = owner; - } - - protected override void OnAdd (GenericParameter item, int index) - { - UpdateGenericParameter (item, index); - } - - protected override void OnInsert (GenericParameter item, int index) - { - UpdateGenericParameter (item, index); - - for (int i = index; i < size; i++) - items [i].position = i + 1; - } - - protected override void OnSet (GenericParameter item, int index) - { - UpdateGenericParameter (item, index); - } - - void UpdateGenericParameter (GenericParameter item, int index) - { - item.owner = owner; - item.position = index; - item.type = owner.GenericParameterType; - } - - protected override void OnRemove (GenericParameter item, int index) - { - item.owner = null; - item.position = -1; - item.type = GenericParameterType.Type; - - for (int i = index + 1; i < size; i++) - items [i].position = i - 1; - } - } - - public sealed class GenericParameterConstraint : ICustomAttributeProvider { - - internal GenericParameter generic_parameter; - internal MetadataToken token; - - TypeReference constraint_type; - Collection custom_attributes; - - public TypeReference ConstraintType { - get { return constraint_type; } - set { constraint_type = value; } - } - - public bool HasCustomAttributes { - get { - if (custom_attributes != null) - return custom_attributes.Count > 0; - - if (generic_parameter == null) - return false; - - return this.GetHasCustomAttributes (generic_parameter.Module); - } - } - - public Collection CustomAttributes { - get { - if (generic_parameter == null) { - if (custom_attributes == null) - Interlocked.CompareExchange (ref custom_attributes, new Collection (), null); - return custom_attributes; - } - - return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, generic_parameter.Module)); - } - } - - public MetadataToken MetadataToken { - get { return token; } - set { token = value; } - } - - internal GenericParameterConstraint (TypeReference constraintType, MetadataToken token) - { - this.constraint_type = constraintType; - this.token = token; - } - - public GenericParameterConstraint (TypeReference constraintType) - { - Mixin.CheckType (constraintType, Mixin.Argument.constraintType); - - this.constraint_type = constraintType; - this.token = new MetadataToken (TokenType.GenericParamConstraint); - } - } - - class GenericParameterConstraintCollection : Collection { - readonly GenericParameter generic_parameter; - - internal GenericParameterConstraintCollection (GenericParameter genericParameter) - { - this.generic_parameter = genericParameter; - } - - internal GenericParameterConstraintCollection (GenericParameter genericParameter, int length) - : base (length) - { - this.generic_parameter = genericParameter; - } - - protected override void OnAdd (GenericParameterConstraint item, int index) - { - item.generic_parameter = generic_parameter; - } - - protected override void OnInsert (GenericParameterConstraint item, int index) - { - item.generic_parameter = generic_parameter; - } - - protected override void OnSet (GenericParameterConstraint item, int index) - { - item.generic_parameter = generic_parameter; - } - - protected override void OnRemove (GenericParameterConstraint item, int index) - { - item.generic_parameter = null; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameter.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameter.cs.meta deleted file mode 100644 index 73db53b..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a20d39eab5fe7884c8cdf55fde143904 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterAttributes.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterAttributes.cs deleted file mode 100644 index a5ae0fc..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterAttributes.cs +++ /dev/null @@ -1,27 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - [Flags] - public enum GenericParameterAttributes : ushort { - VarianceMask = 0x0003, - NonVariant = 0x0000, - Covariant = 0x0001, - Contravariant = 0x0002, - - SpecialConstraintMask = 0x001c, - ReferenceTypeConstraint = 0x0004, - NotNullableValueTypeConstraint = 0x0008, - DefaultConstructorConstraint = 0x0010 - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterAttributes.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterAttributes.cs.meta deleted file mode 100644 index b4e1bf9..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterAttributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 406369465fc07a643b3923d53fb1e941 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterResolver.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterResolver.cs deleted file mode 100644 index b3677e6..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterResolver.cs +++ /dev/null @@ -1,175 +0,0 @@ -using MonoFN.Cecil.Cil; -using System; - -namespace MonoFN.Cecil { - internal sealed class GenericParameterResolver { - internal static TypeReference ResolveReturnTypeIfNeeded (MethodReference methodReference) - { - if (methodReference.DeclaringType.IsArray && methodReference.Name == "Get") - return methodReference.ReturnType; - - var genericInstanceMethod = methodReference as GenericInstanceMethod; - var declaringGenericInstanceType = methodReference.DeclaringType as GenericInstanceType; - - if (genericInstanceMethod == null && declaringGenericInstanceType == null) - return methodReference.ReturnType; - - return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, methodReference.ReturnType); - } - - internal static TypeReference ResolveFieldTypeIfNeeded (FieldReference fieldReference) - { - return ResolveIfNeeded (null, fieldReference.DeclaringType as GenericInstanceType, fieldReference.FieldType); - } - - internal static TypeReference ResolveParameterTypeIfNeeded (MethodReference method, ParameterReference parameter) - { - var genericInstanceMethod = method as GenericInstanceMethod; - var declaringGenericInstanceType = method.DeclaringType as GenericInstanceType; - - if (genericInstanceMethod == null && declaringGenericInstanceType == null) - return parameter.ParameterType; - - return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, parameter.ParameterType); - } - - internal static TypeReference ResolveVariableTypeIfNeeded (MethodReference method, VariableReference variable) - { - var genericInstanceMethod = method as GenericInstanceMethod; - var declaringGenericInstanceType = method.DeclaringType as GenericInstanceType; - - if (genericInstanceMethod == null && declaringGenericInstanceType == null) - return variable.VariableType; - - return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, variable.VariableType); - } - - private static TypeReference ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance declaringGenericInstanceType, TypeReference parameterType) - { - var byRefType = parameterType as ByReferenceType; - if (byRefType != null) - return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, byRefType); - - var arrayType = parameterType as ArrayType; - if (arrayType != null) - return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, arrayType); - - var genericInstanceType = parameterType as GenericInstanceType; - if (genericInstanceType != null) - return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, genericInstanceType); - - var genericParameter = parameterType as GenericParameter; - if (genericParameter != null) - return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, genericParameter); - - var requiredModifierType = parameterType as RequiredModifierType; - if (requiredModifierType != null && ContainsGenericParameters (requiredModifierType)) - return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, requiredModifierType.ElementType); - - if (ContainsGenericParameters (parameterType)) - throw new Exception ("Unexpected generic parameter."); - - return parameterType; - } - - private static TypeReference ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, GenericParameter genericParameterElement) - { - return (genericParameterElement.MetadataType == MetadataType.MVar) - ? (genericInstanceMethod != null ? genericInstanceMethod.GenericArguments [genericParameterElement.Position] : genericParameterElement) - : genericInstanceType.GenericArguments [genericParameterElement.Position]; - } - - private static ArrayType ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, ArrayType arrayType) - { - return new ArrayType (ResolveIfNeeded (genericInstanceMethod, genericInstanceType, arrayType.ElementType), arrayType.Rank); - } - - private static ByReferenceType ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, ByReferenceType byReferenceType) - { - return new ByReferenceType (ResolveIfNeeded (genericInstanceMethod, genericInstanceType, byReferenceType.ElementType)); - } - - private static GenericInstanceType ResolveIfNeeded (IGenericInstance genericInstanceMethod, IGenericInstance genericInstanceType, GenericInstanceType genericInstanceType1) - { - if (!ContainsGenericParameters (genericInstanceType1)) - return genericInstanceType1; - - var newGenericInstance = new GenericInstanceType (genericInstanceType1.ElementType); - - foreach (var genericArgument in genericInstanceType1.GenericArguments) { - if (!genericArgument.IsGenericParameter) { - newGenericInstance.GenericArguments.Add (ResolveIfNeeded (genericInstanceMethod, genericInstanceType, genericArgument)); - continue; - } - - var genParam = (GenericParameter)genericArgument; - - switch (genParam.Type) { - case GenericParameterType.Type: { - if (genericInstanceType == null) - throw new NotSupportedException (); - - newGenericInstance.GenericArguments.Add (genericInstanceType.GenericArguments [genParam.Position]); - } - break; - - case GenericParameterType.Method: { - if (genericInstanceMethod == null) - newGenericInstance.GenericArguments.Add (genParam); - else - newGenericInstance.GenericArguments.Add (genericInstanceMethod.GenericArguments [genParam.Position]); - } - break; - } - } - - return newGenericInstance; - } - - private static bool ContainsGenericParameters (TypeReference typeReference) - { - var genericParameter = typeReference as GenericParameter; - if (genericParameter != null) - return true; - - var arrayType = typeReference as ArrayType; - if (arrayType != null) - return ContainsGenericParameters (arrayType.ElementType); - - var pointerType = typeReference as PointerType; - if (pointerType != null) - return ContainsGenericParameters (pointerType.ElementType); - - var byRefType = typeReference as ByReferenceType; - if (byRefType != null) - return ContainsGenericParameters (byRefType.ElementType); - - var sentinelType = typeReference as SentinelType; - if (sentinelType != null) - return ContainsGenericParameters (sentinelType.ElementType); - - var pinnedType = typeReference as PinnedType; - if (pinnedType != null) - return ContainsGenericParameters (pinnedType.ElementType); - - var requiredModifierType = typeReference as RequiredModifierType; - if (requiredModifierType != null) - return ContainsGenericParameters (requiredModifierType.ElementType); - - var genericInstance = typeReference as GenericInstanceType; - if (genericInstance != null) { - foreach (var genericArgument in genericInstance.GenericArguments) { - if (ContainsGenericParameters (genericArgument)) - return true; - } - - return false; - } - - if (typeReference is TypeSpecification) - throw new NotSupportedException (); - - return false; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterResolver.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterResolver.cs.meta deleted file mode 100644 index c982dd5..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/GenericParameterResolver.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4151464170fe40440a031e1f4f2ecf53 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IConstantProvider.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IConstantProvider.cs deleted file mode 100644 index 3631258..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IConstantProvider.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public interface IConstantProvider : IMetadataTokenProvider { - - bool HasConstant { get; set; } - object Constant { get; set; } - } - - static partial class Mixin { - - internal static object NoValue = new object (); - internal static object NotResolved = new object (); - - public static void ResolveConstant ( - this IConstantProvider self, - ref object constant, - ModuleDefinition module) - { - if (module == null) { - constant = Mixin.NoValue; - return; - } - - lock (module.SyncRoot) { - if (constant != Mixin.NotResolved) - return; - if (module.HasImage ()) - constant = module.Read (self, (provider, reader) => reader.ReadConstant (provider)); - else - constant = Mixin.NoValue; - } - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IConstantProvider.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IConstantProvider.cs.meta deleted file mode 100644 index 8f377d7..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IConstantProvider.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 58315b928b9e49540b9d1591523c92c6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ICustomAttributeProvider.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ICustomAttributeProvider.cs deleted file mode 100644 index 39b8f01..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ICustomAttributeProvider.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System.Threading; - -namespace MonoFN.Cecil { - - public interface ICustomAttributeProvider : IMetadataTokenProvider { - - Collection CustomAttributes { get; } - - bool HasCustomAttributes { get; } - } - - static partial class Mixin { - - public static bool GetHasCustomAttributes ( - this ICustomAttributeProvider self, - ModuleDefinition module) - { - return module.HasImage () && module.Read (self, (provider, reader) => reader.HasCustomAttributes (provider)); - } - - public static Collection GetCustomAttributes ( - this ICustomAttributeProvider self, - ref Collection variable, - ModuleDefinition module) - { - if (module.HasImage ()) - return module.Read (ref variable, self, (provider, reader) => reader.ReadCustomAttributes (provider)); - - Interlocked.CompareExchange (ref variable, new Collection (), null); - return variable; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ICustomAttributeProvider.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ICustomAttributeProvider.cs.meta deleted file mode 100644 index e61f1f9..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ICustomAttributeProvider.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1585603aa3fe4f1409c42694378a557c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericInstance.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericInstance.cs deleted file mode 100644 index ecee2cc..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericInstance.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System.Text; - -namespace MonoFN.Cecil { - - public interface IGenericInstance : IMetadataTokenProvider { - - bool HasGenericArguments { get; } - Collection GenericArguments { get; } - } - - static partial class Mixin { - - public static bool ContainsGenericParameter (this IGenericInstance self) - { - var arguments = self.GenericArguments; - - for (int i = 0; i < arguments.Count; i++) - if (arguments [i].ContainsGenericParameter) - return true; - - return false; - } - - public static void GenericInstanceFullName (this IGenericInstance self, StringBuilder builder) - { - builder.Append ("<"); - var arguments = self.GenericArguments; - for (int i = 0; i < arguments.Count; i++) { - if (i > 0) - builder.Append (","); - builder.Append (arguments [i].FullName); - } - builder.Append (">"); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericInstance.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericInstance.cs.meta deleted file mode 100644 index 3907d65..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericInstance.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 22b3a8ddd25a989449e5e9ffc632bc00 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericParameterProvider.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericParameterProvider.cs deleted file mode 100644 index da27ad3..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericParameterProvider.cs +++ /dev/null @@ -1,58 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System.Threading; - -namespace MonoFN.Cecil { - - public interface IGenericParameterProvider : IMetadataTokenProvider { - - bool HasGenericParameters { get; } - bool IsDefinition { get; } - ModuleDefinition Module { get; } - Collection GenericParameters { get; } - GenericParameterType GenericParameterType { get; } - } - - public enum GenericParameterType { - Type, - Method - } - - interface IGenericContext { - - bool IsDefinition { get; } - IGenericParameterProvider Type { get; } - IGenericParameterProvider Method { get; } - } - - static partial class Mixin { - - public static bool GetHasGenericParameters ( - this IGenericParameterProvider self, - ModuleDefinition module) - { - return module.HasImage () && module.Read (self, (provider, reader) => reader.HasGenericParameters (provider)); - } - - public static Collection GetGenericParameters ( - this IGenericParameterProvider self, - ref Collection collection, - ModuleDefinition module) - { - if (module.HasImage ()) - return module.Read (ref collection, self, (provider, reader) => reader.ReadGenericParameters (provider)); - - Interlocked.CompareExchange (ref collection, new GenericParameterCollection (self), null); - return collection; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericParameterProvider.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericParameterProvider.cs.meta deleted file mode 100644 index d11d967..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IGenericParameterProvider.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c81842a9d1ff34f4b94b047da954469f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMarshalInfoProvider.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMarshalInfoProvider.cs deleted file mode 100644 index 75faa1a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMarshalInfoProvider.cs +++ /dev/null @@ -1,38 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public interface IMarshalInfoProvider : IMetadataTokenProvider { - - bool HasMarshalInfo { get; } - MarshalInfo MarshalInfo { get; set; } - } - - static partial class Mixin { - - public static bool GetHasMarshalInfo ( - this IMarshalInfoProvider self, - ModuleDefinition module) - { - return module.HasImage () && module.Read (self, (provider, reader) => reader.HasMarshalInfo (provider)); - } - - public static MarshalInfo GetMarshalInfo ( - this IMarshalInfoProvider self, - ref MarshalInfo variable, - ModuleDefinition module) - { - return module.HasImage () - ? module.Read (ref variable, self, (provider, reader) => reader.ReadMarshalInfo (provider)) - : null; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMarshalInfoProvider.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMarshalInfoProvider.cs.meta deleted file mode 100644 index 8ce8f0c..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMarshalInfoProvider.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a73829f4e35521e4892ef4e0cce2e4f9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMemberDefinition.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMemberDefinition.cs deleted file mode 100644 index 743e8d4..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMemberDefinition.cs +++ /dev/null @@ -1,82 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public interface IMemberDefinition : ICustomAttributeProvider { - - string Name { get; set; } - string FullName { get; } - - bool IsSpecialName { get; set; } - bool IsRuntimeSpecialName { get; set; } - - TypeDefinition DeclaringType { get; set; } - } - - static partial class Mixin { - - public static bool GetAttributes (this uint self, uint attributes) - { - return (self & attributes) != 0; - } - - public static uint SetAttributes (this uint self, uint attributes, bool value) - { - if (value) - return self | attributes; - - return self & ~attributes; - } - - public static bool GetMaskedAttributes (this uint self, uint mask, uint attributes) - { - return (self & mask) == attributes; - } - - public static uint SetMaskedAttributes (this uint self, uint mask, uint attributes, bool value) - { - if (value) { - self &= ~mask; - return self | attributes; - } - - return self & ~(mask & attributes); - } - - public static bool GetAttributes (this ushort self, ushort attributes) - { - return (self & attributes) != 0; - } - - public static ushort SetAttributes (this ushort self, ushort attributes, bool value) - { - if (value) - return (ushort)(self | attributes); - - return (ushort)(self & ~attributes); - } - - public static bool GetMaskedAttributes (this ushort self, ushort mask, uint attributes) - { - return (self & mask) == attributes; - } - - public static ushort SetMaskedAttributes (this ushort self, ushort mask, uint attributes, bool value) - { - if (value) { - self = (ushort)(self & ~mask); - return (ushort)(self | attributes); - } - - return (ushort)(self & ~(mask & attributes)); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMemberDefinition.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMemberDefinition.cs.meta deleted file mode 100644 index b78f8dc..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMemberDefinition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 482577ba8693d3f438504e54d6edb971 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataScope.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataScope.cs deleted file mode 100644 index 7604a9e..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataScope.cs +++ /dev/null @@ -1,23 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public enum MetadataScopeType { - AssemblyNameReference, - ModuleReference, - ModuleDefinition, - } - - public interface IMetadataScope : IMetadataTokenProvider { - MetadataScopeType MetadataScopeType { get; } - string Name { get; set; } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataScope.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataScope.cs.meta deleted file mode 100644 index 0b8b2bc..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataScope.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: da1ce103d170a414c8c8c6849a8856a3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataTokenProvider.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataTokenProvider.cs deleted file mode 100644 index a82c759..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataTokenProvider.cs +++ /dev/null @@ -1,17 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public interface IMetadataTokenProvider { - - MetadataToken MetadataToken { get; set; } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataTokenProvider.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataTokenProvider.cs.meta deleted file mode 100644 index eb83452..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMetadataTokenProvider.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c01133d3a99e95542b153987746696d1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMethodSignature.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMethodSignature.cs deleted file mode 100644 index 57be39c..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMethodSignature.cs +++ /dev/null @@ -1,56 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System.Text; - -namespace MonoFN.Cecil { - - public interface IMethodSignature : IMetadataTokenProvider { - - bool HasThis { get; set; } - bool ExplicitThis { get; set; } - MethodCallingConvention CallingConvention { get; set; } - - bool HasParameters { get; } - Collection Parameters { get; } - TypeReference ReturnType { get; set; } - MethodReturnType MethodReturnType { get; } - } - - static partial class Mixin { - - public static bool HasImplicitThis (this IMethodSignature self) - { - return self.HasThis && !self.ExplicitThis; - } - - public static void MethodSignatureFullName (this IMethodSignature self, StringBuilder builder) - { - builder.Append ("("); - - if (self.HasParameters) { - var parameters = self.Parameters; - for (int i = 0; i < parameters.Count; i++) { - var parameter = parameters [i]; - if (i > 0) - builder.Append (","); - - if (parameter.ParameterType.IsSentinel) - builder.Append ("...,"); - - builder.Append (parameter.ParameterType.FullName); - } - } - - builder.Append (")"); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMethodSignature.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMethodSignature.cs.meta deleted file mode 100644 index 2f3a715..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/IMethodSignature.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8fdcc55987f0a4f4b93358d994704a98 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Import.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Import.cs deleted file mode 100644 index e021176..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Import.cs +++ /dev/null @@ -1,858 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Metadata; -using MonoFN.Collections.Generic; -using System; -using System.Collections.Generic; -using SR = System.Reflection; - -namespace MonoFN.Cecil -{ - - public interface IMetadataImporterProvider - { - IMetadataImporter GetMetadataImporter(ModuleDefinition module); - } - - public interface IMetadataImporter - { - AssemblyNameReference ImportReference(AssemblyNameReference reference); - TypeReference ImportReference(TypeReference type, IGenericParameterProvider context); - FieldReference ImportReference(FieldReference field, IGenericParameterProvider context); - MethodReference ImportReference(MethodReference method, IGenericParameterProvider context); - } - - public interface IReflectionImporterProvider - { - IReflectionImporter GetReflectionImporter(ModuleDefinition module); - } - - public interface IReflectionImporter - { - AssemblyNameReference ImportReference(SR.AssemblyName reference); - TypeReference ImportReference(Type type, IGenericParameterProvider context); - FieldReference ImportReference(SR.FieldInfo field, IGenericParameterProvider context); - MethodReference ImportReference(SR.MethodBase method, IGenericParameterProvider context); - } - - struct ImportGenericContext - { - - Collection stack; - - public bool IsEmpty { get { return stack == null; } } - - public ImportGenericContext(IGenericParameterProvider provider) - { - if (provider == null) - throw new ArgumentNullException("provider"); - - stack = null; - - Push(provider); - } - - public void Push(IGenericParameterProvider provider) - { - if (stack == null) - stack = new Collection(1) { provider }; - else - stack.Add(provider); - } - - public void Pop() - { - stack.RemoveAt(stack.Count - 1); - } - - public TypeReference MethodParameter(string method, int position) - { - for (int i = stack.Count - 1; i >= 0; i--) - { - var candidate = stack[i] as MethodReference; - if (candidate == null) - continue; - - if (method != NormalizeMethodName(candidate)) - continue; - - return candidate.GenericParameters[position]; - } - - throw new InvalidOperationException(); - } - - public string NormalizeMethodName(MethodReference method) - { - return method.DeclaringType.GetElementType().FullName + "." + method.Name; - } - - public TypeReference TypeParameter(string type, int position) - { - for (int i = stack.Count - 1; i >= 0; i--) - { - var candidate = GenericTypeFor(stack[i]); - - if (candidate.FullName != type) - continue; - - return candidate.GenericParameters[position]; - } - - throw new InvalidOperationException(); - } - - static TypeReference GenericTypeFor(IGenericParameterProvider context) - { - var type = context as TypeReference; - if (type != null) - return type.GetElementType(); - - var method = context as MethodReference; - if (method != null) - return method.DeclaringType.GetElementType(); - - throw new InvalidOperationException(); - } - - public static ImportGenericContext For(IGenericParameterProvider context) - { - return context != null ? new ImportGenericContext(context) : default(ImportGenericContext); - } - } - - public class DefaultReflectionImporter : IReflectionImporter - { - - readonly protected ModuleDefinition module; - - public DefaultReflectionImporter(ModuleDefinition module) - { - Mixin.CheckModule(module); - this.module = module; - } - - enum ImportGenericKind - { - Definition, - Open, - } - - static readonly Dictionary type_etype_mapping = new Dictionary(18) { - { typeof (void), ElementType.Void }, - { typeof (bool), ElementType.Boolean }, - { typeof (char), ElementType.Char }, - { typeof (sbyte), ElementType.I1 }, - { typeof (byte), ElementType.U1 }, - { typeof (short), ElementType.I2 }, - { typeof (ushort), ElementType.U2 }, - { typeof (int), ElementType.I4 }, - { typeof (uint), ElementType.U4 }, - { typeof (long), ElementType.I8 }, - { typeof (ulong), ElementType.U8 }, - { typeof (float), ElementType.R4 }, - { typeof (double), ElementType.R8 }, - { typeof (string), ElementType.String }, - { typeof (TypedReference), ElementType.TypedByRef }, - { typeof (IntPtr), ElementType.I }, - { typeof (UIntPtr), ElementType.U }, - { typeof (object), ElementType.Object }, - }; - - TypeReference ImportType(Type type, ImportGenericContext context) - { - return ImportType(type, context, ImportGenericKind.Open); - } - - TypeReference ImportType(Type type, ImportGenericContext context, ImportGenericKind import_kind) - { - if (IsTypeSpecification(type) || ImportOpenGenericType(type, import_kind)) - return ImportTypeSpecification(type, context); - - var reference = new TypeReference( - string.Empty, - type.Name, - module, - ImportScope(type), - type.IsValueType); - - reference.etype = ImportElementType(type); - - if (IsNestedType(type)) - reference.DeclaringType = ImportType(type.DeclaringType, context, import_kind); - else - reference.Namespace = type.Namespace ?? string.Empty; - - if (type.IsGenericType) - ImportGenericParameters(reference, type.GetGenericArguments()); - - return reference; - } - - protected virtual IMetadataScope ImportScope(Type type) - { - return ImportScope(type.Assembly); - } - - static bool ImportOpenGenericType(Type type, ImportGenericKind import_kind) - { - return type.IsGenericType && type.IsGenericTypeDefinition && import_kind == ImportGenericKind.Open; - } - - static bool ImportOpenGenericMethod(SR.MethodBase method, ImportGenericKind import_kind) - { - return method.IsGenericMethod && method.IsGenericMethodDefinition && import_kind == ImportGenericKind.Open; - } - - static bool IsNestedType(Type type) - { - return type.IsNested; - } - - TypeReference ImportTypeSpecification(Type type, ImportGenericContext context) - { - if (type.IsByRef) - return new ByReferenceType(ImportType(type.GetElementType(), context)); - - if (type.IsPointer) - return new PointerType(ImportType(type.GetElementType(), context)); - - if (type.IsArray) - return new ArrayType(ImportType(type.GetElementType(), context), type.GetArrayRank()); - - if (type.IsGenericType) - return ImportGenericInstance(type, context); - - if (type.IsGenericParameter) - return ImportGenericParameter(type, context); - - throw new NotSupportedException(type.FullName); - } - - static TypeReference ImportGenericParameter(Type type, ImportGenericContext context) - { - if (context.IsEmpty) - throw new InvalidOperationException(); - - if (type.DeclaringMethod != null) - return context.MethodParameter(NormalizeMethodName(type.DeclaringMethod), type.GenericParameterPosition); - - if (type.DeclaringType != null) - return context.TypeParameter(NormalizeTypeFullName(type.DeclaringType), type.GenericParameterPosition); - - throw new InvalidOperationException(); - } - - static string NormalizeMethodName(SR.MethodBase method) - { - return NormalizeTypeFullName(method.DeclaringType) + "." + method.Name; - } - - static string NormalizeTypeFullName(Type type) - { - if (IsNestedType(type)) - return NormalizeTypeFullName(type.DeclaringType) + "/" + type.Name; - - return type.FullName; - } - - TypeReference ImportGenericInstance(Type type, ImportGenericContext context) - { - var element_type = ImportType(type.GetGenericTypeDefinition(), context, ImportGenericKind.Definition); - var arguments = type.GetGenericArguments(); - var instance = new GenericInstanceType(element_type, arguments.Length); - var instance_arguments = instance.GenericArguments; - - context.Push(element_type); - try - { - for (int i = 0; i < arguments.Length; i++) - instance_arguments.Add(ImportType(arguments[i], context)); - - return instance; - } - finally - { - context.Pop(); - } - } - - static bool IsTypeSpecification(Type type) - { - return type.HasElementType - || IsGenericInstance(type) - || type.IsGenericParameter; - } - - static bool IsGenericInstance(Type type) - { - return type.IsGenericType && !type.IsGenericTypeDefinition; - } - - static ElementType ImportElementType(Type type) - { - ElementType etype; - if (!type_etype_mapping.TryGetValue(type, out etype)) - return ElementType.None; - - return etype; - } - - protected AssemblyNameReference ImportScope(SR.Assembly assembly) - { - return ImportReference(assembly.GetName()); - } - - public virtual AssemblyNameReference ImportReference(SR.AssemblyName name) - { - Mixin.CheckName(name); - - AssemblyNameReference reference; - if (TryGetAssemblyNameReference(name, out reference)) - return reference; - - reference = new AssemblyNameReference(name.Name, name.Version) - { - PublicKeyToken = name.GetPublicKeyToken(), - Culture = name.CultureInfo.Name, - HashAlgorithm = (AssemblyHashAlgorithm)name.HashAlgorithm, - }; - - module.AssemblyReferences.Add(reference); - return reference; - } - - bool TryGetAssemblyNameReference(SR.AssemblyName name, out AssemblyNameReference assembly_reference) - { - var references = module.AssemblyReferences; - - for (int i = 0; i < references.Count; i++) - { - var reference = references[i]; - if (name.FullName != reference.FullName) // TODO compare field by field - continue; - - assembly_reference = reference; - return true; - } - - assembly_reference = null; - return false; - } - - FieldReference ImportField(SR.FieldInfo field, ImportGenericContext context) - { - var declaring_type = ImportType(field.DeclaringType, context); - - if (IsGenericInstance(field.DeclaringType)) - field = ResolveFieldDefinition(field); - - context.Push(declaring_type); - try - { - return new FieldReference - { - Name = field.Name, - DeclaringType = declaring_type, - FieldType = ImportType(field.FieldType, context), - }; - } - finally - { - context.Pop(); - } - } - - static SR.FieldInfo ResolveFieldDefinition(SR.FieldInfo field) - { - return field.Module.ResolveField(field.MetadataToken); - } - - static SR.MethodBase ResolveMethodDefinition(SR.MethodBase method) - { - return method.Module.ResolveMethod(method.MetadataToken); - } - - MethodReference ImportMethod(SR.MethodBase method, ImportGenericContext context, ImportGenericKind import_kind) - { - if (IsMethodSpecification(method) || ImportOpenGenericMethod(method, import_kind)) - return ImportMethodSpecification(method, context); - - var declaring_type = ImportType(method.DeclaringType, context); - - if (IsGenericInstance(method.DeclaringType)) - method = ResolveMethodDefinition(method); - - var reference = new MethodReference - { - Name = method.Name, - HasThis = HasCallingConvention(method, SR.CallingConventions.HasThis), - ExplicitThis = HasCallingConvention(method, SR.CallingConventions.ExplicitThis), - DeclaringType = ImportType(method.DeclaringType, context, ImportGenericKind.Definition), - }; - - if (HasCallingConvention(method, SR.CallingConventions.VarArgs)) - reference.CallingConvention &= MethodCallingConvention.VarArg; - - if (method.IsGenericMethod) - ImportGenericParameters(reference, method.GetGenericArguments()); - - context.Push(reference); - try - { - var method_info = method as SR.MethodInfo; - reference.ReturnType = method_info != null - ? ImportType(method_info.ReturnType, context) - : ImportType(typeof(void), default(ImportGenericContext)); - - var parameters = method.GetParameters(); - var reference_parameters = reference.Parameters; - - for (int i = 0; i < parameters.Length; i++) - reference_parameters.Add( - new ParameterDefinition(ImportType(parameters[i].ParameterType, context))); - - reference.DeclaringType = declaring_type; - - return reference; - } - finally - { - context.Pop(); - } - } - - static void ImportGenericParameters(IGenericParameterProvider provider, Type[] arguments) - { - var provider_parameters = provider.GenericParameters; - - for (int i = 0; i < arguments.Length; i++) - provider_parameters.Add(new GenericParameter(arguments[i].Name, provider)); - } - - static bool IsMethodSpecification(SR.MethodBase method) - { - return method.IsGenericMethod && !method.IsGenericMethodDefinition; - } - - MethodReference ImportMethodSpecification(SR.MethodBase method, ImportGenericContext context) - { - var method_info = method as SR.MethodInfo; - if (method_info == null) - throw new InvalidOperationException(); - - var element_method = ImportMethod(method_info.GetGenericMethodDefinition(), context, ImportGenericKind.Definition); - var instance = new GenericInstanceMethod(element_method); - var arguments = method.GetGenericArguments(); - var instance_arguments = instance.GenericArguments; - - context.Push(element_method); - try - { - for (int i = 0; i < arguments.Length; i++) - instance_arguments.Add(ImportType(arguments[i], context)); - - return instance; - } - finally - { - context.Pop(); - } - } - - static bool HasCallingConvention(SR.MethodBase method, SR.CallingConventions conventions) - { - return (method.CallingConvention & conventions) != 0; - } - - public virtual TypeReference ImportReference(Type type, IGenericParameterProvider context) - { - Mixin.CheckType(type); - return ImportType( - type, - ImportGenericContext.For(context), - context != null ? ImportGenericKind.Open : ImportGenericKind.Definition); - } - - public virtual FieldReference ImportReference(SR.FieldInfo field, IGenericParameterProvider context) - { - Mixin.CheckField(field); - return ImportField(field, ImportGenericContext.For(context)); - } - - public virtual MethodReference ImportReference(SR.MethodBase method, IGenericParameterProvider context) - { - Mixin.CheckMethod(method); - return ImportMethod(method, - ImportGenericContext.For(context), - context != null ? ImportGenericKind.Open : ImportGenericKind.Definition); - } - } - - public class DefaultMetadataImporter : IMetadataImporter - { - - readonly protected ModuleDefinition module; - - public DefaultMetadataImporter(ModuleDefinition module) - { - Mixin.CheckModule(module); - - this.module = module; - } - - TypeReference ImportType(TypeReference type, ImportGenericContext context) - { - if (type.IsTypeSpecification()) - return ImportTypeSpecification(type, context); - - var reference = new TypeReference( - type.Namespace, - type.Name, - module, - ImportScope(type), - type.IsValueType); - - MetadataSystem.TryProcessPrimitiveTypeReference(reference); - - if (type.IsNested) - reference.DeclaringType = ImportType(type.DeclaringType, context); - - if (type.HasGenericParameters) - ImportGenericParameters(reference, type); - - return reference; - } - - protected virtual IMetadataScope ImportScope(TypeReference type) - { - return ImportScope(type.Scope); - } - - protected IMetadataScope ImportScope(IMetadataScope scope) - { - switch (scope.MetadataScopeType) - { - case MetadataScopeType.AssemblyNameReference: - return ImportReference((AssemblyNameReference)scope); - case MetadataScopeType.ModuleDefinition: - if (scope == module) return scope; - return ImportReference(((ModuleDefinition)scope).Assembly.Name); - case MetadataScopeType.ModuleReference: - throw new NotImplementedException(); - } - - throw new NotSupportedException(); - } - - public virtual AssemblyNameReference ImportReference(AssemblyNameReference name) - { - Mixin.CheckName(name); - - AssemblyNameReference reference; - if (module.TryGetAssemblyNameReference(name, out reference)) - return reference; - - reference = new AssemblyNameReference(name.Name, name.Version) - { - Culture = name.Culture, - HashAlgorithm = name.HashAlgorithm, - IsRetargetable = name.IsRetargetable, - IsWindowsRuntime = name.IsWindowsRuntime, - }; - - var pk_token = !name.PublicKeyToken.IsNullOrEmpty() - ? new byte[name.PublicKeyToken.Length] - : Empty.Array; - - if (pk_token.Length > 0) - Buffer.BlockCopy(name.PublicKeyToken, 0, pk_token, 0, pk_token.Length); - - reference.PublicKeyToken = pk_token; - - //Only add if not self. - if (CanAddAssemblyNameReference(module, reference)) - module.AssemblyReferences.Add(reference); - - return reference; - } - - private bool CanAddAssemblyNameReference(ModuleDefinition module, AssemblyNameReference nameRef) - { - return true; - //return (module.assembly.FullName != nameRef.FullName); - } - - static void ImportGenericParameters(IGenericParameterProvider imported, IGenericParameterProvider original) - { - var parameters = original.GenericParameters; - var imported_parameters = imported.GenericParameters; - - for (int i = 0; i < parameters.Count; i++) - imported_parameters.Add(new GenericParameter(parameters[i].Name, imported)); - } - - TypeReference ImportTypeSpecification(TypeReference type, ImportGenericContext context) - { - switch (type.etype) - { - case ElementType.SzArray: - var vector = (ArrayType)type; - return new ArrayType(ImportType(vector.ElementType, context)); - case ElementType.Ptr: - var pointer = (PointerType)type; - return new PointerType(ImportType(pointer.ElementType, context)); - case ElementType.ByRef: - var byref = (ByReferenceType)type; - return new ByReferenceType(ImportType(byref.ElementType, context)); - case ElementType.Pinned: - var pinned = (PinnedType)type; - return new PinnedType(ImportType(pinned.ElementType, context)); - case ElementType.Sentinel: - var sentinel = (SentinelType)type; - return new SentinelType(ImportType(sentinel.ElementType, context)); - case ElementType.FnPtr: - var fnptr = (FunctionPointerType)type; - var imported_fnptr = new FunctionPointerType() - { - HasThis = fnptr.HasThis, - ExplicitThis = fnptr.ExplicitThis, - CallingConvention = fnptr.CallingConvention, - ReturnType = ImportType(fnptr.ReturnType, context), - }; - - if (!fnptr.HasParameters) - return imported_fnptr; - - for (int i = 0; i < fnptr.Parameters.Count; i++) - imported_fnptr.Parameters.Add(new ParameterDefinition( - ImportType(fnptr.Parameters[i].ParameterType, context))); - - return imported_fnptr; - case ElementType.CModOpt: - var modopt = (OptionalModifierType)type; - return new OptionalModifierType( - ImportType(modopt.ModifierType, context), - ImportType(modopt.ElementType, context)); - case ElementType.CModReqD: - var modreq = (RequiredModifierType)type; - return new RequiredModifierType( - ImportType(modreq.ModifierType, context), - ImportType(modreq.ElementType, context)); - case ElementType.Array: - var array = (ArrayType)type; - var imported_array = new ArrayType(ImportType(array.ElementType, context)); - if (array.IsVector) - return imported_array; - - var dimensions = array.Dimensions; - var imported_dimensions = imported_array.Dimensions; - - imported_dimensions.Clear(); - - for (int i = 0; i < dimensions.Count; i++) - { - var dimension = dimensions[i]; - - imported_dimensions.Add(new ArrayDimension(dimension.LowerBound, dimension.UpperBound)); - } - - return imported_array; - case ElementType.GenericInst: - var instance = (GenericInstanceType)type; - var element_type = ImportType(instance.ElementType, context); - var arguments = instance.GenericArguments; - var imported_instance = new GenericInstanceType(element_type, arguments.Count); - var imported_arguments = imported_instance.GenericArguments; - - for (int i = 0; i < arguments.Count; i++) - imported_arguments.Add(ImportType(arguments[i], context)); - - return imported_instance; - case ElementType.Var: - var var_parameter = (GenericParameter)type; - if (var_parameter.DeclaringType == null) - throw new InvalidOperationException(); - return context.TypeParameter(var_parameter.DeclaringType.FullName, var_parameter.Position); - case ElementType.MVar: - var mvar_parameter = (GenericParameter)type; - if (mvar_parameter.DeclaringMethod == null) - throw new InvalidOperationException(); - return context.MethodParameter(context.NormalizeMethodName(mvar_parameter.DeclaringMethod), mvar_parameter.Position); - } - - throw new NotSupportedException(type.etype.ToString()); - } - - FieldReference ImportField(FieldReference field, ImportGenericContext context) - { - var declaring_type = ImportType(field.DeclaringType, context); - - context.Push(declaring_type); - try - { - return new FieldReference - { - Name = field.Name, - DeclaringType = declaring_type, - FieldType = ImportType(field.FieldType, context), - }; - } - finally - { - context.Pop(); - } - } - - MethodReference ImportMethod(MethodReference method, ImportGenericContext context) - { - if (method.IsGenericInstance) - return ImportMethodSpecification(method, context); - - var declaring_type = ImportType(method.DeclaringType, context); - - var reference = new MethodReference - { - Name = method.Name, - HasThis = method.HasThis, - ExplicitThis = method.ExplicitThis, - DeclaringType = declaring_type, - CallingConvention = method.CallingConvention, - }; - - if (method.HasGenericParameters) - ImportGenericParameters(reference, method); - - context.Push(reference); - try - { - reference.ReturnType = ImportType(method.ReturnType, context); - - if (!method.HasParameters) - return reference; - - var parameters = method.Parameters; - var reference_parameters = reference.parameters = new ParameterDefinitionCollection(reference, parameters.Count); - for (int i = 0; i < parameters.Count; i++) - reference_parameters.Add( - new ParameterDefinition(ImportType(parameters[i].ParameterType, context))); - - return reference; - } - finally - { - context.Pop(); - } - } - - MethodSpecification ImportMethodSpecification(MethodReference method, ImportGenericContext context) - { - if (!method.IsGenericInstance) - throw new NotSupportedException(); - - var instance = (GenericInstanceMethod)method; - var element_method = ImportMethod(instance.ElementMethod, context); - var imported_instance = new GenericInstanceMethod(element_method); - - var arguments = instance.GenericArguments; - var imported_arguments = imported_instance.GenericArguments; - - for (int i = 0; i < arguments.Count; i++) - imported_arguments.Add(ImportType(arguments[i], context)); - - return imported_instance; - } - - public virtual TypeReference ImportReference(TypeReference type, IGenericParameterProvider context) - { - Mixin.CheckType(type); - return ImportType(type, ImportGenericContext.For(context)); - } - - public virtual FieldReference ImportReference(FieldReference field, IGenericParameterProvider context) - { - Mixin.CheckField(field); - return ImportField(field, ImportGenericContext.For(context)); - } - - public virtual MethodReference ImportReference(MethodReference method, IGenericParameterProvider context) - { - Mixin.CheckMethod(method); - return ImportMethod(method, ImportGenericContext.For(context)); - } - } - - static partial class Mixin - { - - public static void CheckModule(ModuleDefinition module) - { - if (module == null) - throw new ArgumentNullException(Argument.module.ToString()); - } - - public static bool TryGetAssemblyNameReference(this ModuleDefinition module, AssemblyNameReference name_reference, out AssemblyNameReference assembly_reference) - { - var references = module.AssemblyReferences; - - for (int i = 0; i < references.Count; i++) - { - var reference = references[i]; - if (!Equals(name_reference, reference)) - continue; - - assembly_reference = reference; - return true; - } - - assembly_reference = null; - return false; - } - - static bool Equals(byte[] a, byte[] b) - { - if (ReferenceEquals(a, b)) - return true; - if (a == null) - return false; - if (a.Length != b.Length) - return false; - for (int i = 0; i < a.Length; i++) - if (a[i] != b[i]) - return false; - return true; - } - - static bool Equals(T a, T b) where T : class, IEquatable - { - if (ReferenceEquals(a, b)) - return true; - if (a == null) - return false; - return a.Equals(b); - } - - static bool Equals(AssemblyNameReference a, AssemblyNameReference b) - { - if (ReferenceEquals(a, b)) - return true; - if (a.Name != b.Name) - return false; - if (!Equals(a.Version, b.Version)) - return false; - if (a.Culture != b.Culture) - return false; - if (!Equals(a.PublicKeyToken, b.PublicKeyToken)) - return false; - return true; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Import.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Import.cs.meta deleted file mode 100644 index f898f90..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Import.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fa57d261f1a90c746abaef3d59b4c655 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/LinkedResource.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/LinkedResource.cs deleted file mode 100644 index 392ffdb..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/LinkedResource.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public sealed class LinkedResource : Resource { - - internal byte [] hash; - string file; - - public byte [] Hash { - get { return hash; } - } - - public string File { - get { return file; } - set { file = value; } - } - - public override ResourceType ResourceType { - get { return ResourceType.Linked; } - } - - public LinkedResource (string name, ManifestResourceAttributes flags) - : base (name, flags) - { - } - - public LinkedResource (string name, ManifestResourceAttributes flags, string file) - : base (name, flags) - { - this.file = file; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/LinkedResource.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/LinkedResource.cs.meta deleted file mode 100644 index 531db4c..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/LinkedResource.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 18c45c1a0891fdc40a07d309b564ec6d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ManifestResourceAttributes.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ManifestResourceAttributes.cs deleted file mode 100644 index 693004c..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ManifestResourceAttributes.cs +++ /dev/null @@ -1,21 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - [Flags] - public enum ManifestResourceAttributes : uint { - VisibilityMask = 0x0007, - Public = 0x0001, // The resource is exported from the Assembly - Private = 0x0002 // The resource is private to the Assembly - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ManifestResourceAttributes.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ManifestResourceAttributes.cs.meta deleted file mode 100644 index a88aad4..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ManifestResourceAttributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 136b98b695702f048857ea31d91193fc -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MarshalInfo.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MarshalInfo.cs deleted file mode 100644 index e93d1ef..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MarshalInfo.cs +++ /dev/null @@ -1,153 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - public class MarshalInfo { - - internal NativeType native; - - public NativeType NativeType { - get { return native; } - set { native = value; } - } - - public MarshalInfo (NativeType native) - { - this.native = native; - } - } - - public sealed class ArrayMarshalInfo : MarshalInfo { - - internal NativeType element_type; - internal int size_parameter_index; - internal int size; - internal int size_parameter_multiplier; - - public NativeType ElementType { - get { return element_type; } - set { element_type = value; } - } - - public int SizeParameterIndex { - get { return size_parameter_index; } - set { size_parameter_index = value; } - } - - public int Size { - get { return size; } - set { size = value; } - } - - public int SizeParameterMultiplier { - get { return size_parameter_multiplier; } - set { size_parameter_multiplier = value; } - } - - public ArrayMarshalInfo () - : base (NativeType.Array) - { - element_type = NativeType.None; - size_parameter_index = -1; - size = -1; - size_parameter_multiplier = -1; - } - } - - public sealed class CustomMarshalInfo : MarshalInfo { - - internal Guid guid; - internal string unmanaged_type; - internal TypeReference managed_type; - internal string cookie; - - public Guid Guid { - get { return guid; } - set { guid = value; } - } - - public string UnmanagedType { - get { return unmanaged_type; } - set { unmanaged_type = value; } - } - - public TypeReference ManagedType { - get { return managed_type; } - set { managed_type = value; } - } - - public string Cookie { - get { return cookie; } - set { cookie = value; } - } - - public CustomMarshalInfo () - : base (NativeType.CustomMarshaler) - { - } - } - - public sealed class SafeArrayMarshalInfo : MarshalInfo { - - internal VariantType element_type; - - public VariantType ElementType { - get { return element_type; } - set { element_type = value; } - } - - public SafeArrayMarshalInfo () - : base (NativeType.SafeArray) - { - element_type = VariantType.None; - } - } - - public sealed class FixedArrayMarshalInfo : MarshalInfo { - - internal NativeType element_type; - internal int size; - - public NativeType ElementType { - get { return element_type; } - set { element_type = value; } - } - - public int Size { - get { return size; } - set { size = value; } - } - - public FixedArrayMarshalInfo () - : base (NativeType.FixedArray) - { - element_type = NativeType.None; - } - } - - public sealed class FixedSysStringMarshalInfo : MarshalInfo { - - internal int size; - - public int Size { - get { return size; } - set { size = value; } - } - - public FixedSysStringMarshalInfo () - : base (NativeType.FixedSysString) - { - size = -1; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MarshalInfo.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MarshalInfo.cs.meta deleted file mode 100644 index 1a110e3..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MarshalInfo.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 081d03dc18ced1648ae4d9f2eefd3370 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberDefinitionCollection.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberDefinitionCollection.cs deleted file mode 100644 index 172d349..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberDefinitionCollection.cs +++ /dev/null @@ -1,73 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; - -namespace MonoFN.Cecil { - - sealed class MemberDefinitionCollection : Collection where T : IMemberDefinition { - - TypeDefinition container; - - internal MemberDefinitionCollection (TypeDefinition container) - { - this.container = container; - } - - internal MemberDefinitionCollection (TypeDefinition container, int capacity) - : base (capacity) - { - this.container = container; - } - - protected override void OnAdd (T item, int index) - { - Attach (item); - } - - protected sealed override void OnSet (T item, int index) - { - Attach (item); - } - - protected sealed override void OnInsert (T item, int index) - { - Attach (item); - } - - protected sealed override void OnRemove (T item, int index) - { - Detach (item); - } - - protected sealed override void OnClear () - { - foreach (var definition in this) - Detach (definition); - } - - void Attach (T element) - { - if (element.DeclaringType == container) - return; - - if (element.DeclaringType != null) - throw new ArgumentException ("Member already attached"); - - element.DeclaringType = this.container; - } - - static void Detach (T element) - { - element.DeclaringType = null; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberDefinitionCollection.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberDefinitionCollection.cs.meta deleted file mode 100644 index 6684de2..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberDefinitionCollection.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e5caa999f42a585459c62b7b65eefdd8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberReference.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberReference.cs deleted file mode 100644 index 4f75843..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberReference.cs +++ /dev/null @@ -1,102 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - public abstract class MemberReference : IMetadataTokenProvider { - - string name; - TypeReference declaring_type; - - internal MetadataToken token; - internal object projection; - - public virtual string Name { - get { return name; } - set { - if (IsWindowsRuntimeProjection && value != name) - throw new InvalidOperationException (); - - name = value; - } - } - - public abstract string FullName { - get; - } - - public virtual TypeReference DeclaringType { - get { return declaring_type; } - set { declaring_type = value; } - } - - public MetadataToken MetadataToken { - get { return token; } - set { token = value; } - } - - public bool IsWindowsRuntimeProjection { - get { return projection != null; } - } - - internal bool HasImage { - get { - var module = Module; - if (module == null) - return false; - - return module.HasImage; - } - } - - public virtual ModuleDefinition Module { - get { return declaring_type != null ? declaring_type.Module : null; } - } - - public virtual bool IsDefinition { - get { return false; } - } - - public virtual bool ContainsGenericParameter { - get { return declaring_type != null && declaring_type.ContainsGenericParameter; } - } - - internal MemberReference () - { - } - - internal MemberReference (string name) - { - this.name = name ?? string.Empty; - } - - internal string MemberFullName () - { - if (declaring_type == null) - return name; - - return declaring_type.FullName + "::" + name; - } - - public IMemberDefinition Resolve () - { - return ResolveDefinition (); - } - - protected abstract IMemberDefinition ResolveDefinition (); - - public override string ToString () - { - return FullName; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberReference.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberReference.cs.meta deleted file mode 100644 index c3d8f54..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MemberReference.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2dcf551ad731c204fa148ec1ee0ce881 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataResolver.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataResolver.cs deleted file mode 100644 index ce212e4..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataResolver.cs +++ /dev/null @@ -1,391 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; - -namespace MonoFN.Cecil { - - public interface IAssemblyResolver : IDisposable { - AssemblyDefinition Resolve (AssemblyNameReference name); - AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters); - } - - public interface IMetadataResolver { - TypeDefinition Resolve (TypeReference type); - FieldDefinition Resolve (FieldReference field); - MethodDefinition Resolve (MethodReference method); - } - -#if !NET_CORE - [Serializable] -#endif - public sealed class ResolutionException : Exception { - - readonly MemberReference member; - - public MemberReference Member { - get { return member; } - } - - public IMetadataScope Scope { - get { - var type = member as TypeReference; - if (type != null) - return type.Scope; - - var declaring_type = member.DeclaringType; - if (declaring_type != null) - return declaring_type.Scope; - - throw new NotSupportedException (); - } - } - - public ResolutionException (MemberReference member) - : base ("Failed to resolve " + member.FullName) - { - if (member == null) - throw new ArgumentNullException ("member"); - - this.member = member; - } - - public ResolutionException (MemberReference member, Exception innerException) - : base ("Failed to resolve " + member.FullName, innerException) - { - if (member == null) - throw new ArgumentNullException ("member"); - - this.member = member; - } - -#if !NET_CORE - ResolutionException ( - System.Runtime.Serialization.SerializationInfo info, - System.Runtime.Serialization.StreamingContext context) - : base (info, context) - { - } -#endif - } - - public class MetadataResolver : IMetadataResolver { - - readonly IAssemblyResolver assembly_resolver; - - public IAssemblyResolver AssemblyResolver { - get { return assembly_resolver; } - } - - public MetadataResolver (IAssemblyResolver assemblyResolver) - { - if (assemblyResolver == null) - throw new ArgumentNullException ("assemblyResolver"); - - assembly_resolver = assemblyResolver; - } - - public virtual TypeDefinition Resolve (TypeReference type) - { - Mixin.CheckType (type); - - type = type.GetElementType (); - - var scope = type.Scope; - - if (scope == null) - return null; - - switch (scope.MetadataScopeType) { - case MetadataScopeType.AssemblyNameReference: - var assembly = assembly_resolver.Resolve ((AssemblyNameReference)scope); - if (assembly == null) - return null; - - return GetType (assembly.MainModule, type); - case MetadataScopeType.ModuleDefinition: - return GetType ((ModuleDefinition)scope, type); - case MetadataScopeType.ModuleReference: - if (type.Module.Assembly == null) - return null; - - var modules = type.Module.Assembly.Modules; - var module_ref = (ModuleReference)scope; - for (int i = 0; i < modules.Count; i++) { - var netmodule = modules [i]; - if (netmodule.Name == module_ref.Name) - return GetType (netmodule, type); - } - break; - } - - throw new NotSupportedException (); - } - - static TypeDefinition GetType (ModuleDefinition module, TypeReference reference) - { - var type = GetTypeDefinition (module, reference); - if (type != null) - return type; - - if (!module.HasExportedTypes) - return null; - - var exported_types = module.ExportedTypes; - - for (int i = 0; i < exported_types.Count; i++) { - var exported_type = exported_types [i]; - if (exported_type.Name != reference.Name) - continue; - - if (exported_type.Namespace != reference.Namespace) - continue; - - return exported_type.Resolve (); - } - - return null; - } - - static TypeDefinition GetTypeDefinition (ModuleDefinition module, TypeReference type) - { - if (!type.IsNested) - return module.GetType (type.Namespace, type.Name); - - var declaring_type = type.DeclaringType.Resolve (); - if (declaring_type == null) - return null; - - return declaring_type.GetNestedType (type.TypeFullName ()); - } - - public virtual FieldDefinition Resolve (FieldReference field) - { - Mixin.CheckField (field); - - var type = Resolve (field.DeclaringType); - if (type == null) - return null; - - if (!type.HasFields) - return null; - - return GetField (type, field); - } - - FieldDefinition GetField (TypeDefinition type, FieldReference reference) - { - while (type != null) { - var field = GetField (type.Fields, reference); - if (field != null) - return field; - - if (type.BaseType == null) - return null; - - type = Resolve (type.BaseType); - } - - return null; - } - - static FieldDefinition GetField (Collection fields, FieldReference reference) - { - for (int i = 0; i < fields.Count; i++) { - var field = fields [i]; - - if (field.Name != reference.Name) - continue; - - if (!AreSame (field.FieldType, reference.FieldType)) - continue; - - return field; - } - - return null; - } - - public virtual MethodDefinition Resolve (MethodReference method) - { - Mixin.CheckMethod (method); - - var type = Resolve (method.DeclaringType); - if (type == null) - return null; - - method = method.GetElementMethod (); - - if (!type.HasMethods) - return null; - - return GetMethod (type, method); - } - - MethodDefinition GetMethod (TypeDefinition type, MethodReference reference) - { - while (type != null) { - var method = GetMethod (type.Methods, reference); - if (method != null) - return method; - - if (type.BaseType == null) - return null; - - type = Resolve (type.BaseType); - } - - return null; - } - - public static MethodDefinition GetMethod (Collection methods, MethodReference reference) - { - for (int i = 0; i < methods.Count; i++) { - var method = methods [i]; - - if (method.Name != reference.Name) - continue; - - if (method.HasGenericParameters != reference.HasGenericParameters) - continue; - - if (method.HasGenericParameters && method.GenericParameters.Count != reference.GenericParameters.Count) - continue; - - if (!AreSame (method.ReturnType, reference.ReturnType)) - continue; - - if (method.IsVarArg () != reference.IsVarArg ()) - continue; - - if (method.IsVarArg () && IsVarArgCallTo (method, reference)) - return method; - - if (method.HasParameters != reference.HasParameters) - continue; - - if (!method.HasParameters && !reference.HasParameters) - return method; - - if (!AreSame (method.Parameters, reference.Parameters)) - continue; - - return method; - } - - return null; - } - - static bool AreSame (Collection a, Collection b) - { - var count = a.Count; - - if (count != b.Count) - return false; - - if (count == 0) - return true; - - for (int i = 0; i < count; i++) - if (!AreSame (a [i].ParameterType, b [i].ParameterType)) - return false; - - return true; - } - - static bool IsVarArgCallTo (MethodDefinition method, MethodReference reference) - { - if (method.Parameters.Count >= reference.Parameters.Count) - return false; - - if (reference.GetSentinelPosition () != method.Parameters.Count) - return false; - - for (int i = 0; i < method.Parameters.Count; i++) - if (!AreSame (method.Parameters [i].ParameterType, reference.Parameters [i].ParameterType)) - return false; - - return true; - } - - static bool AreSame (TypeSpecification a, TypeSpecification b) - { - if (!AreSame (a.ElementType, b.ElementType)) - return false; - - if (a.IsGenericInstance) - return AreSame ((GenericInstanceType)a, (GenericInstanceType)b); - - if (a.IsRequiredModifier || a.IsOptionalModifier) - return AreSame ((IModifierType)a, (IModifierType)b); - - if (a.IsArray) - return AreSame ((ArrayType)a, (ArrayType)b); - - return true; - } - - static bool AreSame (ArrayType a, ArrayType b) - { - if (a.Rank != b.Rank) - return false; - - // TODO: dimensions - - return true; - } - - static bool AreSame (IModifierType a, IModifierType b) - { - return AreSame (a.ModifierType, b.ModifierType); - } - - static bool AreSame (GenericInstanceType a, GenericInstanceType b) - { - if (a.GenericArguments.Count != b.GenericArguments.Count) - return false; - - for (int i = 0; i < a.GenericArguments.Count; i++) - if (!AreSame (a.GenericArguments [i], b.GenericArguments [i])) - return false; - - return true; - } - - static bool AreSame (GenericParameter a, GenericParameter b) - { - return a.Position == b.Position; - } - - static bool AreSame (TypeReference a, TypeReference b) - { - if (ReferenceEquals (a, b)) - return true; - - if (a == null || b == null) - return false; - - if (a.etype != b.etype) - return false; - - if (a.IsGenericParameter) - return AreSame ((GenericParameter)a, (GenericParameter)b); - - if (a.IsTypeSpecification ()) - return AreSame ((TypeSpecification)a, (TypeSpecification)b); - - if (a.Name != b.Name || a.Namespace != b.Namespace) - return false; - - return AreSame (a.DeclaringType, b.DeclaringType); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataResolver.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataResolver.cs.meta deleted file mode 100644 index 9a42f6b..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataResolver.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fdd2c926d773ffd4692e2d042135fd2b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataSystem.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataSystem.cs deleted file mode 100644 index 00ef319..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataSystem.cs +++ /dev/null @@ -1,431 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Cil; -using MonoFN.Cecil.Metadata; -using MonoFN.Collections.Generic; -using System; -using System.Collections.Generic; -using System.Threading; - -namespace MonoFN.Cecil { - - struct Range { - public uint Start; - public uint Length; - - public Range (uint index, uint length) - { - this.Start = index; - this.Length = length; - } - } - - sealed class MetadataSystem { - - internal AssemblyNameReference [] AssemblyReferences; - internal ModuleReference [] ModuleReferences; - - internal TypeDefinition [] Types; - internal TypeReference [] TypeReferences; - - internal FieldDefinition [] Fields; - internal MethodDefinition [] Methods; - internal MemberReference [] MemberReferences; - - internal Dictionary> NestedTypes; - internal Dictionary ReverseNestedTypes; - internal Dictionary>> Interfaces; - internal Dictionary> ClassLayouts; - internal Dictionary FieldLayouts; - internal Dictionary FieldRVAs; - internal Dictionary FieldMarshals; - internal Dictionary> Constants; - internal Dictionary> Overrides; - internal Dictionary CustomAttributes; - internal Dictionary SecurityDeclarations; - internal Dictionary Events; - internal Dictionary Properties; - internal Dictionary> Semantics; - internal Dictionary> PInvokes; - internal Dictionary GenericParameters; - internal Dictionary>> GenericConstraints; - - internal Document [] Documents; - internal Dictionary>> LocalScopes; - internal ImportDebugInformation [] ImportScopes; - internal Dictionary StateMachineMethods; - internal Dictionary []> CustomDebugInformations; - - static Dictionary> primitive_value_types; - - static void InitializePrimitives () - { - var types = new Dictionary> (18, StringComparer.Ordinal) { - { "Void", new Row (ElementType.Void, false) }, - { "Boolean", new Row (ElementType.Boolean, true) }, - { "Char", new Row (ElementType.Char, true) }, - { "SByte", new Row (ElementType.I1, true) }, - { "Byte", new Row (ElementType.U1, true) }, - { "Int16", new Row (ElementType.I2, true) }, - { "UInt16", new Row (ElementType.U2, true) }, - { "Int32", new Row (ElementType.I4, true) }, - { "UInt32", new Row (ElementType.U4, true) }, - { "Int64", new Row (ElementType.I8, true) }, - { "UInt64", new Row (ElementType.U8, true) }, - { "Single", new Row (ElementType.R4, true) }, - { "Double", new Row (ElementType.R8, true) }, - { "String", new Row (ElementType.String, false) }, - { "TypedReference", new Row (ElementType.TypedByRef, false) }, - { "IntPtr", new Row (ElementType.I, true) }, - { "UIntPtr", new Row (ElementType.U, true) }, - { "Object", new Row (ElementType.Object, false) }, - }; - - Interlocked.CompareExchange (ref primitive_value_types, types, null); - } - - public static void TryProcessPrimitiveTypeReference (TypeReference type) - { - if (type.Namespace != "System") - return; - - var scope = type.scope; - if (scope == null || scope.MetadataScopeType != MetadataScopeType.AssemblyNameReference) - return; - - Row primitive_data; - if (!TryGetPrimitiveData (type, out primitive_data)) - return; - - type.etype = primitive_data.Col1; - type.IsValueType = primitive_data.Col2; - } - - public static bool TryGetPrimitiveElementType (TypeDefinition type, out ElementType etype) - { - etype = ElementType.None; - - if (type.Namespace != "System") - return false; - - Row primitive_data; - if (TryGetPrimitiveData (type, out primitive_data)) { - etype = primitive_data.Col1; - return true; - } - - return false; - } - - static bool TryGetPrimitiveData (TypeReference type, out Row primitive_data) - { - if (primitive_value_types == null) - InitializePrimitives (); - - return primitive_value_types.TryGetValue (type.Name, out primitive_data); - } - - public void Clear () - { - if (NestedTypes != null) NestedTypes = new Dictionary> (capacity: 0); - if (ReverseNestedTypes != null) ReverseNestedTypes = new Dictionary (capacity: 0); - if (Interfaces != null) Interfaces = new Dictionary>> (capacity: 0); - if (ClassLayouts != null) ClassLayouts = new Dictionary> (capacity: 0); - if (FieldLayouts != null) FieldLayouts = new Dictionary (capacity: 0); - if (FieldRVAs != null) FieldRVAs = new Dictionary (capacity: 0); - if (FieldMarshals != null) FieldMarshals = new Dictionary (capacity: 0); - if (Constants != null) Constants = new Dictionary> (capacity: 0); - if (Overrides != null) Overrides = new Dictionary> (capacity: 0); - if (CustomAttributes != null) CustomAttributes = new Dictionary (capacity: 0); - if (SecurityDeclarations != null) SecurityDeclarations = new Dictionary (capacity: 0); - if (Events != null) Events = new Dictionary (capacity: 0); - if (Properties != null) Properties = new Dictionary (capacity: 0); - if (Semantics != null) Semantics = new Dictionary> (capacity: 0); - if (PInvokes != null) PInvokes = new Dictionary> (capacity: 0); - if (GenericParameters != null) GenericParameters = new Dictionary (capacity: 0); - if (GenericConstraints != null) GenericConstraints = new Dictionary>> (capacity: 0); - - Documents = Empty.Array; - ImportScopes = Empty.Array; - if (LocalScopes != null) LocalScopes = new Dictionary>> (capacity: 0); - if (StateMachineMethods != null) StateMachineMethods = new Dictionary (capacity: 0); - } - - public AssemblyNameReference GetAssemblyNameReference (uint rid) - { - if (rid < 1 || rid > AssemblyReferences.Length) - return null; - - return AssemblyReferences [rid - 1]; - } - - public TypeDefinition GetTypeDefinition (uint rid) - { - if (rid < 1 || rid > Types.Length) - return null; - - return Types [rid - 1]; - } - - public void AddTypeDefinition (TypeDefinition type) - { - Types [type.token.RID - 1] = type; - } - - public TypeReference GetTypeReference (uint rid) - { - if (rid < 1 || rid > TypeReferences.Length) - return null; - - return TypeReferences [rid - 1]; - } - - public void AddTypeReference (TypeReference type) - { - TypeReferences [type.token.RID - 1] = type; - } - - public FieldDefinition GetFieldDefinition (uint rid) - { - if (rid < 1 || rid > Fields.Length) - return null; - - return Fields [rid - 1]; - } - - public void AddFieldDefinition (FieldDefinition field) - { - Fields [field.token.RID - 1] = field; - } - - public MethodDefinition GetMethodDefinition (uint rid) - { - if (rid < 1 || rid > Methods.Length) - return null; - - return Methods [rid - 1]; - } - - public void AddMethodDefinition (MethodDefinition method) - { - Methods [method.token.RID - 1] = method; - } - - public MemberReference GetMemberReference (uint rid) - { - if (rid < 1 || rid > MemberReferences.Length) - return null; - - return MemberReferences [rid - 1]; - } - - public void AddMemberReference (MemberReference member) - { - MemberReferences [member.token.RID - 1] = member; - } - - public bool TryGetNestedTypeMapping (TypeDefinition type, out Collection mapping) - { - return NestedTypes.TryGetValue (type.token.RID, out mapping); - } - - public void SetNestedTypeMapping (uint type_rid, Collection mapping) - { - NestedTypes [type_rid] = mapping; - } - - public void RemoveNestedTypeMapping (TypeDefinition type) - { - NestedTypes.Remove (type.token.RID); - } - - public bool TryGetReverseNestedTypeMapping (TypeDefinition type, out uint declaring) - { - return ReverseNestedTypes.TryGetValue (type.token.RID, out declaring); - } - - public void SetReverseNestedTypeMapping (uint nested, uint declaring) - { - ReverseNestedTypes [nested] = declaring; - } - - public void RemoveReverseNestedTypeMapping (TypeDefinition type) - { - ReverseNestedTypes.Remove (type.token.RID); - } - - public bool TryGetInterfaceMapping (TypeDefinition type, out Collection> mapping) - { - return Interfaces.TryGetValue (type.token.RID, out mapping); - } - - public void SetInterfaceMapping (uint type_rid, Collection> mapping) - { - Interfaces [type_rid] = mapping; - } - - public void RemoveInterfaceMapping (TypeDefinition type) - { - Interfaces.Remove (type.token.RID); - } - - public void AddPropertiesRange (uint type_rid, Range range) - { - Properties.Add (type_rid, range); - } - - public bool TryGetPropertiesRange (TypeDefinition type, out Range range) - { - return Properties.TryGetValue (type.token.RID, out range); - } - - public void RemovePropertiesRange (TypeDefinition type) - { - Properties.Remove (type.token.RID); - } - - public void AddEventsRange (uint type_rid, Range range) - { - Events.Add (type_rid, range); - } - - public bool TryGetEventsRange (TypeDefinition type, out Range range) - { - return Events.TryGetValue (type.token.RID, out range); - } - - public void RemoveEventsRange (TypeDefinition type) - { - Events.Remove (type.token.RID); - } - - public bool TryGetGenericParameterRanges (IGenericParameterProvider owner, out Range [] ranges) - { - return GenericParameters.TryGetValue (owner.MetadataToken, out ranges); - } - - public void RemoveGenericParameterRange (IGenericParameterProvider owner) - { - GenericParameters.Remove (owner.MetadataToken); - } - - public bool TryGetCustomAttributeRanges (ICustomAttributeProvider owner, out Range [] ranges) - { - return CustomAttributes.TryGetValue (owner.MetadataToken, out ranges); - } - - public void RemoveCustomAttributeRange (ICustomAttributeProvider owner) - { - CustomAttributes.Remove (owner.MetadataToken); - } - - public bool TryGetSecurityDeclarationRanges (ISecurityDeclarationProvider owner, out Range [] ranges) - { - return SecurityDeclarations.TryGetValue (owner.MetadataToken, out ranges); - } - - public void RemoveSecurityDeclarationRange (ISecurityDeclarationProvider owner) - { - SecurityDeclarations.Remove (owner.MetadataToken); - } - - public bool TryGetGenericConstraintMapping (GenericParameter generic_parameter, out Collection> mapping) - { - return GenericConstraints.TryGetValue (generic_parameter.token.RID, out mapping); - } - - public void SetGenericConstraintMapping (uint gp_rid, Collection> mapping) - { - GenericConstraints [gp_rid] = mapping; - } - - public void RemoveGenericConstraintMapping (GenericParameter generic_parameter) - { - GenericConstraints.Remove (generic_parameter.token.RID); - } - - public bool TryGetOverrideMapping (MethodDefinition method, out Collection mapping) - { - return Overrides.TryGetValue (method.token.RID, out mapping); - } - - public void SetOverrideMapping (uint rid, Collection mapping) - { - Overrides [rid] = mapping; - } - - public void RemoveOverrideMapping (MethodDefinition method) - { - Overrides.Remove (method.token.RID); - } - - public Document GetDocument (uint rid) - { - if (rid < 1 || rid > Documents.Length) - return null; - - return Documents [rid - 1]; - } - - public bool TryGetLocalScopes (MethodDefinition method, out Collection> scopes) - { - return LocalScopes.TryGetValue (method.MetadataToken.RID, out scopes); - } - - public void SetLocalScopes (uint method_rid, Collection> records) - { - LocalScopes [method_rid] = records; - } - - public ImportDebugInformation GetImportScope (uint rid) - { - if (rid < 1 || rid > ImportScopes.Length) - return null; - - return ImportScopes [rid - 1]; - } - - public bool TryGetStateMachineKickOffMethod (MethodDefinition method, out uint rid) - { - return StateMachineMethods.TryGetValue (method.MetadataToken.RID, out rid); - } - - public TypeDefinition GetFieldDeclaringType (uint field_rid) - { - return BinaryRangeSearch (Types, field_rid, true); - } - - public TypeDefinition GetMethodDeclaringType (uint method_rid) - { - return BinaryRangeSearch (Types, method_rid, false); - } - - static TypeDefinition BinaryRangeSearch (TypeDefinition [] types, uint rid, bool field) - { - int min = 0; - int max = types.Length - 1; - while (min <= max) { - int mid = min + ((max - min) / 2); - var type = types [mid]; - var range = field ? type.fields_range : type.methods_range; - - if (rid < range.Start) - max = mid - 1; - else if (rid >= range.Start + range.Length) - min = mid + 1; - else - return type; - } - - return null; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataSystem.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataSystem.cs.meta deleted file mode 100644 index 46912ce..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MetadataSystem.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6ea39c5122499d14fbca126d3ed39890 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodAttributes.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodAttributes.cs deleted file mode 100644 index 043e77a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodAttributes.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - [Flags] - public enum MethodAttributes : ushort { - MemberAccessMask = 0x0007, - CompilerControlled = 0x0000, // Member not referenceable - Private = 0x0001, // Accessible only by the parent type - FamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly - Assembly = 0x0003, // Accessibly by anyone in the Assembly - Family = 0x0004, // Accessible only by type and sub-types - FamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly - Public = 0x0006, // Accessibly by anyone who has visibility to this scope - - Static = 0x0010, // Defined on type, else per instance - Final = 0x0020, // Method may not be overridden - Virtual = 0x0040, // Method is virtual - HideBySig = 0x0080, // Method hides by name+sig, else just by name - - VtableLayoutMask = 0x0100, // Use this mask to retrieve vtable attributes - ReuseSlot = 0x0000, // Method reuses existing slot in vtable - NewSlot = 0x0100, // Method always gets a new slot in the vtable - - CheckAccessOnOverride = 0x0200, // Method can only be overriden if also accessible - Abstract = 0x0400, // Method does not provide an implementation - SpecialName = 0x0800, // Method is special - - // Interop Attributes - PInvokeImpl = 0x2000, // Implementation is forwarded through PInvoke - UnmanagedExport = 0x0008, // Reserved: shall be zero for conforming implementations - - // Additional flags - RTSpecialName = 0x1000, // CLI provides 'special' behavior, depending upon the name of the method - HasSecurity = 0x4000, // Method has security associate with it - RequireSecObject = 0x8000 // Method calls another method containing security code - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodAttributes.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodAttributes.cs.meta deleted file mode 100644 index 6060bf0..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodAttributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 84996fdfc826be145836c454e3781c51 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodCallingConvention.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodCallingConvention.cs deleted file mode 100644 index 2c219ba..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodCallingConvention.cs +++ /dev/null @@ -1,22 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public enum MethodCallingConvention : byte { - Default = 0x0, - C = 0x1, - StdCall = 0x2, - ThisCall = 0x3, - FastCall = 0x4, - VarArg = 0x5, - Generic = 0x10, - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodCallingConvention.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodCallingConvention.cs.meta deleted file mode 100644 index 0897aab..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodCallingConvention.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1d279830051a3cf4a9a8198756171875 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodDefinition.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodDefinition.cs deleted file mode 100644 index 164c0fb..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodDefinition.cs +++ /dev/null @@ -1,558 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Cil; -using MonoFN.Collections.Generic; -using System; -using System.Threading; -using RVA = System.UInt32; - -namespace MonoFN.Cecil { - - public sealed class MethodDefinition : MethodReference, IMemberDefinition, ISecurityDeclarationProvider, ICustomDebugInformationProvider { - - ushort attributes; - ushort impl_attributes; - internal volatile bool sem_attrs_ready; - internal MethodSemanticsAttributes sem_attrs; - Collection custom_attributes; - Collection security_declarations; - - internal RVA rva; - internal PInvokeInfo pinvoke; - Collection overrides; - - internal MethodBody body; - internal MethodDebugInformation debug_info; - internal Collection custom_infos; - - public override string Name { - get { return base.Name; } - set { - if (IsWindowsRuntimeProjection && value != base.Name) - throw new InvalidOperationException (); - - base.Name = value; - } - } - - public MethodAttributes Attributes { - get { return (MethodAttributes)attributes; } - set { - if (IsWindowsRuntimeProjection && (ushort)value != attributes) - throw new InvalidOperationException (); - - attributes = (ushort)value; - } - } - - public MethodImplAttributes ImplAttributes { - get { return (MethodImplAttributes)impl_attributes; } - set { - if (IsWindowsRuntimeProjection && (ushort)value != impl_attributes) - throw new InvalidOperationException (); - - impl_attributes = (ushort)value; - } - } - - public MethodSemanticsAttributes SemanticsAttributes { - get { - if (sem_attrs_ready) - return sem_attrs; - - if (HasImage) { - ReadSemantics (); - return sem_attrs; - } - - sem_attrs = MethodSemanticsAttributes.None; - sem_attrs_ready = true; - return sem_attrs; - } - set { sem_attrs = value; } - } - - internal MethodDefinitionProjection WindowsRuntimeProjection { - get { return (MethodDefinitionProjection)projection; } - set { projection = value; } - } - - internal void ReadSemantics () - { - if (sem_attrs_ready) - return; - - var module = this.Module; - if (module == null) - return; - - if (!module.HasImage) - return; - - lock (module.SyncRoot) { - if (sem_attrs_ready) - return; - - module.Read (this, (method, reader) => reader.ReadAllSemantics (method)); - } - } - - public bool HasSecurityDeclarations { - get { - if (security_declarations != null) - return security_declarations.Count > 0; - - return this.GetHasSecurityDeclarations (Module); - } - } - - public Collection SecurityDeclarations { - get { return security_declarations ?? (this.GetSecurityDeclarations (ref security_declarations, Module)); } - } - - public bool HasCustomAttributes { - get { - if (custom_attributes != null) - return custom_attributes.Count > 0; - - return this.GetHasCustomAttributes (Module); - } - } - - public Collection CustomAttributes { - get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); } - } - - public int RVA { - get { return (int)rva; } - } - - public bool HasBody { - get { - return (attributes & (ushort)MethodAttributes.Abstract) == 0 && - (attributes & (ushort)MethodAttributes.PInvokeImpl) == 0 && - (impl_attributes & (ushort)MethodImplAttributes.InternalCall) == 0 && - (impl_attributes & (ushort)MethodImplAttributes.Native) == 0 && - (impl_attributes & (ushort)MethodImplAttributes.Unmanaged) == 0 && - (impl_attributes & (ushort)MethodImplAttributes.Runtime) == 0; - } - } - - public MethodBody Body { - get { - var local = this.body; - if (local != null) - return local; - - if (!HasBody) - return null; - - if (HasImage && rva != 0) - return Module.Read (ref body, this, (method, reader) => reader.ReadMethodBody (method)); - - Interlocked.CompareExchange (ref body, new MethodBody (this), null); - - return body; - } - set { - var module = this.Module; - if (module == null) { - body = value; - return; - } - - // we reset Body to null in ILSpy to save memory; so we need that operation to be thread-safe - lock (module.SyncRoot) { - body = value; - if (value == null) - this.debug_info = null; - } - } - } - - public MethodDebugInformation DebugInformation { - get { - Mixin.Read (Body); - - if (debug_info == null) { - Interlocked.CompareExchange (ref debug_info, new MethodDebugInformation (this), null); - } - - return debug_info; - } - set { - debug_info = value; - } - } - - public bool HasPInvokeInfo { - get { - if (pinvoke != null) - return true; - - return IsPInvokeImpl; - } - } - - public PInvokeInfo PInvokeInfo { - get { - if (pinvoke != null) - return pinvoke; - - if (HasImage && IsPInvokeImpl) - return Module.Read (ref pinvoke, this, (method, reader) => reader.ReadPInvokeInfo (method)); - - return null; - } - set { - IsPInvokeImpl = true; - pinvoke = value; - } - } - - public bool HasOverrides { - get { - if (overrides != null) - return overrides.Count > 0; - - return HasImage && Module.Read (this, (method, reader) => reader.HasOverrides (method)); - } - } - - public Collection Overrides { - get { - if (overrides != null) - return overrides; - - if (HasImage) - return Module.Read (ref overrides, this, (method, reader) => reader.ReadOverrides (method)); - - Interlocked.CompareExchange (ref overrides, new Collection (), null); - - return overrides; - } - } - - public override bool HasGenericParameters { - get { - if (generic_parameters != null) - return generic_parameters.Count > 0; - - return this.GetHasGenericParameters (Module); - } - } - - public override Collection GenericParameters { - get { return generic_parameters ?? (this.GetGenericParameters (ref generic_parameters, Module)); } - } - - public bool HasCustomDebugInformations { - get { - Mixin.Read (Body); - - return !custom_infos.IsNullOrEmpty (); - } - } - - public Collection CustomDebugInformations { - get { - Mixin.Read (Body); - - if (custom_infos == null) - Interlocked.CompareExchange (ref custom_infos, new Collection (), null); - - return custom_infos; - } - } - - #region MethodAttributes - - public bool IsCompilerControlled { - get { return attributes.GetMaskedAttributes ((ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.CompilerControlled); } - set { attributes = attributes.SetMaskedAttributes ((ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.CompilerControlled, value); } - } - - public bool IsPrivate { - get { return attributes.GetMaskedAttributes ((ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Private); } - set { attributes = attributes.SetMaskedAttributes ((ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Private, value); } - } - - public bool IsFamilyAndAssembly { - get { return attributes.GetMaskedAttributes ((ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.FamANDAssem); } - set { attributes = attributes.SetMaskedAttributes ((ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.FamANDAssem, value); } - } - - public bool IsAssembly { - get { return attributes.GetMaskedAttributes ((ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Assembly); } - set { attributes = attributes.SetMaskedAttributes ((ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Assembly, value); } - } - - public bool IsFamily { - get { return attributes.GetMaskedAttributes ((ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Family); } - set { attributes = attributes.SetMaskedAttributes ((ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Family, value); } - } - - public bool IsFamilyOrAssembly { - get { return attributes.GetMaskedAttributes ((ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.FamORAssem); } - set { attributes = attributes.SetMaskedAttributes ((ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.FamORAssem, value); } - } - - public bool IsPublic { - get { return attributes.GetMaskedAttributes ((ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Public); } - set { attributes = attributes.SetMaskedAttributes ((ushort)MethodAttributes.MemberAccessMask, (ushort)MethodAttributes.Public, value); } - } - - public bool IsStatic { - get { return attributes.GetAttributes ((ushort)MethodAttributes.Static); } - set { attributes = attributes.SetAttributes ((ushort)MethodAttributes.Static, value); } - } - - public bool IsFinal { - get { return attributes.GetAttributes ((ushort)MethodAttributes.Final); } - set { attributes = attributes.SetAttributes ((ushort)MethodAttributes.Final, value); } - } - - public bool IsVirtual { - get { return attributes.GetAttributes ((ushort)MethodAttributes.Virtual); } - set { attributes = attributes.SetAttributes ((ushort)MethodAttributes.Virtual, value); } - } - - public bool IsHideBySig { - get { return attributes.GetAttributes ((ushort)MethodAttributes.HideBySig); } - set { attributes = attributes.SetAttributes ((ushort)MethodAttributes.HideBySig, value); } - } - - public bool IsReuseSlot { - get { return attributes.GetMaskedAttributes ((ushort)MethodAttributes.VtableLayoutMask, (ushort)MethodAttributes.ReuseSlot); } - set { attributes = attributes.SetMaskedAttributes ((ushort)MethodAttributes.VtableLayoutMask, (ushort)MethodAttributes.ReuseSlot, value); } - } - - public bool IsNewSlot { - get { return attributes.GetMaskedAttributes ((ushort)MethodAttributes.VtableLayoutMask, (ushort)MethodAttributes.NewSlot); } - set { attributes = attributes.SetMaskedAttributes ((ushort)MethodAttributes.VtableLayoutMask, (ushort)MethodAttributes.NewSlot, value); } - } - - public bool IsCheckAccessOnOverride { - get { return attributes.GetAttributes ((ushort)MethodAttributes.CheckAccessOnOverride); } - set { attributes = attributes.SetAttributes ((ushort)MethodAttributes.CheckAccessOnOverride, value); } - } - - public bool IsAbstract { - get { return attributes.GetAttributes ((ushort)MethodAttributes.Abstract); } - set { attributes = attributes.SetAttributes ((ushort)MethodAttributes.Abstract, value); } - } - - public bool IsSpecialName { - get { return attributes.GetAttributes ((ushort)MethodAttributes.SpecialName); } - set { attributes = attributes.SetAttributes ((ushort)MethodAttributes.SpecialName, value); } - } - - public bool IsPInvokeImpl { - get { return attributes.GetAttributes ((ushort)MethodAttributes.PInvokeImpl); } - set { attributes = attributes.SetAttributes ((ushort)MethodAttributes.PInvokeImpl, value); } - } - - public bool IsUnmanagedExport { - get { return attributes.GetAttributes ((ushort)MethodAttributes.UnmanagedExport); } - set { attributes = attributes.SetAttributes ((ushort)MethodAttributes.UnmanagedExport, value); } - } - - public bool IsRuntimeSpecialName { - get { return attributes.GetAttributes ((ushort)MethodAttributes.RTSpecialName); } - set { attributes = attributes.SetAttributes ((ushort)MethodAttributes.RTSpecialName, value); } - } - - public bool HasSecurity { - get { return attributes.GetAttributes ((ushort)MethodAttributes.HasSecurity); } - set { attributes = attributes.SetAttributes ((ushort)MethodAttributes.HasSecurity, value); } - } - - #endregion - - #region MethodImplAttributes - - public bool IsIL { - get { return impl_attributes.GetMaskedAttributes ((ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.IL); } - set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.IL, value); } - } - - public bool IsNative { - get { return impl_attributes.GetMaskedAttributes ((ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.Native); } - set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.Native, value); } - } - - public bool IsRuntime { - get { return impl_attributes.GetMaskedAttributes ((ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.Runtime); } - set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort)MethodImplAttributes.CodeTypeMask, (ushort)MethodImplAttributes.Runtime, value); } - } - - public bool IsUnmanaged { - get { return impl_attributes.GetMaskedAttributes ((ushort)MethodImplAttributes.ManagedMask, (ushort)MethodImplAttributes.Unmanaged); } - set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort)MethodImplAttributes.ManagedMask, (ushort)MethodImplAttributes.Unmanaged, value); } - } - - public bool IsManaged { - get { return impl_attributes.GetMaskedAttributes ((ushort)MethodImplAttributes.ManagedMask, (ushort)MethodImplAttributes.Managed); } - set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort)MethodImplAttributes.ManagedMask, (ushort)MethodImplAttributes.Managed, value); } - } - - public bool IsForwardRef { - get { return impl_attributes.GetAttributes ((ushort)MethodImplAttributes.ForwardRef); } - set { impl_attributes = impl_attributes.SetAttributes ((ushort)MethodImplAttributes.ForwardRef, value); } - } - - public bool IsPreserveSig { - get { return impl_attributes.GetAttributes ((ushort)MethodImplAttributes.PreserveSig); } - set { impl_attributes = impl_attributes.SetAttributes ((ushort)MethodImplAttributes.PreserveSig, value); } - } - - public bool IsInternalCall { - get { return impl_attributes.GetAttributes ((ushort)MethodImplAttributes.InternalCall); } - set { impl_attributes = impl_attributes.SetAttributes ((ushort)MethodImplAttributes.InternalCall, value); } - } - - public bool IsSynchronized { - get { return impl_attributes.GetAttributes ((ushort)MethodImplAttributes.Synchronized); } - set { impl_attributes = impl_attributes.SetAttributes ((ushort)MethodImplAttributes.Synchronized, value); } - } - - public bool NoInlining { - get { return impl_attributes.GetAttributes ((ushort)MethodImplAttributes.NoInlining); } - set { impl_attributes = impl_attributes.SetAttributes ((ushort)MethodImplAttributes.NoInlining, value); } - } - - public bool NoOptimization { - get { return impl_attributes.GetAttributes ((ushort)MethodImplAttributes.NoOptimization); } - set { impl_attributes = impl_attributes.SetAttributes ((ushort)MethodImplAttributes.NoOptimization, value); } - } - - public bool AggressiveInlining { - get { return impl_attributes.GetAttributes ((ushort)MethodImplAttributes.AggressiveInlining); } - set { impl_attributes = impl_attributes.SetAttributes ((ushort)MethodImplAttributes.AggressiveInlining, value); } - } - - #endregion - - #region MethodSemanticsAttributes - - public bool IsSetter { - get { return this.GetSemantics (MethodSemanticsAttributes.Setter); } - set { this.SetSemantics (MethodSemanticsAttributes.Setter, value); } - } - - public bool IsGetter { - get { return this.GetSemantics (MethodSemanticsAttributes.Getter); } - set { this.SetSemantics (MethodSemanticsAttributes.Getter, value); } - } - - public bool IsOther { - get { return this.GetSemantics (MethodSemanticsAttributes.Other); } - set { this.SetSemantics (MethodSemanticsAttributes.Other, value); } - } - - public bool IsAddOn { - get { return this.GetSemantics (MethodSemanticsAttributes.AddOn); } - set { this.SetSemantics (MethodSemanticsAttributes.AddOn, value); } - } - - public bool IsRemoveOn { - get { return this.GetSemantics (MethodSemanticsAttributes.RemoveOn); } - set { this.SetSemantics (MethodSemanticsAttributes.RemoveOn, value); } - } - - public bool IsFire { - get { return this.GetSemantics (MethodSemanticsAttributes.Fire); } - set { this.SetSemantics (MethodSemanticsAttributes.Fire, value); } - } - - #endregion - - public new TypeDefinition DeclaringType { - get { return (TypeDefinition)base.DeclaringType; } - set { base.DeclaringType = value; } - } - - public bool IsConstructor { - get { - return this.IsRuntimeSpecialName - && this.IsSpecialName - && (this.Name == ".cctor" || this.Name == ".ctor"); - } - } - - public override bool IsDefinition { - get { return true; } - } - - internal MethodDefinition () - { - this.token = new MetadataToken (TokenType.Method); - } - - public MethodDefinition (string name, MethodAttributes attributes, TypeReference returnType) - : base (name, returnType) - { - this.attributes = (ushort)attributes; - this.HasThis = !this.IsStatic; - this.token = new MetadataToken (TokenType.Method); - } - - public override MethodDefinition Resolve () - { - return this; - } - } - - static partial class Mixin { - - public static ParameterDefinition GetParameter (this MethodBody self, int index) - { - var method = self.method; - - if (method.HasThis) { - if (index == 0) - return self.ThisParameter; - - index--; - } - - var parameters = method.Parameters; - - if (index < 0 || index >= parameters.size) - return null; - - return parameters [index]; - } - - public static VariableDefinition GetVariable (this MethodBody self, int index) - { - var variables = self.Variables; - - if (index < 0 || index >= variables.size) - return null; - - return variables [index]; - } - - public static bool GetSemantics (this MethodDefinition self, MethodSemanticsAttributes semantics) - { - return (self.SemanticsAttributes & semantics) != 0; - } - - public static void SetSemantics (this MethodDefinition self, MethodSemanticsAttributes semantics, bool value) - { - if (value) - self.SemanticsAttributes |= semantics; - else - self.SemanticsAttributes &= ~semantics; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodDefinition.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodDefinition.cs.meta deleted file mode 100644 index 9fbc7fd..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodDefinition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 51ade7e624f84ae4abb8dc28a51b3082 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodImplAttributes.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodImplAttributes.cs deleted file mode 100644 index 722d5c5..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodImplAttributes.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - [Flags] - public enum MethodImplAttributes : ushort { - CodeTypeMask = 0x0003, - IL = 0x0000, // Method impl is CIL - Native = 0x0001, // Method impl is native - OPTIL = 0x0002, // Reserved: shall be zero in conforming implementations - Runtime = 0x0003, // Method impl is provided by the runtime - - ManagedMask = 0x0004, // Flags specifying whether the code is managed or unmanaged - Unmanaged = 0x0004, // Method impl is unmanaged, otherwise managed - Managed = 0x0000, // Method impl is managed - - // Implementation info and interop - ForwardRef = 0x0010, // Indicates method is defined; used primarily in merge scenarios - PreserveSig = 0x0080, // Reserved: conforming implementations may ignore - InternalCall = 0x1000, // Reserved: shall be zero in conforming implementations - Synchronized = 0x0020, // Method is single threaded through the body - NoOptimization = 0x0040, // Method is not optimized by the JIT. - NoInlining = 0x0008, // Method may not be inlined - AggressiveInlining = 0x0100, // Method should be inlined, if possible. - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodImplAttributes.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodImplAttributes.cs.meta deleted file mode 100644 index bc1d0fc..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodImplAttributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: bbe7f8d150d8c6b48abd24ac7718c9f4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReference.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReference.cs deleted file mode 100644 index 6280983..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReference.cs +++ /dev/null @@ -1,202 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; -using System.Text; -using System.Threading; - -namespace MonoFN.Cecil { - - public class MethodReference : MemberReference, IMethodSignature, IGenericParameterProvider, IGenericContext { - - internal ParameterDefinitionCollection parameters; - MethodReturnType return_type; - - bool has_this; - bool explicit_this; - MethodCallingConvention calling_convention; - internal Collection generic_parameters; - - public virtual bool HasThis { - get { return has_this; } - set { has_this = value; } - } - - public virtual bool ExplicitThis { - get { return explicit_this; } - set { explicit_this = value; } - } - - public virtual MethodCallingConvention CallingConvention { - get { return calling_convention; } - set { calling_convention = value; } - } - - public virtual bool HasParameters { - get { return !parameters.IsNullOrEmpty (); } - } - - public virtual Collection Parameters { - get { - if (parameters == null) - Interlocked.CompareExchange (ref parameters, new ParameterDefinitionCollection (this), null); - - return parameters; - } - } - - IGenericParameterProvider IGenericContext.Type { - get { - var declaring_type = this.DeclaringType; - var instance = declaring_type as GenericInstanceType; - if (instance != null) - return instance.ElementType; - - return declaring_type; - } - } - - IGenericParameterProvider IGenericContext.Method { - get { return this; } - } - - GenericParameterType IGenericParameterProvider.GenericParameterType { - get { return GenericParameterType.Method; } - } - - public virtual bool HasGenericParameters { - get { return !generic_parameters.IsNullOrEmpty (); } - } - - public virtual Collection GenericParameters { - get { - if (generic_parameters == null) - Interlocked.CompareExchange (ref generic_parameters, new GenericParameterCollection (this), null); - - return generic_parameters; - } - } - - public TypeReference ReturnType { - get { - var return_type = MethodReturnType; - return return_type != null ? return_type.ReturnType : null; - } - set { - var return_type = MethodReturnType; - if (return_type != null) - return_type.ReturnType = value; - } - } - - public virtual MethodReturnType MethodReturnType { - get { return return_type; } - set { return_type = value; } - } - - public override string FullName { - get { - var builder = new StringBuilder (); - builder.Append (ReturnType.FullName) - .Append (" ") - .Append (MemberFullName ()); - this.MethodSignatureFullName (builder); - return builder.ToString (); - } - } - - public virtual bool IsGenericInstance { - get { return false; } - } - - public override bool ContainsGenericParameter { - get { - if (this.ReturnType.ContainsGenericParameter || base.ContainsGenericParameter) - return true; - - if (!HasParameters) - return false; - - var parameters = this.Parameters; - - for (int i = 0; i < parameters.Count; i++) - if (parameters [i].ParameterType.ContainsGenericParameter) - return true; - - return false; - } - } - - internal MethodReference () - { - this.return_type = new MethodReturnType (this); - this.token = new MetadataToken (TokenType.MemberRef); - } - - public MethodReference (string name, TypeReference returnType) - : base (name) - { - Mixin.CheckType (returnType, Mixin.Argument.returnType); - - this.return_type = new MethodReturnType (this); - this.return_type.ReturnType = returnType; - this.token = new MetadataToken (TokenType.MemberRef); - } - - public MethodReference (string name, TypeReference returnType, TypeReference declaringType) - : this (name, returnType) - { - Mixin.CheckType (declaringType, Mixin.Argument.declaringType); - - this.DeclaringType = declaringType; - } - - public virtual MethodReference GetElementMethod () - { - return this; - } - - protected override IMemberDefinition ResolveDefinition () - { - return this.Resolve (); - } - - public new virtual MethodDefinition Resolve () - { - var module = this.Module; - if (module == null) - throw new NotSupportedException (); - - return module.Resolve (this); - } - } - - static partial class Mixin { - - public static bool IsVarArg (this IMethodSignature self) - { - return self.CallingConvention == MethodCallingConvention.VarArg; - } - - public static int GetSentinelPosition (this IMethodSignature self) - { - if (!self.HasParameters) - return -1; - - var parameters = self.Parameters; - for (int i = 0; i < parameters.Count; i++) - if (parameters [i].ParameterType.IsSentinel) - return i; - - return -1; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReference.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReference.cs.meta deleted file mode 100644 index 2f0eb25..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReference.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e894eb84c10b07f42bf952d556a35c1c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReferenceComparer.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReferenceComparer.cs deleted file mode 100644 index e8df3fd..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReferenceComparer.cs +++ /dev/null @@ -1,144 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace MonoFN.Cecil { - internal sealed class MethodReferenceComparer : EqualityComparer { - // Initialized lazily for each thread - [ThreadStatic] - static List xComparisonStack = null; - - [ThreadStatic] - static List yComparisonStack = null; - - public override bool Equals (MethodReference x, MethodReference y) - { - return AreEqual (x, y); - } - - public override int GetHashCode (MethodReference obj) - { - return GetHashCodeFor (obj); - } - - public static bool AreEqual (MethodReference x, MethodReference y) - { - if (ReferenceEquals (x, y)) - return true; - - if (x.HasThis != y.HasThis) - return false; - - if (x.HasParameters != y.HasParameters) - return false; - - if (x.HasGenericParameters != y.HasGenericParameters) - return false; - - if (x.Parameters.Count != y.Parameters.Count) - return false; - - if (x.Name != y.Name) - return false; - - if (!TypeReferenceEqualityComparer.AreEqual (x.DeclaringType, y.DeclaringType)) - return false; - - var xGeneric = x as GenericInstanceMethod; - var yGeneric = y as GenericInstanceMethod; - if (xGeneric != null || yGeneric != null) { - if (xGeneric == null || yGeneric == null) - return false; - - if (xGeneric.GenericArguments.Count != yGeneric.GenericArguments.Count) - return false; - - for (int i = 0; i < xGeneric.GenericArguments.Count; i++) - if (!TypeReferenceEqualityComparer.AreEqual (xGeneric.GenericArguments [i], yGeneric.GenericArguments [i])) - return false; - } - - var xResolved = x.Resolve (); - var yResolved = y.Resolve (); - - if (xResolved != yResolved) - return false; - - if (xResolved == null) { - // We couldn't resolve either method. In order for them to be equal, their parameter types _must_ match. But wait, there's a twist! - // There exists a situation where we might get into a recursive state: parameter type comparison might lead to comparing the same - // methods again if the parameter types are generic parameters whose owners are these methods. We guard against these by using a - // thread static list of all our comparisons carried out in the stack so far, and if we're in progress of comparing them already, - // we'll just say that they match. - - if (xComparisonStack == null) - xComparisonStack = new List (); - - if (yComparisonStack == null) - yComparisonStack = new List (); - - for (int i = 0; i < xComparisonStack.Count; i++) { - if (xComparisonStack [i] == x && yComparisonStack [i] == y) - return true; - } - - xComparisonStack.Add (x); - - try { - yComparisonStack.Add (y); - - try { - for (int i = 0; i < x.Parameters.Count; i++) { - if (!TypeReferenceEqualityComparer.AreEqual (x.Parameters [i].ParameterType, y.Parameters [i].ParameterType)) - return false; - } - } - finally { - yComparisonStack.RemoveAt (yComparisonStack.Count - 1); - } - } - finally { - xComparisonStack.RemoveAt (xComparisonStack.Count - 1); - } - } - - return true; - } - - public static bool AreSignaturesEqual (MethodReference x, MethodReference y, TypeComparisonMode comparisonMode = TypeComparisonMode.Exact) - { - if (x.HasThis != y.HasThis) - return false; - - if (x.Parameters.Count != y.Parameters.Count) - return false; - - if (x.GenericParameters.Count != y.GenericParameters.Count) - return false; - - for (var i = 0; i < x.Parameters.Count; i++) - if (!TypeReferenceEqualityComparer.AreEqual (x.Parameters [i].ParameterType, y.Parameters [i].ParameterType, comparisonMode)) - return false; - - if (!TypeReferenceEqualityComparer.AreEqual (x.ReturnType, y.ReturnType, comparisonMode)) - return false; - - return true; - } - - public static int GetHashCodeFor (MethodReference obj) - { - // a very good prime number - const int hashCodeMultiplier = 486187739; - - var genericInstanceMethod = obj as GenericInstanceMethod; - if (genericInstanceMethod != null) { - var hashCode = GetHashCodeFor (genericInstanceMethod.ElementMethod); - for (var i = 0; i < genericInstanceMethod.GenericArguments.Count; i++) - hashCode = hashCode * hashCodeMultiplier + TypeReferenceEqualityComparer.GetHashCodeFor (genericInstanceMethod.GenericArguments [i]); - return hashCode; - } - - return TypeReferenceEqualityComparer.GetHashCodeFor (obj.DeclaringType) * hashCodeMultiplier + obj.Name.GetHashCode (); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReferenceComparer.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReferenceComparer.cs.meta deleted file mode 100644 index 901496a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReferenceComparer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e61a3569af766524884d80a918529ab8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReturnType.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReturnType.cs deleted file mode 100644 index c833565..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReturnType.cs +++ /dev/null @@ -1,97 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System.Threading; - -namespace MonoFN.Cecil { - - public sealed class MethodReturnType : IConstantProvider, ICustomAttributeProvider, IMarshalInfoProvider { - - internal IMethodSignature method; - internal ParameterDefinition parameter; - TypeReference return_type; - - public IMethodSignature Method { - get { return method; } - } - - public TypeReference ReturnType { - get { return return_type; } - set { return_type = value; } - } - - internal ParameterDefinition Parameter { - get { - if (parameter == null) - Interlocked.CompareExchange (ref parameter, new ParameterDefinition (return_type, method), null); - - return parameter; - } - } - - public MetadataToken MetadataToken { - get { return Parameter.MetadataToken; } - set { Parameter.MetadataToken = value; } - } - - public ParameterAttributes Attributes { - get { return Parameter.Attributes; } - set { Parameter.Attributes = value; } - } - - public string Name { - get { return Parameter.Name; } - set { Parameter.Name = value; } - } - - public bool HasCustomAttributes { - get { return parameter != null && parameter.HasCustomAttributes; } - } - - public Collection CustomAttributes { - get { return Parameter.CustomAttributes; } - } - - public bool HasDefault { - get { return parameter != null && parameter.HasDefault; } - set { Parameter.HasDefault = value; } - } - - public bool HasConstant { - get { return parameter != null && parameter.HasConstant; } - set { Parameter.HasConstant = value; } - } - - public object Constant { - get { return Parameter.Constant; } - set { Parameter.Constant = value; } - } - - public bool HasFieldMarshal { - get { return parameter != null && parameter.HasFieldMarshal; } - set { Parameter.HasFieldMarshal = value; } - } - - public bool HasMarshalInfo { - get { return parameter != null && parameter.HasMarshalInfo; } - } - - public MarshalInfo MarshalInfo { - get { return Parameter.MarshalInfo; } - set { Parameter.MarshalInfo = value; } - } - - public MethodReturnType (IMethodSignature method) - { - this.method = method; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReturnType.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReturnType.cs.meta deleted file mode 100644 index 1cab923..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodReturnType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 51d33467d0e0c6f46a788d5da23d7b23 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSemanticsAttributes.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSemanticsAttributes.cs deleted file mode 100644 index 10b9ef9..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSemanticsAttributes.cs +++ /dev/null @@ -1,25 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - [Flags] - public enum MethodSemanticsAttributes : ushort { - None = 0x0000, - Setter = 0x0001, // Setter for property - Getter = 0x0002, // Getter for property - Other = 0x0004, // Other method for property or event - AddOn = 0x0008, // AddOn method for event - RemoveOn = 0x0010, // RemoveOn method for event - Fire = 0x0020 // Fire method for event - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSemanticsAttributes.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSemanticsAttributes.cs.meta deleted file mode 100644 index 7e68665..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSemanticsAttributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d6ed7cb61b1647749854923d7f4f2c4e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSpecification.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSpecification.cs deleted file mode 100644 index b4bc4ed..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSpecification.cs +++ /dev/null @@ -1,83 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; - -namespace MonoFN.Cecil { - - public abstract class MethodSpecification : MethodReference { - - readonly MethodReference method; - - public MethodReference ElementMethod { - get { return method; } - } - - public override string Name { - get { return method.Name; } - set { throw new InvalidOperationException (); } - } - - public override MethodCallingConvention CallingConvention { - get { return method.CallingConvention; } - set { throw new InvalidOperationException (); } - } - - public override bool HasThis { - get { return method.HasThis; } - set { throw new InvalidOperationException (); } - } - - public override bool ExplicitThis { - get { return method.ExplicitThis; } - set { throw new InvalidOperationException (); } - } - - public override MethodReturnType MethodReturnType { - get { return method.MethodReturnType; } - set { throw new InvalidOperationException (); } - } - - public override TypeReference DeclaringType { - get { return method.DeclaringType; } - set { throw new InvalidOperationException (); } - } - - public override ModuleDefinition Module { - get { return method.Module; } - } - - public override bool HasParameters { - get { return method.HasParameters; } - } - - public override Collection Parameters { - get { return method.Parameters; } - } - - public override bool ContainsGenericParameter { - get { return method.ContainsGenericParameter; } - } - - internal MethodSpecification (MethodReference method) - { - Mixin.CheckMethod (method); - - this.method = method; - this.token = new MetadataToken (TokenType.MethodSpec); - } - - public sealed override MethodReference GetElementMethod () - { - return method.GetElementMethod (); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSpecification.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSpecification.cs.meta deleted file mode 100644 index 0ab0565..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/MethodSpecification.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: aab27df5116b6ef46ac37993c843e4f0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Modifiers.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Modifiers.cs deleted file mode 100644 index 13367cd..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Modifiers.cs +++ /dev/null @@ -1,112 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -using MD = MonoFN.Cecil.Metadata; - -namespace MonoFN.Cecil { - - public interface IModifierType { - TypeReference ModifierType { get; } - TypeReference ElementType { get; } - } - - public sealed class OptionalModifierType : TypeSpecification, IModifierType { - - TypeReference modifier_type; - - public TypeReference ModifierType { - get { return modifier_type; } - set { modifier_type = value; } - } - - public override string Name { - get { return base.Name + Suffix; } - } - - public override string FullName { - get { return base.FullName + Suffix; } - } - - string Suffix { - get { return " modopt(" + modifier_type + ")"; } - } - - public override bool IsValueType { - get { return false; } - set { throw new InvalidOperationException (); } - } - - public override bool IsOptionalModifier { - get { return true; } - } - - public override bool ContainsGenericParameter { - get { return modifier_type.ContainsGenericParameter || base.ContainsGenericParameter; } - } - - public OptionalModifierType (TypeReference modifierType, TypeReference type) - : base (type) - { - if (modifierType == null) - throw new ArgumentNullException (Mixin.Argument.modifierType.ToString ()); - Mixin.CheckType (type); - this.modifier_type = modifierType; - this.etype = MD.ElementType.CModOpt; - } - } - - public sealed class RequiredModifierType : TypeSpecification, IModifierType { - - TypeReference modifier_type; - - public TypeReference ModifierType { - get { return modifier_type; } - set { modifier_type = value; } - } - - public override string Name { - get { return base.Name + Suffix; } - } - - public override string FullName { - get { return base.FullName + Suffix; } - } - - string Suffix { - get { return " modreq(" + modifier_type + ")"; } - } - - public override bool IsValueType { - get { return false; } - set { throw new InvalidOperationException (); } - } - - public override bool IsRequiredModifier { - get { return true; } - } - - public override bool ContainsGenericParameter { - get { return modifier_type.ContainsGenericParameter || base.ContainsGenericParameter; } - } - - public RequiredModifierType (TypeReference modifierType, TypeReference type) - : base (type) - { - if (modifierType == null) - throw new ArgumentNullException (Mixin.Argument.modifierType.ToString ()); - Mixin.CheckType (type); - this.modifier_type = modifierType; - this.etype = MD.ElementType.CModReqD; - } - - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Modifiers.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Modifiers.cs.meta deleted file mode 100644 index 7678d47..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Modifiers.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1fc5ce450d74933428a568f51cb49c16 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleDefinition.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleDefinition.cs deleted file mode 100644 index 9af60a5..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleDefinition.cs +++ /dev/null @@ -1,1353 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Cil; -using MonoFN.Cecil.Metadata; -using MonoFN.Cecil.PE; -using MonoFN.Collections.Generic; -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using SR = System.Reflection; - -namespace MonoFN.Cecil { - - public enum ReadingMode { - Immediate = 1, - Deferred = 2, - } - - public sealed class ReaderParameters { - - ReadingMode reading_mode; - internal IAssemblyResolver assembly_resolver; - internal IMetadataResolver metadata_resolver; - internal IMetadataImporterProvider metadata_importer_provider; - internal IReflectionImporterProvider reflection_importer_provider; - Stream symbol_stream; - ISymbolReaderProvider symbol_reader_provider; - bool read_symbols; - bool throw_symbols_mismatch; - bool projections; - bool in_memory; - bool read_write; - - public ReadingMode ReadingMode { - get { return reading_mode; } - set { reading_mode = value; } - } - - public bool InMemory { - get { return in_memory; } - set { in_memory = value; } - } - - public IAssemblyResolver AssemblyResolver { - get { return assembly_resolver; } - set { assembly_resolver = value; } - } - - public IMetadataResolver MetadataResolver { - get { return metadata_resolver; } - set { metadata_resolver = value; } - } - - public IMetadataImporterProvider MetadataImporterProvider { - get { return metadata_importer_provider; } - set { metadata_importer_provider = value; } - } - - public IReflectionImporterProvider ReflectionImporterProvider { - get { return reflection_importer_provider; } - set { reflection_importer_provider = value; } - } - - public Stream SymbolStream { - get { return symbol_stream; } - set { symbol_stream = value; } - } - - public ISymbolReaderProvider SymbolReaderProvider { - get { return symbol_reader_provider; } - set { symbol_reader_provider = value; } - } - - public bool ReadSymbols { - get { return read_symbols; } - set { read_symbols = value; } - } - - public bool ThrowIfSymbolsAreNotMatching { - get { return throw_symbols_mismatch; } - set { throw_symbols_mismatch = value; } - } - - public bool ReadWrite { - get { return read_write; } - set { read_write = value; } - } - - public bool ApplyWindowsRuntimeProjections { - get { return projections; } - set { projections = value; } - } - - public ReaderParameters () - : this (ReadingMode.Deferred) - { - } - - public ReaderParameters (ReadingMode readingMode) - { - this.reading_mode = readingMode; - this.throw_symbols_mismatch = true; - } - } - - public sealed class ModuleParameters { - - ModuleKind kind; - TargetRuntime runtime; - uint? timestamp; - TargetArchitecture architecture; - IAssemblyResolver assembly_resolver; - IMetadataResolver metadata_resolver; - IMetadataImporterProvider metadata_importer_provider; - IReflectionImporterProvider reflection_importer_provider; - - public ModuleKind Kind { - get { return kind; } - set { kind = value; } - } - - public TargetRuntime Runtime { - get { return runtime; } - set { runtime = value; } - } - - public uint? Timestamp { - get { return timestamp; } - set { timestamp = value; } - } - - public TargetArchitecture Architecture { - get { return architecture; } - set { architecture = value; } - } - - public IAssemblyResolver AssemblyResolver { - get { return assembly_resolver; } - set { assembly_resolver = value; } - } - - public IMetadataResolver MetadataResolver { - get { return metadata_resolver; } - set { metadata_resolver = value; } - } - - public IMetadataImporterProvider MetadataImporterProvider { - get { return metadata_importer_provider; } - set { metadata_importer_provider = value; } - } - - public IReflectionImporterProvider ReflectionImporterProvider { - get { return reflection_importer_provider; } - set { reflection_importer_provider = value; } - } - - public ModuleParameters () - { - this.kind = ModuleKind.Dll; - this.Runtime = GetCurrentRuntime (); - this.architecture = TargetArchitecture.I386; - } - - static TargetRuntime GetCurrentRuntime () - { - return typeof (object).Assembly.ImageRuntimeVersion.ParseRuntime (); - } - } - - public sealed class WriterParameters { - - uint? timestamp; - Stream symbol_stream; - ISymbolWriterProvider symbol_writer_provider; - bool write_symbols; - byte [] key_blob; - string key_container; - SR.StrongNameKeyPair key_pair; - - public uint? Timestamp { - get { return timestamp; } - set { timestamp = value; } - } - - public Stream SymbolStream { - get { return symbol_stream; } - set { symbol_stream = value; } - } - - public ISymbolWriterProvider SymbolWriterProvider { - get { return symbol_writer_provider; } - set { symbol_writer_provider = value; } - } - - public bool WriteSymbols { - get { return write_symbols; } - set { write_symbols = value; } - } - - public bool HasStrongNameKey { - get { return key_pair != null || key_blob != null || key_container != null; } - } - - public byte [] StrongNameKeyBlob { - get { return key_blob; } - set { key_blob = value; } - } - - public string StrongNameKeyContainer { - get { return key_container; } - set { key_container = value; } - } - - public SR.StrongNameKeyPair StrongNameKeyPair { - get { return key_pair; } - set { key_pair = value; } - } - - public bool DeterministicMvid { get; set; } - } - - public sealed class ModuleDefinition : ModuleReference, ICustomAttributeProvider, ICustomDebugInformationProvider, IDisposable { - - internal Image Image; - internal MetadataSystem MetadataSystem; - internal ReadingMode ReadingMode; - internal ISymbolReaderProvider SymbolReaderProvider; - - internal ISymbolReader symbol_reader; - internal Disposable assembly_resolver; - internal IMetadataResolver metadata_resolver; - internal TypeSystem type_system; - internal readonly MetadataReader reader; - readonly string file_name; - - internal string runtime_version; - internal ModuleKind kind; - WindowsRuntimeProjections projections; - MetadataKind metadata_kind; - TargetRuntime runtime; - TargetArchitecture architecture; - ModuleAttributes attributes; - ModuleCharacteristics characteristics; - Guid mvid; - - internal ushort linker_version = 8; - internal ushort subsystem_major = 4; - internal ushort subsystem_minor = 0; - internal uint timestamp; - - internal AssemblyDefinition assembly; - MethodDefinition entry_point; - bool entry_point_set; - - internal IReflectionImporter reflection_importer; - internal IMetadataImporter metadata_importer; - - Collection custom_attributes; - Collection references; - Collection modules; - Collection resources; - Collection exported_types; - TypeDefinitionCollection types; - - internal Collection custom_infos; - - internal MetadataBuilder metadata_builder; - - public bool IsMain { - get { return kind != ModuleKind.NetModule; } - } - - public ModuleKind Kind { - get { return kind; } - set { kind = value; } - } - - public MetadataKind MetadataKind { - get { return metadata_kind; } - set { metadata_kind = value; } - } - - internal WindowsRuntimeProjections Projections { - get { - if (projections == null) - Interlocked.CompareExchange (ref projections, new WindowsRuntimeProjections (this), null); - - return projections; - } - } - - public TargetRuntime Runtime { - get { return runtime; } - set { - runtime = value; - runtime_version = runtime.RuntimeVersionString (); - } - } - - public string RuntimeVersion { - get { return runtime_version; } - set { - runtime_version = value; - runtime = runtime_version.ParseRuntime (); - } - } - - public TargetArchitecture Architecture { - get { return architecture; } - set { architecture = value; } - } - - public ModuleAttributes Attributes { - get { return attributes; } - set { attributes = value; } - } - - public ModuleCharacteristics Characteristics { - get { return characteristics; } - set { characteristics = value; } - } - - [Obsolete ("Use FileName")] - public string FullyQualifiedName { - get { return file_name; } - } - - public string FileName { - get { return file_name; } - } - - public Guid Mvid { - get { return mvid; } - set { mvid = value; } - } - - internal bool HasImage { - get { return Image != null; } - } - - public bool HasSymbols { - get { return symbol_reader != null; } - } - - public ISymbolReader SymbolReader { - get { return symbol_reader; } - } - - public override MetadataScopeType MetadataScopeType { - get { return MetadataScopeType.ModuleDefinition; } - } - - public AssemblyDefinition Assembly { - get { return assembly; } - } - - internal IReflectionImporter ReflectionImporter { - get { - if (reflection_importer == null) - Interlocked.CompareExchange (ref reflection_importer, new DefaultReflectionImporter (this), null); - - return reflection_importer; - } - } - - internal IMetadataImporter MetadataImporter { - get { - if (metadata_importer == null) - Interlocked.CompareExchange (ref metadata_importer, new DefaultMetadataImporter (this), null); - - return metadata_importer; - } - } - - public IAssemblyResolver AssemblyResolver { - get { - if (assembly_resolver.value == null) { - lock (module_lock) { - assembly_resolver = Disposable.Owned (new DefaultAssemblyResolver () as IAssemblyResolver); - } - } - - return assembly_resolver.value; - } - } - - public IMetadataResolver MetadataResolver { - get { - if (metadata_resolver == null) - Interlocked.CompareExchange (ref metadata_resolver, new MetadataResolver (this.AssemblyResolver), null); - - return metadata_resolver; - } - } - - public TypeSystem TypeSystem { - get { - if (type_system == null) - Interlocked.CompareExchange (ref type_system, TypeSystem.CreateTypeSystem (this), null); - - return type_system; - } - } - - public bool HasAssemblyReferences { - get { - if (references != null) - return references.Count > 0; - - return HasImage && Image.HasTable (Table.AssemblyRef); - } - } - - public Collection AssemblyReferences { - get { - if (references != null) - return references; - - if (HasImage) - return Read (ref references, this, (_, reader) => reader.ReadAssemblyReferences ()); - - Interlocked.CompareExchange (ref references, new Collection (), null); - return references; - } - } - - public bool HasModuleReferences { - get { - if (modules != null) - return modules.Count > 0; - - return HasImage && Image.HasTable (Table.ModuleRef); - } - } - - public Collection ModuleReferences { - get { - if (modules != null) - return modules; - - if (HasImage) - return Read (ref modules, this, (_, reader) => reader.ReadModuleReferences ()); - - Interlocked.CompareExchange (ref modules, new Collection (), null); - return modules; - } - } - - public bool HasResources { - get { - if (resources != null) - return resources.Count > 0; - - if (HasImage) - return Image.HasTable (Table.ManifestResource) || Read (this, (_, reader) => reader.HasFileResource ()); - - return false; - } - } - - public Collection Resources { - get { - if (resources != null) - return resources; - - if (HasImage) - return Read (ref resources, this, (_, reader) => reader.ReadResources ()); - - Interlocked.CompareExchange (ref resources, new Collection (), null); - return resources; - } - } - - public bool HasCustomAttributes { - get { - if (custom_attributes != null) - return custom_attributes.Count > 0; - - return this.GetHasCustomAttributes (this); - } - } - - public Collection CustomAttributes { - get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, this)); } - } - - public bool HasTypes { - get { - if (types != null) - return types.Count > 0; - - return HasImage && Image.HasTable (Table.TypeDef); - } - } - - public Collection Types { - get { - if (types != null) - return types; - - if (HasImage) - return Read (ref types, this, (_, reader) => reader.ReadTypes ()); - - Interlocked.CompareExchange (ref types, new TypeDefinitionCollection (this), null); - return types; - } - } - - public bool HasExportedTypes { - get { - if (exported_types != null) - return exported_types.Count > 0; - - return HasImage && Image.HasTable (Table.ExportedType); - } - } - - public Collection ExportedTypes { - get { - if (exported_types != null) - return exported_types; - - if (HasImage) - return Read (ref exported_types, this, (_, reader) => reader.ReadExportedTypes ()); - - Interlocked.CompareExchange (ref exported_types, new Collection (), null); - return exported_types; - } - } - - public MethodDefinition EntryPoint { - get { - if (entry_point_set) - return entry_point; - - if (HasImage) - Read (ref entry_point, this, (_, reader) => reader.ReadEntryPoint ()); - else - entry_point = null; - - entry_point_set = true; - return entry_point; - } - set { - entry_point = value; - entry_point_set = true; - } - } - - public bool HasCustomDebugInformations { - get { - return custom_infos != null && custom_infos.Count > 0; - } - } - - public Collection CustomDebugInformations { - get { - if (custom_infos == null) - Interlocked.CompareExchange (ref custom_infos, new Collection (), null); - - return custom_infos; - } - } - - internal ModuleDefinition () - { - this.MetadataSystem = new MetadataSystem (); - this.token = new MetadataToken (TokenType.Module, 1); - } - - internal ModuleDefinition (Image image) - : this () - { - this.Image = image; - this.kind = image.Kind; - this.RuntimeVersion = image.RuntimeVersion; - this.architecture = image.Architecture; - this.attributes = image.Attributes; - this.characteristics = image.DllCharacteristics; - this.linker_version = image.LinkerVersion; - this.subsystem_major = image.SubSystemMajor; - this.subsystem_minor = image.SubSystemMinor; - this.file_name = image.FileName; - this.timestamp = image.Timestamp; - - this.reader = new MetadataReader (this); - } - - public void Dispose () - { - if (Image != null) - Image.Dispose (); - - if (symbol_reader != null) - symbol_reader.Dispose (); - - if (assembly_resolver.value != null) - assembly_resolver.Dispose (); - } - - public bool HasTypeReference (string fullName) - { - return HasTypeReference (string.Empty, fullName); - } - - public bool HasTypeReference (string scope, string fullName) - { - Mixin.CheckFullName (fullName); - - if (!HasImage) - return false; - - return GetTypeReference (scope, fullName) != null; - } - - public bool TryGetTypeReference (string fullName, out TypeReference type) - { - return TryGetTypeReference (string.Empty, fullName, out type); - } - - public bool TryGetTypeReference (string scope, string fullName, out TypeReference type) - { - Mixin.CheckFullName (fullName); - - if (!HasImage) { - type = null; - return false; - } - - return (type = GetTypeReference (scope, fullName)) != null; - } - - TypeReference GetTypeReference (string scope, string fullname) - { - return Read (new Row (scope, fullname), (row, reader) => reader.GetTypeReference (row.Col1, row.Col2)); - } - - public IEnumerable GetTypeReferences () - { - if (!HasImage) - return Empty.Array; - - return Read (this, (_, reader) => reader.GetTypeReferences ()); - } - - public IEnumerable GetMemberReferences () - { - if (!HasImage) - return Empty.Array; - - return Read (this, (_, reader) => reader.GetMemberReferences ()); - } - - public IEnumerable GetCustomAttributes () - { - if (!HasImage) - return Empty.Array; - - return Read (this, (_, reader) => reader.GetCustomAttributes ()); - } - - public TypeReference GetType (string fullName, bool runtimeName) - { - return runtimeName - ? TypeParser.ParseType (this, fullName, typeDefinitionOnly: true) - : GetType (fullName); - } - - public TypeDefinition GetType (string fullName) - { - Mixin.CheckFullName (fullName); - - var position = fullName.IndexOf ('/'); - if (position > 0) - return GetNestedType (fullName); - - return ((TypeDefinitionCollection)this.Types).GetType (fullName); - } - - public TypeDefinition GetType (string @namespace, string name) - { - Mixin.CheckName (name); - - return ((TypeDefinitionCollection)this.Types).GetType (@namespace ?? string.Empty, name); - } - - public IEnumerable GetTypes () - { - return GetTypes (Types); - } - - static IEnumerable GetTypes (Collection types) - { - for (int i = 0; i < types.Count; i++) { - var type = types [i]; - - yield return type; - - if (!type.HasNestedTypes) - continue; - - foreach (var nested in GetTypes (type.NestedTypes)) - yield return nested; - } - } - - TypeDefinition GetNestedType (string fullname) - { - var names = fullname.Split ('/'); - var type = GetType (names [0]); - - if (type == null) - return null; - - for (int i = 1; i < names.Length; i++) { - var nested_type = type.GetNestedType (names [i]); - if (nested_type == null) - return null; - - type = nested_type; - } - - return type; - } - - internal FieldDefinition Resolve (FieldReference field) - { - return MetadataResolver.Resolve (field); - } - - internal MethodDefinition Resolve (MethodReference method) - { - return MetadataResolver.Resolve (method); - } - - internal TypeDefinition Resolve (TypeReference type) - { - return MetadataResolver.Resolve (type); - } - - static void CheckContext (IGenericParameterProvider context, ModuleDefinition module) - { - if (context == null) - return; - - if (context.Module != module) - throw new ArgumentException (); - } - - [Obsolete ("Use ImportReference", error: false)] - public TypeReference Import (Type type) - { - return ImportReference (type, null); - } - - public TypeReference ImportReference (Type type) - { - return ImportReference (type, null); - } - - [Obsolete ("Use ImportReference", error: false)] - public TypeReference Import (Type type, IGenericParameterProvider context) - { - return ImportReference (type, context); - } - - public TypeReference ImportReference (Type type, IGenericParameterProvider context) - { - Mixin.CheckType (type); - CheckContext (context, this); - - return ReflectionImporter.ImportReference (type, context); - } - - [Obsolete ("Use ImportReference", error: false)] - public FieldReference Import (SR.FieldInfo field) - { - return ImportReference (field, null); - } - - [Obsolete ("Use ImportReference", error: false)] - public FieldReference Import (SR.FieldInfo field, IGenericParameterProvider context) - { - return ImportReference (field, context); - } - - public FieldReference ImportReference (SR.FieldInfo field) - { - return ImportReference (field, null); - } - - public FieldReference ImportReference (SR.FieldInfo field, IGenericParameterProvider context) - { - Mixin.CheckField (field); - CheckContext (context, this); - - return ReflectionImporter.ImportReference (field, context); - } - - [Obsolete ("Use ImportReference", error: false)] - public MethodReference Import (SR.MethodBase method) - { - return ImportReference (method, null); - } - - [Obsolete ("Use ImportReference", error: false)] - public MethodReference Import (SR.MethodBase method, IGenericParameterProvider context) - { - return ImportReference (method, context); - } - - public MethodReference ImportReference (SR.MethodBase method) - { - return ImportReference (method, null); - } - - public MethodReference ImportReference (SR.MethodBase method, IGenericParameterProvider context) - { - Mixin.CheckMethod (method); - CheckContext (context, this); - - return ReflectionImporter.ImportReference (method, context); - } - - [Obsolete ("Use ImportReference", error: false)] - public TypeReference Import (TypeReference type) - { - return ImportReference (type, null); - } - - [Obsolete ("Use ImportReference", error: false)] - public TypeReference Import (TypeReference type, IGenericParameterProvider context) - { - return ImportReference (type, context); - } - - public TypeReference ImportReference (TypeReference type) - { - return ImportReference (type, null); - } - - public TypeReference ImportReference (TypeReference type, IGenericParameterProvider context) - { - Mixin.CheckType (type); - - if (type.Module == this) - return type; - - CheckContext (context, this); - - return MetadataImporter.ImportReference (type, context); - } - - [Obsolete ("Use ImportReference", error: false)] - public FieldReference Import (FieldReference field) - { - return ImportReference (field, null); - } - - [Obsolete ("Use ImportReference", error: false)] - public FieldReference Import (FieldReference field, IGenericParameterProvider context) - { - return ImportReference (field, context); - } - - public FieldReference ImportReference (FieldReference field) - { - return ImportReference (field, null); - } - - public FieldReference ImportReference (FieldReference field, IGenericParameterProvider context) - { - Mixin.CheckField (field); - - if (field.Module == this) - return field; - - CheckContext (context, this); - - return MetadataImporter.ImportReference (field, context); - } - - [Obsolete ("Use ImportReference", error: false)] - public MethodReference Import (MethodReference method) - { - return ImportReference (method, null); - } - - [Obsolete ("Use ImportReference", error: false)] - public MethodReference Import (MethodReference method, IGenericParameterProvider context) - { - return ImportReference (method, context); - } - - public MethodReference ImportReference (MethodReference method) - { - return ImportReference (method, null); - } - - public MethodReference ImportReference (MethodReference method, IGenericParameterProvider context) - { - Mixin.CheckMethod (method); - - if (method.Module == this) - return method; - - CheckContext (context, this); - - return MetadataImporter.ImportReference (method, context); - } - - public IMetadataTokenProvider LookupToken (int token) - { - return LookupToken (new MetadataToken ((uint)token)); - } - - public IMetadataTokenProvider LookupToken (MetadataToken token) - { - return Read (token, (t, reader) => reader.LookupToken (t)); - } - - public void ImmediateRead () - { - if (!HasImage) - return; - ReadingMode = ReadingMode.Immediate; - var moduleReader = new ImmediateModuleReader (Image); - moduleReader.ReadModule (this, resolve_attributes: true); - } - - readonly object module_lock = new object (); - - internal object SyncRoot { - get { return module_lock; } - } - - internal void Read (TItem item, Action read) - { - lock (module_lock) { - var position = reader.position; - var context = reader.context; - - read (item, reader); - - reader.position = position; - reader.context = context; - } - } - - internal TRet Read (TItem item, Func read) - { - lock (module_lock) { - var position = reader.position; - var context = reader.context; - - var ret = read (item, reader); - - reader.position = position; - reader.context = context; - - return ret; - } - } - - internal TRet Read (ref TRet variable, TItem item, Func read) where TRet : class - { - lock (module_lock) { - if (variable != null) - return variable; - - var position = reader.position; - var context = reader.context; - - var ret = read (item, reader); - - reader.position = position; - reader.context = context; - - return variable = ret; - } - } - - public bool HasDebugHeader { - get { return Image != null && Image.DebugHeader != null; } - } - - public ImageDebugHeader GetDebugHeader () - { - return Image.DebugHeader ?? new ImageDebugHeader (); - } - - public static ModuleDefinition CreateModule (string name, ModuleKind kind) - { - return CreateModule (name, new ModuleParameters { Kind = kind }); - } - - public static ModuleDefinition CreateModule (string name, ModuleParameters parameters) - { - Mixin.CheckName (name); - Mixin.CheckParameters (parameters); - - var module = new ModuleDefinition { - Name = name, - kind = parameters.Kind, - timestamp = parameters.Timestamp ?? Mixin.GetTimestamp (), - Runtime = parameters.Runtime, - architecture = parameters.Architecture, - mvid = Guid.NewGuid (), - Attributes = ModuleAttributes.ILOnly, - Characteristics = (ModuleCharacteristics)0x8540, - }; - - if (parameters.AssemblyResolver != null) - module.assembly_resolver = Disposable.NotOwned (parameters.AssemblyResolver); - - if (parameters.MetadataResolver != null) - module.metadata_resolver = parameters.MetadataResolver; - - if (parameters.MetadataImporterProvider != null) - module.metadata_importer = parameters.MetadataImporterProvider.GetMetadataImporter (module); - - if (parameters.ReflectionImporterProvider != null) - module.reflection_importer = parameters.ReflectionImporterProvider.GetReflectionImporter (module); - - if (parameters.Kind != ModuleKind.NetModule) { - var assembly = new AssemblyDefinition (); - module.assembly = assembly; - module.assembly.Name = CreateAssemblyName (name); - assembly.main_module = module; - } - - module.Types.Add (new TypeDefinition (string.Empty, "", TypeAttributes.NotPublic)); - - return module; - } - - static AssemblyNameDefinition CreateAssemblyName (string name) - { - if (name.EndsWith (".dll") || name.EndsWith (".exe")) - name = name.Substring (0, name.Length - 4); - - return new AssemblyNameDefinition (name, Mixin.ZeroVersion); - } - - public void ReadSymbols () - { - if (string.IsNullOrEmpty (file_name)) - throw new InvalidOperationException (); - - var provider = new DefaultSymbolReaderProvider (throwIfNoSymbol: true); - ReadSymbols (provider.GetSymbolReader (this, file_name), throwIfSymbolsAreNotMaching: true); - } - - public void ReadSymbols (ISymbolReader reader) - { - ReadSymbols (reader, throwIfSymbolsAreNotMaching: true); - } - - public void ReadSymbols (ISymbolReader reader, bool throwIfSymbolsAreNotMaching) - { - if (reader == null) - throw new ArgumentNullException ("reader"); - - symbol_reader = reader; - - if (!symbol_reader.ProcessDebugHeader (GetDebugHeader ())) { - symbol_reader = null; - - if (throwIfSymbolsAreNotMaching) - throw new SymbolsNotMatchingException ("Symbols were found but are not matching the assembly"); - - return; - } - - if (HasImage && ReadingMode == ReadingMode.Immediate) { - var immediate_reader = new ImmediateModuleReader (Image); - immediate_reader.ReadSymbols (this); - } - } - - public static ModuleDefinition ReadModule (string fileName) - { - return ReadModule (fileName, new ReaderParameters (ReadingMode.Deferred)); - } - - public static ModuleDefinition ReadModule (string fileName, ReaderParameters parameters) - { - var stream = GetFileStream (fileName, FileMode.Open, parameters.ReadWrite ? FileAccess.ReadWrite : FileAccess.Read, FileShare.Read); - - if (parameters.InMemory) { - var memory = new MemoryStream (stream.CanSeek ? (int)stream.Length : 0); - using (stream) - stream.CopyTo (memory); - - memory.Position = 0; - stream = memory; - } - - try { - return ReadModule (Disposable.Owned (stream), fileName, parameters); - } - catch (Exception) { - stream.Dispose (); - throw; - } - } - - static Stream GetFileStream (string fileName, FileMode mode, FileAccess access, FileShare share) - { - Mixin.CheckFileName (fileName); - - return new FileStream (fileName, mode, access, share); - } - - public static ModuleDefinition ReadModule (Stream stream) - { - return ReadModule (stream, new ReaderParameters (ReadingMode.Deferred)); - } - - public static ModuleDefinition ReadModule (Stream stream, ReaderParameters parameters) - { - Mixin.CheckStream (stream); - Mixin.CheckReadSeek (stream); - - return ReadModule (Disposable.NotOwned (stream), stream.GetFileName (), parameters); - } - - static ModuleDefinition ReadModule (Disposable stream, string fileName, ReaderParameters parameters) - { - Mixin.CheckParameters (parameters); - - return ModuleReader.CreateModule ( - ImageReader.ReadImage (stream, fileName), - parameters); - } - - public void Write (string fileName) - { - Write (fileName, new WriterParameters ()); - } - - public void Write (string fileName, WriterParameters parameters) - { - Mixin.CheckParameters (parameters); - var file = GetFileStream (fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); - ModuleWriter.WriteModule (this, Disposable.Owned (file), parameters); - } - - public void Write () - { - Write (new WriterParameters ()); - } - - public void Write (WriterParameters parameters) - { - if (!HasImage) - throw new InvalidOperationException (); - - Write (Image.Stream.value, parameters); - } - - public void Write (Stream stream) - { - Write (stream, new WriterParameters ()); - } - - public void Write (Stream stream, WriterParameters parameters) - { - Mixin.CheckStream (stream); - Mixin.CheckWriteSeek (stream); - Mixin.CheckParameters (parameters); - - ModuleWriter.WriteModule (this, Disposable.NotOwned (stream), parameters); - } - } - - static partial class Mixin { - - public enum Argument { - name, - fileName, - fullName, - stream, - type, - method, - field, - parameters, - module, - modifierType, - eventType, - fieldType, - declaringType, - returnType, - propertyType, - interfaceType, - constraintType, - } - - public static void CheckName (object name) - { - if (name == null) - throw new ArgumentNullException (Argument.name.ToString ()); - } - - public static void CheckName (string name) - { - if (string.IsNullOrEmpty (name)) - throw new ArgumentNullOrEmptyException (Argument.name.ToString ()); - } - - public static void CheckFileName (string fileName) - { - if (string.IsNullOrEmpty (fileName)) - throw new ArgumentNullOrEmptyException (Argument.fileName.ToString ()); - } - - public static void CheckFullName (string fullName) - { - if (string.IsNullOrEmpty (fullName)) - throw new ArgumentNullOrEmptyException (Argument.fullName.ToString ()); - } - - public static void CheckStream (object stream) - { - if (stream == null) - throw new ArgumentNullException (Argument.stream.ToString ()); - } - - public static void CheckWriteSeek (Stream stream) - { - if (!stream.CanWrite || !stream.CanSeek) - throw new ArgumentException ("Stream must be writable and seekable."); - } - - public static void CheckReadSeek (Stream stream) - { - if (!stream.CanRead || !stream.CanSeek) - throw new ArgumentException ("Stream must be readable and seekable."); - } - - public static void CheckType (object type) - { - if (type == null) - throw new ArgumentNullException (Argument.type.ToString ()); - } - - public static void CheckType (object type, Argument argument) - { - if (type == null) - throw new ArgumentNullException (argument.ToString ()); - } - - public static void CheckField (object field) - { - if (field == null) - throw new ArgumentNullException (Argument.field.ToString ()); - } - - public static void CheckMethod (object method) - { - if (method == null) - throw new ArgumentNullException (Argument.method.ToString ()); - } - - public static void CheckParameters (object parameters) - { - if (parameters == null) - throw new ArgumentNullException (Argument.parameters.ToString ()); - } - - public static uint GetTimestamp () - { - return (uint)DateTime.UtcNow.Subtract (new DateTime (1970, 1, 1)).TotalSeconds; - } - - public static bool HasImage (this ModuleDefinition self) - { - return self != null && self.HasImage; - } - - public static string GetFileName (this Stream self) - { - var file_stream = self as FileStream; - if (file_stream == null) - return string.Empty; - - return Path.GetFullPath (file_stream.Name); - } - - public static TargetRuntime ParseRuntime (this string self) - { - if (string.IsNullOrEmpty (self)) - return TargetRuntime.Net_4_0; - - switch (self [1]) { - case '1': - return self [3] == '0' - ? TargetRuntime.Net_1_0 - : TargetRuntime.Net_1_1; - case '2': - return TargetRuntime.Net_2_0; - case '4': - default: - return TargetRuntime.Net_4_0; - } - } - - public static string RuntimeVersionString (this TargetRuntime runtime) - { - switch (runtime) { - case TargetRuntime.Net_1_0: - return "v1.0.3705"; - case TargetRuntime.Net_1_1: - return "v1.1.4322"; - case TargetRuntime.Net_2_0: - return "v2.0.50727"; - case TargetRuntime.Net_4_0: - default: - return "v4.0.30319"; - } - } - - public static bool IsWindowsMetadata (this ModuleDefinition module) - { - return module.MetadataKind != MetadataKind.Ecma335; - } - - public static byte [] ReadAll (this Stream self) - { - int read; - var memory = new MemoryStream ((int)self.Length); - var buffer = new byte [1024]; - - while ((read = self.Read (buffer, 0, buffer.Length)) != 0) - memory.Write (buffer, 0, read); - - return memory.ToArray (); - } - - public static void Read (object o) - { - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleDefinition.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleDefinition.cs.meta deleted file mode 100644 index d34c5c1..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleDefinition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: be36668e876daba419d4cf3aa5e8cac9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleKind.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleKind.cs deleted file mode 100644 index 429fa8f..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleKind.cs +++ /dev/null @@ -1,55 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - public enum ModuleKind { - Dll, - Console, - Windows, - NetModule, - } - - public enum MetadataKind { - Ecma335, - WindowsMetadata, - ManagedWindowsMetadata, - } - - public enum TargetArchitecture { - I386 = 0x014c, - AMD64 = 0x8664, - IA64 = 0x0200, - ARM = 0x01c0, - ARMv7 = 0x01c4, - ARM64 = 0xaa64, - } - - [Flags] - public enum ModuleAttributes { - ILOnly = 1, - Required32Bit = 2, - ILLibrary = 4, - StrongNameSigned = 8, - Preferred32Bit = 0x00020000, - } - - [Flags] - public enum ModuleCharacteristics { - HighEntropyVA = 0x0020, - DynamicBase = 0x0040, - NoSEH = 0x0400, - NXCompat = 0x0100, - AppContainer = 0x1000, - TerminalServerAware = 0x8000, - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleKind.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleKind.cs.meta deleted file mode 100644 index 110cc83..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleKind.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b85d54df2658b6d4bab3d27002f45a01 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleReference.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleReference.cs deleted file mode 100644 index eb22872..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleReference.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public class ModuleReference : IMetadataScope { - - string name; - - internal MetadataToken token; - - public string Name { - get { return name; } - set { name = value; } - } - - public virtual MetadataScopeType MetadataScopeType { - get { return MetadataScopeType.ModuleReference; } - } - - public MetadataToken MetadataToken { - get { return token; } - set { token = value; } - } - - internal ModuleReference () - { - this.token = new MetadataToken (TokenType.ModuleRef); - } - - public ModuleReference (string name) - : this () - { - this.name = name; - } - - public override string ToString () - { - return name; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleReference.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleReference.cs.meta deleted file mode 100644 index 3510c8c..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ModuleReference.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2b28049ba3ae6394dbe9f227aaf9c88e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/NativeType.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/NativeType.cs deleted file mode 100644 index b2ed6d2..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/NativeType.cs +++ /dev/null @@ -1,55 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public enum NativeType { - None = 0x66, - - Boolean = 0x02, - I1 = 0x03, - U1 = 0x04, - I2 = 0x05, - U2 = 0x06, - I4 = 0x07, - U4 = 0x08, - I8 = 0x09, - U8 = 0x0a, - R4 = 0x0b, - R8 = 0x0c, - LPStr = 0x14, - Int = 0x1f, - UInt = 0x20, - Func = 0x26, - Array = 0x2a, - - // Msft specific - Currency = 0x0f, - BStr = 0x13, - LPWStr = 0x15, - LPTStr = 0x16, - FixedSysString = 0x17, - IUnknown = 0x19, - IDispatch = 0x1a, - Struct = 0x1b, - IntF = 0x1c, - SafeArray = 0x1d, - FixedArray = 0x1e, - ByValStr = 0x22, - ANSIBStr = 0x23, - TBStr = 0x24, - VariantBool = 0x25, - ASAny = 0x28, - LPStruct = 0x2b, - CustomMarshaler = 0x2c, - Error = 0x2d, - Max = 0x50 - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/NativeType.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/NativeType.cs.meta deleted file mode 100644 index a6dd298..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/NativeType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: bb32c8b42f4f314448ff4b2c7eae0533 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeAttributes.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeAttributes.cs deleted file mode 100644 index d99aca4..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeAttributes.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - [Flags] - public enum PInvokeAttributes : ushort { - NoMangle = 0x0001, // PInvoke is to use the member name as specified - - // Character set - CharSetMask = 0x0006, - CharSetNotSpec = 0x0000, - CharSetAnsi = 0x0002, - CharSetUnicode = 0x0004, - CharSetAuto = 0x0006, - - SupportsLastError = 0x0040, // Information about target function. Not relevant for fields - - // Calling convetion - CallConvMask = 0x0700, - CallConvWinapi = 0x0100, - CallConvCdecl = 0x0200, - CallConvStdCall = 0x0300, - CallConvThiscall = 0x0400, - CallConvFastcall = 0x0500, - - BestFitMask = 0x0030, - BestFitEnabled = 0x0010, - BestFitDisabled = 0x0020, - - ThrowOnUnmappableCharMask = 0x3000, - ThrowOnUnmappableCharEnabled = 0x1000, - ThrowOnUnmappableCharDisabled = 0x2000, - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeAttributes.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeAttributes.cs.meta deleted file mode 100644 index e1bed46..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeAttributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: cf3019a5e2270654abca972684f5c2f9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeInfo.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeInfo.cs deleted file mode 100644 index 079c6bc..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeInfo.cs +++ /dev/null @@ -1,120 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public sealed class PInvokeInfo { - - ushort attributes; - string entry_point; - ModuleReference module; - - public PInvokeAttributes Attributes { - get { return (PInvokeAttributes)attributes; } - set { attributes = (ushort)value; } - } - - public string EntryPoint { - get { return entry_point; } - set { entry_point = value; } - } - - public ModuleReference Module { - get { return module; } - set { module = value; } - } - - #region PInvokeAttributes - - public bool IsNoMangle { - get { return attributes.GetAttributes ((ushort)PInvokeAttributes.NoMangle); } - set { attributes = attributes.SetAttributes ((ushort)PInvokeAttributes.NoMangle, value); } - } - - public bool IsCharSetNotSpec { - get { return attributes.GetMaskedAttributes ((ushort)PInvokeAttributes.CharSetMask, (ushort)PInvokeAttributes.CharSetNotSpec); } - set { attributes = attributes.SetMaskedAttributes ((ushort)PInvokeAttributes.CharSetMask, (ushort)PInvokeAttributes.CharSetNotSpec, value); } - } - - public bool IsCharSetAnsi { - get { return attributes.GetMaskedAttributes ((ushort)PInvokeAttributes.CharSetMask, (ushort)PInvokeAttributes.CharSetAnsi); } - set { attributes = attributes.SetMaskedAttributes ((ushort)PInvokeAttributes.CharSetMask, (ushort)PInvokeAttributes.CharSetAnsi, value); } - } - - public bool IsCharSetUnicode { - get { return attributes.GetMaskedAttributes ((ushort)PInvokeAttributes.CharSetMask, (ushort)PInvokeAttributes.CharSetUnicode); } - set { attributes = attributes.SetMaskedAttributes ((ushort)PInvokeAttributes.CharSetMask, (ushort)PInvokeAttributes.CharSetUnicode, value); } - } - - public bool IsCharSetAuto { - get { return attributes.GetMaskedAttributes ((ushort)PInvokeAttributes.CharSetMask, (ushort)PInvokeAttributes.CharSetAuto); } - set { attributes = attributes.SetMaskedAttributes ((ushort)PInvokeAttributes.CharSetMask, (ushort)PInvokeAttributes.CharSetAuto, value); } - } - - public bool SupportsLastError { - get { return attributes.GetAttributes ((ushort)PInvokeAttributes.SupportsLastError); } - set { attributes = attributes.SetAttributes ((ushort)PInvokeAttributes.SupportsLastError, value); } - } - - public bool IsCallConvWinapi { - get { return attributes.GetMaskedAttributes ((ushort)PInvokeAttributes.CallConvMask, (ushort)PInvokeAttributes.CallConvWinapi); } - set { attributes = attributes.SetMaskedAttributes ((ushort)PInvokeAttributes.CallConvMask, (ushort)PInvokeAttributes.CallConvWinapi, value); } - } - - public bool IsCallConvCdecl { - get { return attributes.GetMaskedAttributes ((ushort)PInvokeAttributes.CallConvMask, (ushort)PInvokeAttributes.CallConvCdecl); } - set { attributes = attributes.SetMaskedAttributes ((ushort)PInvokeAttributes.CallConvMask, (ushort)PInvokeAttributes.CallConvCdecl, value); } - } - - public bool IsCallConvStdCall { - get { return attributes.GetMaskedAttributes ((ushort)PInvokeAttributes.CallConvMask, (ushort)PInvokeAttributes.CallConvStdCall); } - set { attributes = attributes.SetMaskedAttributes ((ushort)PInvokeAttributes.CallConvMask, (ushort)PInvokeAttributes.CallConvStdCall, value); } - } - - public bool IsCallConvThiscall { - get { return attributes.GetMaskedAttributes ((ushort)PInvokeAttributes.CallConvMask, (ushort)PInvokeAttributes.CallConvThiscall); } - set { attributes = attributes.SetMaskedAttributes ((ushort)PInvokeAttributes.CallConvMask, (ushort)PInvokeAttributes.CallConvThiscall, value); } - } - - public bool IsCallConvFastcall { - get { return attributes.GetMaskedAttributes ((ushort)PInvokeAttributes.CallConvMask, (ushort)PInvokeAttributes.CallConvFastcall); } - set { attributes = attributes.SetMaskedAttributes ((ushort)PInvokeAttributes.CallConvMask, (ushort)PInvokeAttributes.CallConvFastcall, value); } - } - - public bool IsBestFitEnabled { - get { return attributes.GetMaskedAttributes ((ushort)PInvokeAttributes.BestFitMask, (ushort)PInvokeAttributes.BestFitEnabled); } - set { attributes = attributes.SetMaskedAttributes ((ushort)PInvokeAttributes.BestFitMask, (ushort)PInvokeAttributes.BestFitEnabled, value); } - } - - public bool IsBestFitDisabled { - get { return attributes.GetMaskedAttributes ((ushort)PInvokeAttributes.BestFitMask, (ushort)PInvokeAttributes.BestFitDisabled); } - set { attributes = attributes.SetMaskedAttributes ((ushort)PInvokeAttributes.BestFitMask, (ushort)PInvokeAttributes.BestFitDisabled, value); } - } - - public bool IsThrowOnUnmappableCharEnabled { - get { return attributes.GetMaskedAttributes ((ushort)PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort)PInvokeAttributes.ThrowOnUnmappableCharEnabled); } - set { attributes = attributes.SetMaskedAttributes ((ushort)PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort)PInvokeAttributes.ThrowOnUnmappableCharEnabled, value); } - } - - public bool IsThrowOnUnmappableCharDisabled { - get { return attributes.GetMaskedAttributes ((ushort)PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort)PInvokeAttributes.ThrowOnUnmappableCharDisabled); } - set { attributes = attributes.SetMaskedAttributes ((ushort)PInvokeAttributes.ThrowOnUnmappableCharMask, (ushort)PInvokeAttributes.ThrowOnUnmappableCharDisabled, value); } - } - - #endregion - - public PInvokeInfo (PInvokeAttributes attributes, string entryPoint, ModuleReference module) - { - this.attributes = (ushort)attributes; - this.entry_point = entryPoint; - this.module = module; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeInfo.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeInfo.cs.meta deleted file mode 100644 index 4c27d4b..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PInvokeInfo.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 56eb336b3d1ea2b4094fbb5586a11d49 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterAttributes.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterAttributes.cs deleted file mode 100644 index 387e1dc..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterAttributes.cs +++ /dev/null @@ -1,27 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - [Flags] - public enum ParameterAttributes : ushort { - None = 0x0000, - In = 0x0001, // Param is [In] - Out = 0x0002, // Param is [Out] - Lcid = 0x0004, - Retval = 0x0008, - Optional = 0x0010, // Param is optional - HasDefault = 0x1000, // Param has default value - HasFieldMarshal = 0x2000, // Param has field marshal - Unused = 0xcfe0 // Reserved: shall be zero in a conforming implementation - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterAttributes.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterAttributes.cs.meta deleted file mode 100644 index 487cc73..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterAttributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: dc153e8db6e9d1b4ca432cd66ecfe423 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinition.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinition.cs deleted file mode 100644 index cd4905a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinition.cs +++ /dev/null @@ -1,146 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; - -namespace MonoFN.Cecil { - - public sealed class ParameterDefinition : ParameterReference, ICustomAttributeProvider, IConstantProvider, IMarshalInfoProvider { - - ushort attributes; - - internal IMethodSignature method; - - object constant = Mixin.NotResolved; - Collection custom_attributes; - MarshalInfo marshal_info; - - public ParameterAttributes Attributes { - get { return (ParameterAttributes)attributes; } - set { attributes = (ushort)value; } - } - - public IMethodSignature Method { - get { return method; } - } - - public int Sequence { - get { - if (method == null) - return -1; - - return method.HasImplicitThis () ? index + 1 : index; - } - } - - public bool HasConstant { - get { - this.ResolveConstant (ref constant, parameter_type.Module); - - return constant != Mixin.NoValue; - } - set { if (!value) constant = Mixin.NoValue; } - } - - public object Constant { - get { return HasConstant ? constant : null; } - set { constant = value; } - } - - public bool HasCustomAttributes { - get { - if (custom_attributes != null) - return custom_attributes.Count > 0; - - return this.GetHasCustomAttributes (parameter_type.Module); - } - } - - public Collection CustomAttributes { - get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, parameter_type.Module)); } - } - - public bool HasMarshalInfo { - get { - if (marshal_info != null) - return true; - - return this.GetHasMarshalInfo (parameter_type.Module); - } - } - - public MarshalInfo MarshalInfo { - get { return marshal_info ?? (this.GetMarshalInfo (ref marshal_info, parameter_type.Module)); } - set { marshal_info = value; } - } - - #region ParameterAttributes - - public bool IsIn { - get { return attributes.GetAttributes ((ushort)ParameterAttributes.In); } - set { attributes = attributes.SetAttributes ((ushort)ParameterAttributes.In, value); } - } - - public bool IsOut { - get { return attributes.GetAttributes ((ushort)ParameterAttributes.Out); } - set { attributes = attributes.SetAttributes ((ushort)ParameterAttributes.Out, value); } - } - - public bool IsLcid { - get { return attributes.GetAttributes ((ushort)ParameterAttributes.Lcid); } - set { attributes = attributes.SetAttributes ((ushort)ParameterAttributes.Lcid, value); } - } - - public bool IsReturnValue { - get { return attributes.GetAttributes ((ushort)ParameterAttributes.Retval); } - set { attributes = attributes.SetAttributes ((ushort)ParameterAttributes.Retval, value); } - } - - public bool IsOptional { - get { return attributes.GetAttributes ((ushort)ParameterAttributes.Optional); } - set { attributes = attributes.SetAttributes ((ushort)ParameterAttributes.Optional, value); } - } - - public bool HasDefault { - get { return attributes.GetAttributes ((ushort)ParameterAttributes.HasDefault); } - set { attributes = attributes.SetAttributes ((ushort)ParameterAttributes.HasDefault, value); } - } - - public bool HasFieldMarshal { - get { return attributes.GetAttributes ((ushort)ParameterAttributes.HasFieldMarshal); } - set { attributes = attributes.SetAttributes ((ushort)ParameterAttributes.HasFieldMarshal, value); } - } - - #endregion - - internal ParameterDefinition (TypeReference parameterType, IMethodSignature method) - : this (string.Empty, ParameterAttributes.None, parameterType) - { - this.method = method; - } - - public ParameterDefinition (TypeReference parameterType) - : this (string.Empty, ParameterAttributes.None, parameterType) - { - } - - public ParameterDefinition (string name, ParameterAttributes attributes, TypeReference parameterType) - : base (name, parameterType) - { - this.attributes = (ushort)attributes; - this.token = new MetadataToken (TokenType.Param); - } - - public override ParameterDefinition Resolve () - { - return this; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinition.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinition.cs.meta deleted file mode 100644 index 06cef24..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b6759139d8b53974087e609a88da6072 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinitionCollection.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinitionCollection.cs deleted file mode 100644 index 26eaec0..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinitionCollection.cs +++ /dev/null @@ -1,60 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; - -namespace MonoFN.Cecil { - - sealed class ParameterDefinitionCollection : Collection { - - readonly IMethodSignature method; - - internal ParameterDefinitionCollection (IMethodSignature method) - { - this.method = method; - } - - internal ParameterDefinitionCollection (IMethodSignature method, int capacity) - : base (capacity) - { - this.method = method; - } - - protected override void OnAdd (ParameterDefinition item, int index) - { - item.method = method; - item.index = index; - } - - protected override void OnInsert (ParameterDefinition item, int index) - { - item.method = method; - item.index = index; - - for (int i = index; i < size; i++) - items [i].index = i + 1; - } - - protected override void OnSet (ParameterDefinition item, int index) - { - item.method = method; - item.index = index; - } - - protected override void OnRemove (ParameterDefinition item, int index) - { - item.method = null; - item.index = -1; - - for (int i = index + 1; i < size; i++) - items [i].index = i - 1; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinitionCollection.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinitionCollection.cs.meta deleted file mode 100644 index 1e96811..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterDefinitionCollection.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 01e788194a3a3604784e347ac41ec6b1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterReference.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterReference.cs deleted file mode 100644 index b84fe3f..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterReference.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - public abstract class ParameterReference : IMetadataTokenProvider { - - string name; - internal int index = -1; - protected TypeReference parameter_type; - internal MetadataToken token; - - public string Name { - get { return name; } - set { name = value; } - } - - public int Index { - get { return index; } - } - - public TypeReference ParameterType { - get { return parameter_type; } - set { parameter_type = value; } - } - - public MetadataToken MetadataToken { - get { return token; } - set { token = value; } - } - - internal ParameterReference (string name, TypeReference parameterType) - { - if (parameterType == null) - throw new ArgumentNullException ("parameterType"); - - this.name = name ?? string.Empty; - this.parameter_type = parameterType; - } - - public override string ToString () - { - return name; - } - - public abstract ParameterDefinition Resolve (); - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterReference.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterReference.cs.meta deleted file mode 100644 index 69166ca..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ParameterReference.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0643ce0ca6e47bf4e92518aed8a3a955 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PinnedType.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PinnedType.cs deleted file mode 100644 index dc83596..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PinnedType.cs +++ /dev/null @@ -1,35 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -using MD = MonoFN.Cecil.Metadata; - -namespace MonoFN.Cecil { - - public sealed class PinnedType : TypeSpecification { - - public override bool IsValueType { - get { return false; } - set { throw new InvalidOperationException (); } - } - - public override bool IsPinned { - get { return true; } - } - - public PinnedType (TypeReference type) - : base (type) - { - Mixin.CheckType (type); - this.etype = MD.ElementType.Pinned; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PinnedType.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PinnedType.cs.meta deleted file mode 100644 index 325921b..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PinnedType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6840e25b64ef0924d84724d5587cfa68 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PointerType.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PointerType.cs deleted file mode 100644 index 5c27093..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PointerType.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -using MD = MonoFN.Cecil.Metadata; - -namespace MonoFN.Cecil { - - public sealed class PointerType : TypeSpecification { - - public override string Name { - get { return base.Name + "*"; } - } - - public override string FullName { - get { return base.FullName + "*"; } - } - - public override bool IsValueType { - get { return false; } - set { throw new InvalidOperationException (); } - } - - public override bool IsPointer { - get { return true; } - } - - public PointerType (TypeReference type) - : base (type) - { - Mixin.CheckType (type); - this.etype = MD.ElementType.Ptr; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PointerType.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PointerType.cs.meta deleted file mode 100644 index 665c696..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PointerType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7b6a1c540eedbb04082628ad5dd10583 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyAttributes.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyAttributes.cs deleted file mode 100644 index 1f32a51..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyAttributes.cs +++ /dev/null @@ -1,23 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - [Flags] - public enum PropertyAttributes : ushort { - None = 0x0000, - SpecialName = 0x0200, // Property is special - RTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding - HasDefault = 0x1000, // Property has default - Unused = 0xe9ff // Reserved: shall be zero in a conforming implementation - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyAttributes.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyAttributes.cs.meta deleted file mode 100644 index 6a0dbc7..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyAttributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 163bf99004c8e294f8b4113c29cae987 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyDefinition.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyDefinition.cs deleted file mode 100644 index 3268ffd..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyDefinition.cs +++ /dev/null @@ -1,245 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System.Text; -using System.Threading; - -namespace MonoFN.Cecil { - - public sealed class PropertyDefinition : PropertyReference, IMemberDefinition, IConstantProvider { - - bool? has_this; - ushort attributes; - - Collection custom_attributes; - - internal MethodDefinition get_method; - internal MethodDefinition set_method; - internal Collection other_methods; - - object constant = Mixin.NotResolved; - - public PropertyAttributes Attributes { - get { return (PropertyAttributes)attributes; } - set { attributes = (ushort)value; } - } - - public bool HasThis { - get { - if (has_this.HasValue) - return has_this.Value; - - if (GetMethod != null) - return get_method.HasThis; - - if (SetMethod != null) - return set_method.HasThis; - - return false; - } - set { has_this = value; } - } - - public bool HasCustomAttributes { - get { - if (custom_attributes != null) - return custom_attributes.Count > 0; - - return this.GetHasCustomAttributes (Module); - } - } - - public Collection CustomAttributes { - get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); } - } - - public MethodDefinition GetMethod { - get { - if (get_method != null) - return get_method; - - InitializeMethods (); - return get_method; - } - set { get_method = value; } - } - - public MethodDefinition SetMethod { - get { - if (set_method != null) - return set_method; - - InitializeMethods (); - return set_method; - } - set { set_method = value; } - } - - public bool HasOtherMethods { - get { - if (other_methods != null) - return other_methods.Count > 0; - - InitializeMethods (); - return !other_methods.IsNullOrEmpty (); - } - } - - public Collection OtherMethods { - get { - if (other_methods != null) - return other_methods; - - InitializeMethods (); - - if (other_methods != null) - return other_methods; - - Interlocked.CompareExchange (ref other_methods, new Collection (), null); - return other_methods; - } - } - - public bool HasParameters { - get { - InitializeMethods (); - - if (get_method != null) - return get_method.HasParameters; - - if (set_method != null) - return set_method.HasParameters && set_method.Parameters.Count > 1; - - return false; - } - } - - public override Collection Parameters { - get { - InitializeMethods (); - - if (get_method != null) - return MirrorParameters (get_method, 0); - - if (set_method != null) - return MirrorParameters (set_method, 1); - - return new Collection (); - } - } - - static Collection MirrorParameters (MethodDefinition method, int bound) - { - var parameters = new Collection (); - if (!method.HasParameters) - return parameters; - - var original_parameters = method.Parameters; - var end = original_parameters.Count - bound; - - for (int i = 0; i < end; i++) - parameters.Add (original_parameters [i]); - - return parameters; - } - - public bool HasConstant { - get { - this.ResolveConstant (ref constant, Module); - - return constant != Mixin.NoValue; - } - set { if (!value) constant = Mixin.NoValue; } - } - - public object Constant { - get { return HasConstant ? constant : null; } - set { constant = value; } - } - - #region PropertyAttributes - - public bool IsSpecialName { - get { return attributes.GetAttributes ((ushort)PropertyAttributes.SpecialName); } - set { attributes = attributes.SetAttributes ((ushort)PropertyAttributes.SpecialName, value); } - } - - public bool IsRuntimeSpecialName { - get { return attributes.GetAttributes ((ushort)PropertyAttributes.RTSpecialName); } - set { attributes = attributes.SetAttributes ((ushort)PropertyAttributes.RTSpecialName, value); } - } - - public bool HasDefault { - get { return attributes.GetAttributes ((ushort)PropertyAttributes.HasDefault); } - set { attributes = attributes.SetAttributes ((ushort)PropertyAttributes.HasDefault, value); } - } - - #endregion - - public new TypeDefinition DeclaringType { - get { return (TypeDefinition)base.DeclaringType; } - set { base.DeclaringType = value; } - } - - public override bool IsDefinition { - get { return true; } - } - - public override string FullName { - get { - var builder = new StringBuilder (); - builder.Append (PropertyType.ToString ()); - builder.Append (' '); - builder.Append (MemberFullName ()); - builder.Append ('('); - if (HasParameters) { - var parameters = Parameters; - for (int i = 0; i < parameters.Count; i++) { - if (i > 0) - builder.Append (','); - builder.Append (parameters [i].ParameterType.FullName); - } - } - builder.Append (')'); - return builder.ToString (); - } - } - - public PropertyDefinition (string name, PropertyAttributes attributes, TypeReference propertyType) - : base (name, propertyType) - { - this.attributes = (ushort)attributes; - this.token = new MetadataToken (TokenType.Property); - } - - void InitializeMethods () - { - var module = this.Module; - if (module == null) - return; - - lock (module.SyncRoot) { - if (get_method != null || set_method != null) - return; - - if (!module.HasImage ()) - return; - - module.Read (this, (property, reader) => reader.ReadMethods (property)); - } - } - - public override PropertyDefinition Resolve () - { - return this; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyDefinition.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyDefinition.cs.meta deleted file mode 100644 index a372850..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyDefinition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6c1878ca62c0e6f4595238eb6a87edfd -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyReference.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyReference.cs deleted file mode 100644 index d3f7a4c..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyReference.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; - -namespace MonoFN.Cecil { - - public abstract class PropertyReference : MemberReference { - - TypeReference property_type; - - public TypeReference PropertyType { - get { return property_type; } - set { property_type = value; } - } - - public abstract Collection Parameters { - get; - } - - internal PropertyReference (string name, TypeReference propertyType) - : base (name) - { - Mixin.CheckType (propertyType, Mixin.Argument.propertyType); - - property_type = propertyType; - } - - protected override IMemberDefinition ResolveDefinition () - { - return this.Resolve (); - } - - public new abstract PropertyDefinition Resolve (); - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyReference.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyReference.cs.meta deleted file mode 100644 index a218f3c..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/PropertyReference.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a30c5751a554ce649bf88a597e4075e9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ReferenceType.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ReferenceType.cs deleted file mode 100644 index e2703a4..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ReferenceType.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -using MD = MonoFN.Cecil.Metadata; - -namespace MonoFN.Cecil { - - public sealed class ByReferenceType : TypeSpecification { - - public override string Name { - get { return base.Name + "&"; } - } - - public override string FullName { - get { return base.FullName + "&"; } - } - - public override bool IsValueType { - get { return false; } - set { throw new InvalidOperationException (); } - } - - public override bool IsByReference { - get { return true; } - } - - public ByReferenceType (TypeReference type) - : base (type) - { - Mixin.CheckType (type); - this.etype = MD.ElementType.ByRef; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ReferenceType.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ReferenceType.cs.meta deleted file mode 100644 index de5a90f..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/ReferenceType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 32a78d7552e92774cbf44ddd46fb7aa4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Resource.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Resource.cs deleted file mode 100644 index 92c007f..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Resource.cs +++ /dev/null @@ -1,58 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public enum ResourceType { - Linked, - Embedded, - AssemblyLinked, - } - - public abstract class Resource { - - string name; - uint attributes; - - public string Name { - get { return name; } - set { name = value; } - } - - public ManifestResourceAttributes Attributes { - get { return (ManifestResourceAttributes)attributes; } - set { attributes = (uint)value; } - } - - public abstract ResourceType ResourceType { - get; - } - - #region ManifestResourceAttributes - - public bool IsPublic { - get { return attributes.GetMaskedAttributes ((uint)ManifestResourceAttributes.VisibilityMask, (uint)ManifestResourceAttributes.Public); } - set { attributes = attributes.SetMaskedAttributes ((uint)ManifestResourceAttributes.VisibilityMask, (uint)ManifestResourceAttributes.Public, value); } - } - - public bool IsPrivate { - get { return attributes.GetMaskedAttributes ((uint)ManifestResourceAttributes.VisibilityMask, (uint)ManifestResourceAttributes.Private); } - set { attributes = attributes.SetMaskedAttributes ((uint)ManifestResourceAttributes.VisibilityMask, (uint)ManifestResourceAttributes.Private, value); } - } - - #endregion - - internal Resource (string name, ManifestResourceAttributes attributes) - { - this.name = name; - this.attributes = (uint)attributes; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Resource.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Resource.cs.meta deleted file mode 100644 index c4c82c9..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Resource.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b8b738634202e694ebec627727698b83 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SecurityDeclaration.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SecurityDeclaration.cs deleted file mode 100644 index c3e27b4..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SecurityDeclaration.cs +++ /dev/null @@ -1,201 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; -using System.Diagnostics; -using System.Threading; - -namespace MonoFN.Cecil { - - public enum SecurityAction : ushort { - Request = 1, - Demand = 2, - Assert = 3, - Deny = 4, - PermitOnly = 5, - LinkDemand = 6, - InheritDemand = 7, - RequestMinimum = 8, - RequestOptional = 9, - RequestRefuse = 10, - PreJitGrant = 11, - PreJitDeny = 12, - NonCasDemand = 13, - NonCasLinkDemand = 14, - NonCasInheritance = 15 - } - - public interface ISecurityDeclarationProvider : IMetadataTokenProvider { - - bool HasSecurityDeclarations { get; } - Collection SecurityDeclarations { get; } - } - - [DebuggerDisplay ("{AttributeType}")] - public sealed class SecurityAttribute : ICustomAttribute { - - TypeReference attribute_type; - - internal Collection fields; - internal Collection properties; - - public TypeReference AttributeType { - get { return attribute_type; } - set { attribute_type = value; } - } - - public bool HasFields { - get { return !fields.IsNullOrEmpty (); } - } - - public Collection Fields { - get { - if (fields == null) - Interlocked.CompareExchange (ref fields, new Collection (), null); - - return fields; - } - } - - public bool HasProperties { - get { return !properties.IsNullOrEmpty (); } - } - - public Collection Properties { - get { - if (properties == null) - Interlocked.CompareExchange (ref properties, new Collection (), null); - - return properties; - } - } - - public SecurityAttribute (TypeReference attributeType) - { - this.attribute_type = attributeType; - } - - bool ICustomAttribute.HasConstructorArguments { - get { return false; } - } - - Collection ICustomAttribute.ConstructorArguments { - get { throw new NotSupportedException (); } - } - } - - public sealed class SecurityDeclaration { - - readonly internal uint signature; - byte [] blob; - readonly ModuleDefinition module; - - internal bool resolved; - SecurityAction action; - internal Collection security_attributes; - - public SecurityAction Action { - get { return action; } - set { action = value; } - } - - public bool HasSecurityAttributes { - get { - Resolve (); - - return !security_attributes.IsNullOrEmpty (); - } - } - - public Collection SecurityAttributes { - get { - Resolve (); - - if (security_attributes == null) - Interlocked.CompareExchange (ref security_attributes, new Collection (), null); - - return security_attributes; - } - } - - internal bool HasImage { - get { return module != null && module.HasImage; } - } - - internal SecurityDeclaration (SecurityAction action, uint signature, ModuleDefinition module) - { - this.action = action; - this.signature = signature; - this.module = module; - } - - public SecurityDeclaration (SecurityAction action) - { - this.action = action; - this.resolved = true; - } - - public SecurityDeclaration (SecurityAction action, byte [] blob) - { - this.action = action; - this.resolved = false; - this.blob = blob; - } - - public byte [] GetBlob () - { - if (blob != null) - return blob; - - if (!HasImage || signature == 0) - throw new NotSupportedException (); - - return module.Read (ref blob, this, (declaration, reader) => reader.ReadSecurityDeclarationBlob (declaration.signature)); - } - - void Resolve () - { - if (resolved || !HasImage) - return; - - lock (module.SyncRoot) { - - if (resolved) - return; - - module.Read (this, (declaration, reader) => reader.ReadSecurityDeclarationSignature (declaration)); - resolved = true; - } - } - } - - static partial class Mixin { - - public static bool GetHasSecurityDeclarations ( - this ISecurityDeclarationProvider self, - ModuleDefinition module) - { - return module.HasImage () && module.Read (self, (provider, reader) => reader.HasSecurityDeclarations (provider)); - } - - public static Collection GetSecurityDeclarations ( - this ISecurityDeclarationProvider self, - ref Collection variable, - ModuleDefinition module) - { - if (module.HasImage) - return module.Read (ref variable, self, (provider, reader) => reader.ReadSecurityDeclarations (provider)); - - Interlocked.CompareExchange (ref variable, new Collection (), null); - return variable; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SecurityDeclaration.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SecurityDeclaration.cs.meta deleted file mode 100644 index 67a6b92..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SecurityDeclaration.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7a39c3df615f71b409a5aa3d102fb35e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SentinelType.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SentinelType.cs deleted file mode 100644 index 24e3840..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SentinelType.cs +++ /dev/null @@ -1,35 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -using MD = MonoFN.Cecil.Metadata; - -namespace MonoFN.Cecil { - - public sealed class SentinelType : TypeSpecification { - - public override bool IsValueType { - get { return false; } - set { throw new InvalidOperationException (); } - } - - public override bool IsSentinel { - get { return true; } - } - - public SentinelType (TypeReference type) - : base (type) - { - Mixin.CheckType (type); - this.etype = MD.ElementType.Sentinel; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SentinelType.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SentinelType.cs.meta deleted file mode 100644 index f025abf..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/SentinelType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 31522df8b7c72c1499a3fb951e73a69a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TargetRuntime.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TargetRuntime.cs deleted file mode 100644 index d2c48f3..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TargetRuntime.cs +++ /dev/null @@ -1,19 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public enum TargetRuntime { - Net_1_0, - Net_1_1, - Net_2_0, - Net_4_0, - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TargetRuntime.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TargetRuntime.cs.meta deleted file mode 100644 index 9192b08..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TargetRuntime.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 64ac90055dca01347b6ed93dff5e4284 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Treatments.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Treatments.cs deleted file mode 100644 index 4b65d6a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Treatments.cs +++ /dev/null @@ -1,61 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - [Flags] - enum TypeDefinitionTreatment { - None = 0x0, - - KindMask = 0xf, - NormalType = 0x1, - NormalAttribute = 0x2, - UnmangleWindowsRuntimeName = 0x3, - PrefixWindowsRuntimeName = 0x4, - RedirectToClrType = 0x5, - RedirectToClrAttribute = 0x6, - RedirectImplementedMethods = 0x7, - - Abstract = 0x10, - Internal = 0x20, - } - - enum TypeReferenceTreatment { - None = 0x0, - SystemDelegate = 0x1, - SystemAttribute = 0x2, - UseProjectionInfo = 0x3, - } - - [Flags] - enum MethodDefinitionTreatment { - None = 0x0, - Abstract = 0x2, - Private = 0x4, - Public = 0x8, - Runtime = 0x10, - InternalCall = 0x20, - } - - enum FieldDefinitionTreatment { - None = 0x0, - Public = 0x1, - } - - enum CustomAttributeValueTreatment { - None = 0x0, - AllowSingle = 0x1, - AllowMultiple = 0x2, - VersionAttribute = 0x3, - DeprecatedAttribute = 0x4, - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Treatments.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Treatments.cs.meta deleted file mode 100644 index d9698b7..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Treatments.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d2bba6ea16ba63147b7bff91a65ad5fa -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeAttributes.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeAttributes.cs deleted file mode 100644 index dae187b..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeAttributes.cs +++ /dev/null @@ -1,63 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - [Flags] - public enum TypeAttributes : uint { - // Visibility attributes - VisibilityMask = 0x00000007, // Use this mask to retrieve visibility information - NotPublic = 0x00000000, // Class has no public scope - Public = 0x00000001, // Class has public scope - NestedPublic = 0x00000002, // Class is nested with public visibility - NestedPrivate = 0x00000003, // Class is nested with private visibility - NestedFamily = 0x00000004, // Class is nested with family visibility - NestedAssembly = 0x00000005, // Class is nested with assembly visibility - NestedFamANDAssem = 0x00000006, // Class is nested with family and assembly visibility - NestedFamORAssem = 0x00000007, // Class is nested with family or assembly visibility - - // Class layout attributes - LayoutMask = 0x00000018, // Use this mask to retrieve class layout information - AutoLayout = 0x00000000, // Class fields are auto-laid out - SequentialLayout = 0x00000008, // Class fields are laid out sequentially - ExplicitLayout = 0x00000010, // Layout is supplied explicitly - - // Class semantics attributes - ClassSemanticMask = 0x00000020, // Use this mask to retrieve class semantics information - Class = 0x00000000, // Type is a class - Interface = 0x00000020, // Type is an interface - - // Special semantics in addition to class semantics - Abstract = 0x00000080, // Class is abstract - Sealed = 0x00000100, // Class cannot be extended - SpecialName = 0x00000400, // Class name is special - - // Implementation attributes - Import = 0x00001000, // Class/Interface is imported - Serializable = 0x00002000, // Class is serializable - WindowsRuntime = 0x00004000, // Windows Runtime type - - // String formatting attributes - StringFormatMask = 0x00030000, // Use this mask to retrieve string information for native interop - AnsiClass = 0x00000000, // LPSTR is interpreted as ANSI - UnicodeClass = 0x00010000, // LPSTR is interpreted as Unicode - AutoClass = 0x00020000, // LPSTR is interpreted automatically - - // Class initialization attributes - BeforeFieldInit = 0x00100000, // Initialize the class before first static field access - - // Additional flags - RTSpecialName = 0x00000800, // CLI provides 'special' behavior, depending upon the name of the Type - HasSecurity = 0x00040000, // Type has security associate with it - Forwarder = 0x00200000, // Exported type is a type forwarder - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeAttributes.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeAttributes.cs.meta deleted file mode 100644 index eb01e16..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeAttributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a634580522059d74bb5ad1f997af1284 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeComparisonMode.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeComparisonMode.cs deleted file mode 100644 index b61e8aa..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeComparisonMode.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace MonoFN.Cecil { - internal enum TypeComparisonMode { - Exact, - SignatureOnly, - - /// - /// Types can be in different assemblies, as long as the module, assembly, and type names match they will be considered equal - /// - SignatureOnlyLoose - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeComparisonMode.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeComparisonMode.cs.meta deleted file mode 100644 index 235e452..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeComparisonMode.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3777ff31cb318a8488a68226f53f7381 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinition.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinition.cs deleted file mode 100644 index 6562ecc..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinition.cs +++ /dev/null @@ -1,618 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Metadata; -using MonoFN.Collections.Generic; -using System; -using System.Threading; - -namespace MonoFN.Cecil { - - public sealed class TypeDefinition : TypeReference, IMemberDefinition, ISecurityDeclarationProvider { - - uint attributes; - TypeReference base_type; - internal Range fields_range; - internal Range methods_range; - - short packing_size = Mixin.NotResolvedMarker; - int class_size = Mixin.NotResolvedMarker; - - InterfaceImplementationCollection interfaces; - Collection nested_types; - Collection methods; - Collection fields; - Collection events; - Collection properties; - Collection custom_attributes; - Collection security_declarations; - - public TypeAttributes Attributes { - get { return (TypeAttributes)attributes; } - set { - if (IsWindowsRuntimeProjection && (ushort)value != attributes) - throw new InvalidOperationException (); - - attributes = (uint)value; - } - } - - public TypeReference BaseType { - get { return base_type; } - set { base_type = value; } - } - - public override string Name { - get { return base.Name; } - set { - if (IsWindowsRuntimeProjection && value != base.Name) - throw new InvalidOperationException (); - - base.Name = value; - } - } - - void ResolveLayout () - { - if (!HasImage) { - packing_size = Mixin.NoDataMarker; - class_size = Mixin.NoDataMarker; - return; - } - - lock (Module.SyncRoot) { - if (packing_size != Mixin.NotResolvedMarker || class_size != Mixin.NotResolvedMarker) - return; - - var row = Module.Read (this, (type, reader) => reader.ReadTypeLayout (type)); - - packing_size = row.Col1; - class_size = row.Col2; - } - } - - public bool HasLayoutInfo { - get { - if (packing_size >= 0 || class_size >= 0) - return true; - - ResolveLayout (); - - return packing_size >= 0 || class_size >= 0; - } - } - - public short PackingSize { - get { - if (packing_size >= 0) - return packing_size; - - ResolveLayout (); - - return packing_size >= 0 ? packing_size : (short)-1; - } - set { packing_size = value; } - } - - public int ClassSize { - get { - if (class_size >= 0) - return class_size; - - ResolveLayout (); - - return class_size >= 0 ? class_size : -1; - } - set { class_size = value; } - } - - public bool HasInterfaces { - get { - if (interfaces != null) - return interfaces.Count > 0; - - return HasImage && Module.Read (this, (type, reader) => reader.HasInterfaces (type)); - } - } - - public Collection Interfaces { - get { - if (interfaces != null) - return interfaces; - - if (HasImage) - return Module.Read (ref interfaces, this, (type, reader) => reader.ReadInterfaces (type)); - - Interlocked.CompareExchange (ref interfaces, new InterfaceImplementationCollection (this), null); - return interfaces; - } - } - - public bool HasNestedTypes { - get { - if (nested_types != null) - return nested_types.Count > 0; - - return HasImage && Module.Read (this, (type, reader) => reader.HasNestedTypes (type)); - } - } - - public Collection NestedTypes { - get { - if (nested_types != null) - return nested_types; - - if (HasImage) - return Module.Read (ref nested_types, this, (type, reader) => reader.ReadNestedTypes (type)); - - Interlocked.CompareExchange (ref nested_types, new MemberDefinitionCollection (this), null); - return nested_types; - } - } - - public bool HasMethods { - get { - if (methods != null) - return methods.Count > 0; - - return HasImage && methods_range.Length > 0; - } - } - - public Collection Methods { - get { - if (methods != null) - return methods; - - if (HasImage) - return Module.Read (ref methods, this, (type, reader) => reader.ReadMethods (type)); - - Interlocked.CompareExchange (ref methods, new MemberDefinitionCollection (this), null); - return methods; - } - } - - public bool HasFields { - get { - if (fields != null) - return fields.Count > 0; - - return HasImage && fields_range.Length > 0; - } - } - - public Collection Fields { - get { - if (fields != null) - return fields; - - if (HasImage) - return Module.Read (ref fields, this, (type, reader) => reader.ReadFields (type)); - - Interlocked.CompareExchange (ref fields, new MemberDefinitionCollection (this), null); - return fields; - } - } - - public bool HasEvents { - get { - if (events != null) - return events.Count > 0; - - return HasImage && Module.Read (this, (type, reader) => reader.HasEvents (type)); - } - } - - public Collection Events { - get { - if (events != null) - return events; - - if (HasImage) - return Module.Read (ref events, this, (type, reader) => reader.ReadEvents (type)); - - Interlocked.CompareExchange (ref events, new MemberDefinitionCollection (this), null); - return events; - } - } - - public bool HasProperties { - get { - if (properties != null) - return properties.Count > 0; - - return HasImage && Module.Read (this, (type, reader) => reader.HasProperties (type)); - } - } - - public Collection Properties { - get { - if (properties != null) - return properties; - - if (HasImage) - return Module.Read (ref properties, this, (type, reader) => reader.ReadProperties (type)); - - Interlocked.CompareExchange (ref properties, new MemberDefinitionCollection (this), null); - return properties; - } - } - - public bool HasSecurityDeclarations { - get { - if (security_declarations != null) - return security_declarations.Count > 0; - - return this.GetHasSecurityDeclarations (Module); - } - } - - public Collection SecurityDeclarations { - get { return security_declarations ?? (this.GetSecurityDeclarations (ref security_declarations, Module)); } - } - - public bool HasCustomAttributes { - get { - if (custom_attributes != null) - return custom_attributes.Count > 0; - - return this.GetHasCustomAttributes (Module); - } - } - - public Collection CustomAttributes { - get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); } - } - - public override bool HasGenericParameters { - get { - if (generic_parameters != null) - return generic_parameters.Count > 0; - - return this.GetHasGenericParameters (Module); - } - } - - public override Collection GenericParameters { - get { return generic_parameters ?? (this.GetGenericParameters (ref generic_parameters, Module)); } - } - - #region TypeAttributes - - public bool IsNotPublic { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NotPublic); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NotPublic, value); } - } - - public bool IsPublic { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.Public); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.Public, value); } - } - - public bool IsNestedPublic { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPublic); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPublic, value); } - } - - public bool IsNestedPrivate { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPrivate); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedPrivate, value); } - } - - public bool IsNestedFamily { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamily); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamily, value); } - } - - public bool IsNestedAssembly { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedAssembly); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedAssembly, value); } - } - - public bool IsNestedFamilyAndAssembly { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamANDAssem); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamANDAssem, value); } - } - - public bool IsNestedFamilyOrAssembly { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamORAssem); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.VisibilityMask, (uint)TypeAttributes.NestedFamORAssem, value); } - } - - public bool IsAutoLayout { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.AutoLayout); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.AutoLayout, value); } - } - - public bool IsSequentialLayout { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.SequentialLayout); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.SequentialLayout, value); } - } - - public bool IsExplicitLayout { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.ExplicitLayout); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.LayoutMask, (uint)TypeAttributes.ExplicitLayout, value); } - } - - public bool IsClass { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Class); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Class, value); } - } - - public bool IsInterface { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Interface); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.ClassSemanticMask, (uint)TypeAttributes.Interface, value); } - } - - public bool IsAbstract { - get { return attributes.GetAttributes ((uint)TypeAttributes.Abstract); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.Abstract, value); } - } - - public bool IsSealed { - get { return attributes.GetAttributes ((uint)TypeAttributes.Sealed); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.Sealed, value); } - } - - public bool IsSpecialName { - get { return attributes.GetAttributes ((uint)TypeAttributes.SpecialName); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.SpecialName, value); } - } - - public bool IsImport { - get { return attributes.GetAttributes ((uint)TypeAttributes.Import); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.Import, value); } - } - - public bool IsSerializable { - get { return attributes.GetAttributes ((uint)TypeAttributes.Serializable); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.Serializable, value); } - } - - public bool IsWindowsRuntime { - get { return attributes.GetAttributes ((uint)TypeAttributes.WindowsRuntime); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.WindowsRuntime, value); } - } - - public bool IsAnsiClass { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AnsiClass); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AnsiClass, value); } - } - - public bool IsUnicodeClass { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.UnicodeClass); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.UnicodeClass, value); } - } - - public bool IsAutoClass { - get { return attributes.GetMaskedAttributes ((uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AutoClass); } - set { attributes = attributes.SetMaskedAttributes ((uint)TypeAttributes.StringFormatMask, (uint)TypeAttributes.AutoClass, value); } - } - - public bool IsBeforeFieldInit { - get { return attributes.GetAttributes ((uint)TypeAttributes.BeforeFieldInit); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.BeforeFieldInit, value); } - } - - public bool IsRuntimeSpecialName { - get { return attributes.GetAttributes ((uint)TypeAttributes.RTSpecialName); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.RTSpecialName, value); } - } - - public bool HasSecurity { - get { return attributes.GetAttributes ((uint)TypeAttributes.HasSecurity); } - set { attributes = attributes.SetAttributes ((uint)TypeAttributes.HasSecurity, value); } - } - - #endregion - - public bool IsEnum { - get { return base_type != null && base_type.IsTypeOf ("System", "Enum"); } - } - - public override bool IsValueType { - get { - if (base_type == null) - return false; - - return base_type.IsTypeOf ("System", "Enum") || (base_type.IsTypeOf ("System", "ValueType") && !this.IsTypeOf ("System", "Enum")); - } - set { - throw new NotSupportedException (); - } - } - - public override bool IsPrimitive { - get { - ElementType primitive_etype; - return MetadataSystem.TryGetPrimitiveElementType (this, out primitive_etype) && primitive_etype.IsPrimitive (); - } - } - - public override MetadataType MetadataType { - get { - ElementType primitive_etype; - if (MetadataSystem.TryGetPrimitiveElementType (this, out primitive_etype)) - return (MetadataType)primitive_etype; - - return base.MetadataType; - } - } - - public override bool IsDefinition { - get { return true; } - } - - public new TypeDefinition DeclaringType { - get { return (TypeDefinition)base.DeclaringType; } - set { base.DeclaringType = value; } - } - - internal new TypeDefinitionProjection WindowsRuntimeProjection { - get { return (TypeDefinitionProjection)projection; } - set { projection = value; } - } - - public TypeDefinition (string @namespace, string name, TypeAttributes attributes) - : base (@namespace, name) - { - this.attributes = (uint)attributes; - this.token = new MetadataToken (TokenType.TypeDef); - } - - public TypeDefinition (string @namespace, string name, TypeAttributes attributes, TypeReference baseType) : - this (@namespace, name, attributes) - { - this.BaseType = baseType; - } - - protected override void ClearFullName () - { - base.ClearFullName (); - - if (!HasNestedTypes) - return; - - var nested_types = this.NestedTypes; - - for (int i = 0; i < nested_types.Count; i++) - nested_types [i].ClearFullName (); - } - - public override TypeDefinition Resolve () - { - return this; - } - } - - public sealed class InterfaceImplementation : ICustomAttributeProvider { - internal TypeDefinition type; - internal MetadataToken token; - - TypeReference interface_type; - Collection custom_attributes; - - public TypeReference InterfaceType { - get { return interface_type; } - set { interface_type = value; } - } - - public bool HasCustomAttributes { - get { - if (custom_attributes != null) - return custom_attributes.Count > 0; - - if (type == null) - return false; - - return this.GetHasCustomAttributes (type.Module); - } - } - - public Collection CustomAttributes { - get { - if (type == null) { - if (custom_attributes == null) - Interlocked.CompareExchange (ref custom_attributes, new Collection (), null); - return custom_attributes; - } - - return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, type.Module)); - } - } - - public MetadataToken MetadataToken { - get { return token; } - set { token = value; } - } - - internal InterfaceImplementation (TypeReference interfaceType, MetadataToken token) - { - this.interface_type = interfaceType; - this.token = token; - } - - public InterfaceImplementation (TypeReference interfaceType) - { - Mixin.CheckType (interfaceType, Mixin.Argument.interfaceType); - - this.interface_type = interfaceType; - this.token = new MetadataToken (TokenType.InterfaceImpl); - } - } - - class InterfaceImplementationCollection : Collection { - readonly TypeDefinition type; - - internal InterfaceImplementationCollection (TypeDefinition type) - { - this.type = type; - } - - internal InterfaceImplementationCollection (TypeDefinition type, int length) - : base (length) - { - this.type = type; - } - - protected override void OnAdd (InterfaceImplementation item, int index) - { - item.type = type; - } - - protected override void OnInsert (InterfaceImplementation item, int index) - { - item.type = type; - } - - protected override void OnSet (InterfaceImplementation item, int index) - { - item.type = type; - } - - protected override void OnRemove (InterfaceImplementation item, int index) - { - item.type = null; - } - } - - static partial class Mixin { - - public static TypeReference GetEnumUnderlyingType (this TypeDefinition self) - { - var fields = self.Fields; - - for (int i = 0; i < fields.Count; i++) { - var field = fields [i]; - if (!field.IsStatic) - return field.FieldType; - } - - throw new ArgumentException (); - } - - public static TypeDefinition GetNestedType (this TypeDefinition self, string fullname) - { - if (!self.HasNestedTypes) - return null; - - var nested_types = self.NestedTypes; - - for (int i = 0; i < nested_types.Count; i++) { - var nested_type = nested_types [i]; - - if (nested_type.TypeFullName () == fullname) - return nested_type; - } - - return null; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinition.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinition.cs.meta deleted file mode 100644 index c55bd55..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4616a4ea6dc219f419ae9ba98109f98c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinitionCollection.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinitionCollection.cs deleted file mode 100644 index aa07389..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinitionCollection.cs +++ /dev/null @@ -1,98 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Metadata; -using MonoFN.Collections.Generic; -using System; -using System.Collections.Generic; - -namespace MonoFN.Cecil { - - using Slot = Row; - - sealed class TypeDefinitionCollection : Collection { - - readonly ModuleDefinition container; - readonly Dictionary name_cache; - - internal TypeDefinitionCollection (ModuleDefinition container) - { - this.container = container; - this.name_cache = new Dictionary (new RowEqualityComparer ()); - } - - internal TypeDefinitionCollection (ModuleDefinition container, int capacity) - : base (capacity) - { - this.container = container; - this.name_cache = new Dictionary (capacity, new RowEqualityComparer ()); - } - - protected override void OnAdd (TypeDefinition item, int index) - { - Attach (item); - } - - protected override void OnSet (TypeDefinition item, int index) - { - Attach (item); - } - - protected override void OnInsert (TypeDefinition item, int index) - { - Attach (item); - } - - protected override void OnRemove (TypeDefinition item, int index) - { - Detach (item); - } - - protected override void OnClear () - { - foreach (var type in this) - Detach (type); - } - - void Attach (TypeDefinition type) - { - if (type.Module != null && type.Module != container) - throw new ArgumentException ("Type already attached"); - - type.module = container; - type.scope = container; - name_cache [new Slot (type.Namespace, type.Name)] = type; - } - - void Detach (TypeDefinition type) - { - type.module = null; - type.scope = null; - name_cache.Remove (new Slot (type.Namespace, type.Name)); - } - - public TypeDefinition GetType (string fullname) - { - string @namespace, name; - TypeParser.SplitFullName (fullname, out @namespace, out name); - - return GetType (@namespace, name); - } - - public TypeDefinition GetType (string @namespace, string name) - { - TypeDefinition type; - if (name_cache.TryGetValue (new Slot (@namespace, name), out type)) - return type; - - return null; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinitionCollection.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinitionCollection.cs.meta deleted file mode 100644 index e800734..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeDefinitionCollection.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4440ec34ba0da7b4aac0fc4c009035aa -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeParser.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeParser.cs deleted file mode 100644 index c533b98..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeParser.cs +++ /dev/null @@ -1,531 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Metadata; -using System; -using System.Text; - -namespace MonoFN.Cecil { - - class TypeParser { - - class Type { - public const int Ptr = -1; - public const int ByRef = -2; - public const int SzArray = -3; - - public string type_fullname; - public string [] nested_names; - public int arity; - public int [] specs; - public Type [] generic_arguments; - public string assembly; - } - - readonly string fullname; - readonly int length; - - int position; - - TypeParser (string fullname) - { - this.fullname = fullname; - this.length = fullname.Length; - } - - Type ParseType (bool fq_name) - { - var type = new Type (); - type.type_fullname = ParsePart (); - - type.nested_names = ParseNestedNames (); - - if (TryGetArity (type)) - type.generic_arguments = ParseGenericArguments (type.arity); - - type.specs = ParseSpecs (); - - if (fq_name) - type.assembly = ParseAssemblyName (); - - return type; - } - - static bool TryGetArity (Type type) - { - int arity = 0; - - TryAddArity (type.type_fullname, ref arity); - - var nested_names = type.nested_names; - if (!nested_names.IsNullOrEmpty ()) { - for (int i = 0; i < nested_names.Length; i++) - TryAddArity (nested_names [i], ref arity); - } - - type.arity = arity; - return arity > 0; - } - - static bool TryGetArity (string name, out int arity) - { - arity = 0; - var index = name.LastIndexOf ('`'); - if (index == -1) - return false; - - return ParseInt32 (name.Substring (index + 1), out arity); - } - - static bool ParseInt32 (string value, out int result) - { - return int.TryParse (value, out result); - } - - static void TryAddArity (string name, ref int arity) - { - int type_arity; - if (!TryGetArity (name, out type_arity)) - return; - - arity += type_arity; - } - - string ParsePart () - { - var part = new StringBuilder (); - while (position < length && !IsDelimiter (fullname [position])) { - if (fullname [position] == '\\') - position++; - - part.Append (fullname [position++]); - } - - return part.ToString (); - } - - static bool IsDelimiter (char chr) - { - return "+,[]*&".IndexOf (chr) != -1; - } - - void TryParseWhiteSpace () - { - while (position < length && Char.IsWhiteSpace (fullname [position])) - position++; - } - - string [] ParseNestedNames () - { - string [] nested_names = null; - while (TryParse ('+')) - Add (ref nested_names, ParsePart ()); - - return nested_names; - } - - bool TryParse (char chr) - { - if (position < length && fullname [position] == chr) { - position++; - return true; - } - - return false; - } - - static void Add (ref T [] array, T item) - { - array = array.Add (item); - } - - int [] ParseSpecs () - { - int [] specs = null; - - while (position < length) { - switch (fullname [position]) { - case '*': - position++; - Add (ref specs, Type.Ptr); - break; - case '&': - position++; - Add (ref specs, Type.ByRef); - break; - case '[': - position++; - switch (fullname [position]) { - case ']': - position++; - Add (ref specs, Type.SzArray); - break; - case '*': - position++; - Add (ref specs, 1); - break; - default: - var rank = 1; - while (TryParse (',')) - rank++; - - Add (ref specs, rank); - - TryParse (']'); - break; - } - break; - default: - return specs; - } - } - - return specs; - } - - Type [] ParseGenericArguments (int arity) - { - Type [] generic_arguments = null; - - if (position == length || fullname [position] != '[') - return generic_arguments; - - TryParse ('['); - - for (int i = 0; i < arity; i++) { - var fq_argument = TryParse ('['); - Add (ref generic_arguments, ParseType (fq_argument)); - if (fq_argument) - TryParse (']'); - - TryParse (','); - TryParseWhiteSpace (); - } - - TryParse (']'); - - return generic_arguments; - } - - string ParseAssemblyName () - { - if (!TryParse (',')) - return string.Empty; - - TryParseWhiteSpace (); - - var start = position; - while (position < length) { - var chr = fullname [position]; - if (chr == '[' || chr == ']') - break; - - position++; - } - - return fullname.Substring (start, position - start); - } - - public static TypeReference ParseType (ModuleDefinition module, string fullname, bool typeDefinitionOnly = false) - { - if (string.IsNullOrEmpty (fullname)) - return null; - - var parser = new TypeParser (fullname); - return GetTypeReference (module, parser.ParseType (true), typeDefinitionOnly); - } - - static TypeReference GetTypeReference (ModuleDefinition module, Type type_info, bool type_def_only) - { - TypeReference type; - if (!TryGetDefinition (module, type_info, out type)) { - if (type_def_only) - return null; - - type = CreateReference (type_info, module, GetMetadataScope (module, type_info)); - } - - return CreateSpecs (type, type_info); - } - - static TypeReference CreateSpecs (TypeReference type, Type type_info) - { - type = TryCreateGenericInstanceType (type, type_info); - - var specs = type_info.specs; - if (specs.IsNullOrEmpty ()) - return type; - - for (int i = 0; i < specs.Length; i++) { - switch (specs [i]) { - case Type.Ptr: - type = new PointerType (type); - break; - case Type.ByRef: - type = new ByReferenceType (type); - break; - case Type.SzArray: - type = new ArrayType (type); - break; - default: - var array = new ArrayType (type); - array.Dimensions.Clear (); - - for (int j = 0; j < specs [i]; j++) - array.Dimensions.Add (new ArrayDimension ()); - - type = array; - break; - } - } - - return type; - } - - static TypeReference TryCreateGenericInstanceType (TypeReference type, Type type_info) - { - var generic_arguments = type_info.generic_arguments; - if (generic_arguments.IsNullOrEmpty ()) - return type; - - var instance = new GenericInstanceType (type, generic_arguments.Length); - var instance_arguments = instance.GenericArguments; - - for (int i = 0; i < generic_arguments.Length; i++) - instance_arguments.Add (GetTypeReference (type.Module, generic_arguments [i], false)); - - return instance; - } - - public static void SplitFullName (string fullname, out string @namespace, out string name) - { - var last_dot = fullname.LastIndexOf ('.'); - - if (last_dot == -1) { - @namespace = string.Empty; - name = fullname; - } else { - @namespace = fullname.Substring (0, last_dot); - name = fullname.Substring (last_dot + 1); - } - } - - static TypeReference CreateReference (Type type_info, ModuleDefinition module, IMetadataScope scope) - { - string @namespace, name; - SplitFullName (type_info.type_fullname, out @namespace, out name); - - var type = new TypeReference (@namespace, name, module, scope); - MetadataSystem.TryProcessPrimitiveTypeReference (type); - - AdjustGenericParameters (type); - - var nested_names = type_info.nested_names; - if (nested_names.IsNullOrEmpty ()) - return type; - - for (int i = 0; i < nested_names.Length; i++) { - type = new TypeReference (string.Empty, nested_names [i], module, null) { - DeclaringType = type, - }; - - AdjustGenericParameters (type); - } - - return type; - } - - static void AdjustGenericParameters (TypeReference type) - { - int arity; - if (!TryGetArity (type.Name, out arity)) - return; - - for (int i = 0; i < arity; i++) - type.GenericParameters.Add (new GenericParameter (type)); - } - - static IMetadataScope GetMetadataScope (ModuleDefinition module, Type type_info) - { - if (string.IsNullOrEmpty (type_info.assembly)) - return module.TypeSystem.CoreLibrary; - - AssemblyNameReference match; - var reference = AssemblyNameReference.Parse (type_info.assembly); - - return module.TryGetAssemblyNameReference (reference, out match) - ? match - : reference; - } - - static bool TryGetDefinition (ModuleDefinition module, Type type_info, out TypeReference type) - { - type = null; - if (!TryCurrentModule (module, type_info)) - return false; - - var typedef = module.GetType (type_info.type_fullname); - if (typedef == null) - return false; - - var nested_names = type_info.nested_names; - if (!nested_names.IsNullOrEmpty ()) { - for (int i = 0; i < nested_names.Length; i++) { - var nested_type = typedef.GetNestedType (nested_names [i]); - if (nested_type == null) - return false; - - typedef = nested_type; - } - } - - type = typedef; - return true; - } - - static bool TryCurrentModule (ModuleDefinition module, Type type_info) - { - if (string.IsNullOrEmpty (type_info.assembly)) - return true; - - if (module.assembly != null && module.assembly.Name.FullName == type_info.assembly) - return true; - - return false; - } - - public static string ToParseable (TypeReference type, bool top_level = true) - { - if (type == null) - return null; - - var name = new StringBuilder (); - AppendType (type, name, true, top_level); - return name.ToString (); - } - - static void AppendNamePart (string part, StringBuilder name) - { - foreach (var c in part) { - if (IsDelimiter (c)) - name.Append ('\\'); - - name.Append (c); - } - } - - static void AppendType (TypeReference type, StringBuilder name, bool fq_name, bool top_level) - { - var element_type = type.GetElementType (); - - var declaring_type = element_type.DeclaringType; - if (declaring_type != null) { - AppendType (declaring_type, name, false, top_level); - name.Append ('+'); - } - - var @namespace = type.Namespace; - if (!string.IsNullOrEmpty (@namespace)) { - AppendNamePart (@namespace, name); - name.Append ('.'); - } - - AppendNamePart (element_type.Name, name); - - if (!fq_name) - return; - - if (type.IsTypeSpecification ()) - AppendTypeSpecification ((TypeSpecification)type, name); - - if (RequiresFullyQualifiedName (type, top_level)) { - name.Append (", "); - name.Append (GetScopeFullName (type)); - } - } - - static string GetScopeFullName (TypeReference type) - { - var scope = type.Scope; - switch (scope.MetadataScopeType) { - case MetadataScopeType.AssemblyNameReference: - return ((AssemblyNameReference)scope).FullName; - case MetadataScopeType.ModuleDefinition: - return ((ModuleDefinition)scope).Assembly.Name.FullName; - } - - throw new ArgumentException (); - } - - static void AppendTypeSpecification (TypeSpecification type, StringBuilder name) - { - if (type.ElementType.IsTypeSpecification ()) - AppendTypeSpecification ((TypeSpecification)type.ElementType, name); - - switch (type.etype) { - case ElementType.Ptr: - name.Append ('*'); - break; - case ElementType.ByRef: - name.Append ('&'); - break; - case ElementType.SzArray: - case ElementType.Array: - var array = (ArrayType)type; - if (array.IsVector) { - name.Append ("[]"); - } else { - name.Append ('['); - for (int i = 1; i < array.Rank; i++) - name.Append (','); - name.Append (']'); - } - break; - case ElementType.GenericInst: - var instance = (GenericInstanceType)type; - var arguments = instance.GenericArguments; - - name.Append ('['); - - for (int i = 0; i < arguments.Count; i++) { - if (i > 0) - name.Append (','); - - var argument = arguments [i]; - var requires_fqname = argument.Scope != argument.Module; - - if (requires_fqname) - name.Append ('['); - - AppendType (argument, name, true, false); - - if (requires_fqname) - name.Append (']'); - } - - name.Append (']'); - break; - default: - return; - } - } - - static bool RequiresFullyQualifiedName (TypeReference type, bool top_level) - { - if (type.Scope == type.Module) - return false; - - if (type.Scope.Name == "mscorlib" && top_level) - return false; - - return true; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeParser.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeParser.cs.meta deleted file mode 100644 index 0cc685b..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeParser.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 14cea45910a5fc94ca89429bd0587148 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReference.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReference.cs deleted file mode 100644 index 993daf5..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReference.cs +++ /dev/null @@ -1,352 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Metadata; -using MonoFN.Collections.Generic; -using System; -using System.Threading; - -namespace MonoFN.Cecil { - - public enum MetadataType : byte { - Void = ElementType.Void, - Boolean = ElementType.Boolean, - Char = ElementType.Char, - SByte = ElementType.I1, - Byte = ElementType.U1, - Int16 = ElementType.I2, - UInt16 = ElementType.U2, - Int32 = ElementType.I4, - UInt32 = ElementType.U4, - Int64 = ElementType.I8, - UInt64 = ElementType.U8, - Single = ElementType.R4, - Double = ElementType.R8, - String = ElementType.String, - Pointer = ElementType.Ptr, - ByReference = ElementType.ByRef, - ValueType = ElementType.ValueType, - Class = ElementType.Class, - Var = ElementType.Var, - Array = ElementType.Array, - GenericInstance = ElementType.GenericInst, - TypedByReference = ElementType.TypedByRef, - IntPtr = ElementType.I, - UIntPtr = ElementType.U, - FunctionPointer = ElementType.FnPtr, - Object = ElementType.Object, - MVar = ElementType.MVar, - RequiredModifier = ElementType.CModReqD, - OptionalModifier = ElementType.CModOpt, - Sentinel = ElementType.Sentinel, - Pinned = ElementType.Pinned, - } - - public class TypeReference : MemberReference, IGenericParameterProvider, IGenericContext { - - string @namespace; - bool value_type; - internal IMetadataScope scope; - internal ModuleDefinition module; - - internal ElementType etype = ElementType.None; - - string fullname; - - protected Collection generic_parameters; - - public override string Name { - get { return base.Name; } - set { - if (IsWindowsRuntimeProjection && value != base.Name) - throw new InvalidOperationException ("Projected type reference name can't be changed."); - base.Name = value; - ClearFullName (); - } - } - - public virtual string Namespace { - get { return @namespace; } - set { - if (IsWindowsRuntimeProjection && value != @namespace) - throw new InvalidOperationException ("Projected type reference namespace can't be changed."); - @namespace = value; - ClearFullName (); - } - } - - public virtual bool IsValueType { - get { return value_type; } - set { value_type = value; } - } - - public override ModuleDefinition Module { - get { - if (module != null) - return module; - - var declaring_type = this.DeclaringType; - if (declaring_type != null) - return declaring_type.Module; - - return null; - } - } - - internal TypeReferenceProjection WindowsRuntimeProjection { - get { return (TypeReferenceProjection)projection; } - set { projection = value; } - } - - IGenericParameterProvider IGenericContext.Type { - get { return this; } - } - - IGenericParameterProvider IGenericContext.Method { - get { return null; } - } - - GenericParameterType IGenericParameterProvider.GenericParameterType { - get { return GenericParameterType.Type; } - } - - public virtual bool HasGenericParameters { - get { return !generic_parameters.IsNullOrEmpty (); } - } - - public virtual Collection GenericParameters { - get { - if (generic_parameters == null) - Interlocked.CompareExchange (ref generic_parameters, new GenericParameterCollection (this), null); - - return generic_parameters; - } - } - - public virtual IMetadataScope Scope { - get { - var declaring_type = this.DeclaringType; - if (declaring_type != null) - return declaring_type.Scope; - - return scope; - } - set { - var declaring_type = this.DeclaringType; - if (declaring_type != null) { - if (IsWindowsRuntimeProjection && value != declaring_type.Scope) - throw new InvalidOperationException ("Projected type scope can't be changed."); - declaring_type.Scope = value; - return; - } - - if (IsWindowsRuntimeProjection && value != scope) - throw new InvalidOperationException ("Projected type scope can't be changed."); - scope = value; - } - } - - public bool IsNested { - get { return this.DeclaringType != null; } - } - - public override TypeReference DeclaringType { - get { return base.DeclaringType; } - set { - if (IsWindowsRuntimeProjection && value != base.DeclaringType) - throw new InvalidOperationException ("Projected type declaring type can't be changed."); - base.DeclaringType = value; - ClearFullName (); - } - } - - public override string FullName { - get { - if (fullname != null) - return fullname; - - var new_fullname = this.TypeFullName (); - - if (IsNested) - new_fullname = DeclaringType.FullName + "/" + new_fullname; - Interlocked.CompareExchange (ref fullname, new_fullname, null); - return fullname; - } - } - - public virtual bool IsByReference { - get { return false; } - } - - public virtual bool IsPointer { - get { return false; } - } - - public virtual bool IsSentinel { - get { return false; } - } - - public virtual bool IsArray { - get { return false; } - } - - public virtual bool IsGenericParameter { - get { return false; } - } - - public virtual bool IsGenericInstance { - get { return false; } - } - - public virtual bool IsRequiredModifier { - get { return false; } - } - - public virtual bool IsOptionalModifier { - get { return false; } - } - - public virtual bool IsPinned { - get { return false; } - } - - public virtual bool IsFunctionPointer { - get { return false; } - } - - public virtual bool IsPrimitive { - get { return etype.IsPrimitive (); } - } - - public virtual MetadataType MetadataType { - get { - switch (etype) { - case ElementType.None: - return IsValueType ? MetadataType.ValueType : MetadataType.Class; - default: - return (MetadataType)etype; - } - } - } - - protected TypeReference (string @namespace, string name) - : base (name) - { - this.@namespace = @namespace ?? string.Empty; - this.token = new MetadataToken (TokenType.TypeRef, 0); - } - - public TypeReference (string @namespace, string name, ModuleDefinition module, IMetadataScope scope) - : this (@namespace, name) - { - this.module = module; - this.scope = scope; - } - - public TypeReference (string @namespace, string name, ModuleDefinition module, IMetadataScope scope, bool valueType) : - this (@namespace, name, module, scope) - { - value_type = valueType; - } - - protected virtual void ClearFullName () - { - this.fullname = null; - } - - public virtual TypeReference GetElementType () - { - return this; - } - - protected override IMemberDefinition ResolveDefinition () - { - return this.Resolve (); - } - - public new virtual TypeDefinition Resolve () - { - var module = this.Module; - if (module == null) - throw new NotSupportedException (); - - return module.Resolve (this); - } - } - - static partial class Mixin { - - public static bool IsPrimitive (this ElementType self) - { - switch (self) { - case ElementType.Boolean: - case ElementType.Char: - case ElementType.I: - case ElementType.U: - case ElementType.I1: - case ElementType.U1: - case ElementType.I2: - case ElementType.U2: - case ElementType.I4: - case ElementType.U4: - case ElementType.I8: - case ElementType.U8: - case ElementType.R4: - case ElementType.R8: - return true; - default: - return false; - } - } - - public static string TypeFullName (this TypeReference self) - { - return string.IsNullOrEmpty (self.Namespace) - ? self.Name - : self.Namespace + '.' + self.Name; - } - - public static bool IsTypeOf (this TypeReference self, string @namespace, string name) - { - return self.Name == name - && self.Namespace == @namespace; - } - - public static bool IsTypeSpecification (this TypeReference type) - { - switch (type.etype) { - case ElementType.Array: - case ElementType.ByRef: - case ElementType.CModOpt: - case ElementType.CModReqD: - case ElementType.FnPtr: - case ElementType.GenericInst: - case ElementType.MVar: - case ElementType.Pinned: - case ElementType.Ptr: - case ElementType.SzArray: - case ElementType.Sentinel: - case ElementType.Var: - return true; - } - - return false; - } - - public static TypeDefinition CheckedResolve (this TypeReference self) - { - var type = self.Resolve (); - if (type == null) - throw new ResolutionException (self); - - return type; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReference.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReference.cs.meta deleted file mode 100644 index 6133f4f..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReference.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: be8b0c2aa3d8d534a90ff392789fac67 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReferenceEqualityComparer.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReferenceEqualityComparer.cs deleted file mode 100644 index a399fba..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReferenceEqualityComparer.cs +++ /dev/null @@ -1,253 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace MonoFN.Cecil { - internal sealed class TypeReferenceEqualityComparer : EqualityComparer { - public override bool Equals (TypeReference x, TypeReference y) - { - return AreEqual (x, y); - } - - public override int GetHashCode (TypeReference obj) - { - return GetHashCodeFor (obj); - } - - public static bool AreEqual (TypeReference a, TypeReference b, TypeComparisonMode comparisonMode = TypeComparisonMode.Exact) - { - if (ReferenceEquals (a, b)) - return true; - - if (a == null || b == null) - return false; - - var aMetadataType = a.MetadataType; - var bMetadataType = b.MetadataType; - - if (aMetadataType == MetadataType.GenericInstance || bMetadataType == MetadataType.GenericInstance) { - if (aMetadataType != bMetadataType) - return false; - - return AreEqual ((GenericInstanceType)a, (GenericInstanceType)b, comparisonMode); - } - - if (aMetadataType == MetadataType.Array || bMetadataType == MetadataType.Array) { - if (aMetadataType != bMetadataType) - return false; - - var a1 = (ArrayType)a; - var b1 = (ArrayType)b; - if (a1.Rank != b1.Rank) - return false; - - return AreEqual (a1.ElementType, b1.ElementType, comparisonMode); - } - - if (aMetadataType == MetadataType.Var || bMetadataType == MetadataType.Var) { - if (aMetadataType != bMetadataType) - return false; - - return AreEqual ((GenericParameter)a, (GenericParameter)b, comparisonMode); - } - - if (aMetadataType == MetadataType.MVar || bMetadataType == MetadataType.MVar) { - if (aMetadataType != bMetadataType) - return false; - - return AreEqual ((GenericParameter)a, (GenericParameter)b, comparisonMode); - } - - if (aMetadataType == MetadataType.ByReference || bMetadataType == MetadataType.ByReference) { - if (aMetadataType != bMetadataType) - return false; - - return AreEqual (((ByReferenceType)a).ElementType, ((ByReferenceType)b).ElementType, comparisonMode); - } - - if (aMetadataType == MetadataType.Pointer || bMetadataType == MetadataType.Pointer) { - if (aMetadataType != bMetadataType) - return false; - - return AreEqual (((PointerType)a).ElementType, ((PointerType)b).ElementType, comparisonMode); - } - - if (aMetadataType == MetadataType.RequiredModifier || bMetadataType == MetadataType.RequiredModifier) { - if (aMetadataType != bMetadataType) - return false; - - var a1 = (RequiredModifierType)a; - var b1 = (RequiredModifierType)b; - - return AreEqual (a1.ModifierType, b1.ModifierType, comparisonMode) && AreEqual (a1.ElementType, b1.ElementType, comparisonMode); - } - - if (aMetadataType == MetadataType.OptionalModifier || bMetadataType == MetadataType.OptionalModifier) { - if (aMetadataType != bMetadataType) - return false; - - var a1 = (OptionalModifierType)a; - var b1 = (OptionalModifierType)b; - - return AreEqual (a1.ModifierType, b1.ModifierType, comparisonMode) && AreEqual (a1.ElementType, b1.ElementType, comparisonMode); - } - - if (aMetadataType == MetadataType.Pinned || bMetadataType == MetadataType.Pinned) { - if (aMetadataType != bMetadataType) - return false; - - return AreEqual (((PinnedType)a).ElementType, ((PinnedType)b).ElementType, comparisonMode); - } - - if (aMetadataType == MetadataType.Sentinel || bMetadataType == MetadataType.Sentinel) { - if (aMetadataType != bMetadataType) - return false; - - return AreEqual (((SentinelType)a).ElementType, ((SentinelType)b).ElementType, comparisonMode); - } - - if (!a.Name.Equals (b.Name) || !a.Namespace.Equals (b.Namespace)) - return false; - - var xDefinition = a.Resolve (); - var yDefinition = b.Resolve (); - - // For loose signature the types could be in different assemblies, as long as the type names match we will consider them equal - if (comparisonMode == TypeComparisonMode.SignatureOnlyLoose) { - if (xDefinition.Module.Name != yDefinition.Module.Name) - return false; - - if (xDefinition.Module.Assembly.Name.Name != yDefinition.Module.Assembly.Name.Name) - return false; - - return xDefinition.FullName == yDefinition.FullName; - } - - return xDefinition == yDefinition; - } - - static bool AreEqual (GenericParameter a, GenericParameter b, TypeComparisonMode comparisonMode = TypeComparisonMode.Exact) - { - if (ReferenceEquals (a, b)) - return true; - - if (a.Position != b.Position) - return false; - - if (a.Type != b.Type) - return false; - - var aOwnerType = a.Owner as TypeReference; - if (aOwnerType != null && AreEqual (aOwnerType, b.Owner as TypeReference, comparisonMode)) - return true; - - var aOwnerMethod = a.Owner as MethodReference; - if (aOwnerMethod != null && comparisonMode != TypeComparisonMode.SignatureOnlyLoose && MethodReferenceComparer.AreEqual (aOwnerMethod, b.Owner as MethodReference)) - return true; - - return comparisonMode == TypeComparisonMode.SignatureOnly || comparisonMode == TypeComparisonMode.SignatureOnlyLoose; - } - - static bool AreEqual (GenericInstanceType a, GenericInstanceType b, TypeComparisonMode comparisonMode = TypeComparisonMode.Exact) - { - if (ReferenceEquals (a, b)) - return true; - - var aGenericArgumentsCount = a.GenericArguments.Count; - if (aGenericArgumentsCount != b.GenericArguments.Count) - return false; - - if (!AreEqual (a.ElementType, b.ElementType, comparisonMode)) - return false; - - for (int i = 0; i < aGenericArgumentsCount; i++) - if (!AreEqual (a.GenericArguments [i], b.GenericArguments [i], comparisonMode)) - return false; - - return true; - } - - public static int GetHashCodeFor (TypeReference obj) - { - // a very good prime number - const int hashCodeMultiplier = 486187739; - // prime numbers - const int genericInstanceTypeMultiplier = 31; - const int byReferenceMultiplier = 37; - const int pointerMultiplier = 41; - const int requiredModifierMultiplier = 43; - const int optionalModifierMultiplier = 47; - const int pinnedMultiplier = 53; - const int sentinelMultiplier = 59; - - var metadataType = obj.MetadataType; - - if (metadataType == MetadataType.GenericInstance) { - var genericInstanceType = (GenericInstanceType)obj; - var hashCode = GetHashCodeFor (genericInstanceType.ElementType) * hashCodeMultiplier + genericInstanceTypeMultiplier; - for (var i = 0; i < genericInstanceType.GenericArguments.Count; i++) - hashCode = hashCode * hashCodeMultiplier + GetHashCodeFor (genericInstanceType.GenericArguments [i]); - return hashCode; - } - - if (metadataType == MetadataType.Array) { - var arrayType = (ArrayType)obj; - return GetHashCodeFor (arrayType.ElementType) * hashCodeMultiplier + arrayType.Rank.GetHashCode (); - } - - if (metadataType == MetadataType.Var || metadataType == MetadataType.MVar) { - var genericParameter = (GenericParameter)obj; - var hashCode = genericParameter.Position.GetHashCode () * hashCodeMultiplier + ((int)metadataType).GetHashCode (); - - var ownerTypeReference = genericParameter.Owner as TypeReference; - if (ownerTypeReference != null) - return hashCode * hashCodeMultiplier + GetHashCodeFor (ownerTypeReference); - - var ownerMethodReference = genericParameter.Owner as MethodReference; - if (ownerMethodReference != null) - return hashCode * hashCodeMultiplier + MethodReferenceComparer.GetHashCodeFor (ownerMethodReference); - - throw new InvalidOperationException ("Generic parameter encountered with invalid owner"); - } - - if (metadataType == MetadataType.ByReference) { - var byReferenceType = (ByReferenceType)obj; - return GetHashCodeFor (byReferenceType.ElementType) * hashCodeMultiplier * byReferenceMultiplier; - } - - if (metadataType == MetadataType.Pointer) { - var pointerType = (PointerType)obj; - return GetHashCodeFor (pointerType.ElementType) * hashCodeMultiplier * pointerMultiplier; - } - - if (metadataType == MetadataType.RequiredModifier) { - var requiredModifierType = (RequiredModifierType)obj; - var hashCode = GetHashCodeFor (requiredModifierType.ElementType) * requiredModifierMultiplier; - hashCode = hashCode * hashCodeMultiplier + GetHashCodeFor (requiredModifierType.ModifierType); - return hashCode; - } - - if (metadataType == MetadataType.OptionalModifier) { - var optionalModifierType = (OptionalModifierType)obj; - var hashCode = GetHashCodeFor (optionalModifierType.ElementType) * optionalModifierMultiplier; - hashCode = hashCode * hashCodeMultiplier + GetHashCodeFor (optionalModifierType.ModifierType); - return hashCode; - } - - if (metadataType == MetadataType.Pinned) { - var pinnedType = (PinnedType)obj; - return GetHashCodeFor (pinnedType.ElementType) * hashCodeMultiplier * pinnedMultiplier; - } - - if (metadataType == MetadataType.Sentinel) { - var sentinelType = (SentinelType)obj; - return GetHashCodeFor (sentinelType.ElementType) * hashCodeMultiplier * sentinelMultiplier; - } - - if (metadataType == MetadataType.FunctionPointer) { - throw new NotImplementedException ("We currently don't handle function pointer types."); - } - - return obj.Namespace.GetHashCode () * hashCodeMultiplier + obj.FullName.GetHashCode (); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReferenceEqualityComparer.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReferenceEqualityComparer.cs.meta deleted file mode 100644 index e8ce2b4..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeReferenceEqualityComparer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5e048a822386ae34ab1124eaf29e1d84 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeResolver.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeResolver.cs deleted file mode 100644 index 69b8507..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeResolver.cs +++ /dev/null @@ -1,220 +0,0 @@ -using MonoFN.Cecil.Cil; -using System; - -namespace MonoFN.Cecil { - internal sealed class TypeResolver { - private readonly IGenericInstance _typeDefinitionContext; - private readonly IGenericInstance _methodDefinitionContext; - - public static TypeResolver For (TypeReference typeReference) - { - return typeReference.IsGenericInstance ? new TypeResolver ((GenericInstanceType)typeReference) : new TypeResolver (); - } - - public static TypeResolver For (TypeReference typeReference, MethodReference methodReference) - { - return new TypeResolver (typeReference as GenericInstanceType, methodReference as GenericInstanceMethod); - } - - public TypeResolver () - { - - } - - public TypeResolver (GenericInstanceType typeDefinitionContext) - { - _typeDefinitionContext = typeDefinitionContext; - } - - public TypeResolver (GenericInstanceMethod methodDefinitionContext) - { - _methodDefinitionContext = methodDefinitionContext; - } - - public TypeResolver (GenericInstanceType typeDefinitionContext, GenericInstanceMethod methodDefinitionContext) - { - _typeDefinitionContext = typeDefinitionContext; - _methodDefinitionContext = methodDefinitionContext; - } - - public MethodReference Resolve (MethodReference method) - { - var methodReference = method; - if (IsDummy ()) - return methodReference; - - var declaringType = Resolve (method.DeclaringType); - - var genericInstanceMethod = method as GenericInstanceMethod; - if (genericInstanceMethod != null) { - methodReference = new MethodReference (method.Name, method.ReturnType, declaringType); - - foreach (var p in method.Parameters) - methodReference.Parameters.Add (new ParameterDefinition (p.Name, p.Attributes, p.ParameterType)); - - foreach (var gp in genericInstanceMethod.ElementMethod.GenericParameters) - methodReference.GenericParameters.Add (new GenericParameter (gp.Name, methodReference)); - - methodReference.HasThis = method.HasThis; - - var m = new GenericInstanceMethod (methodReference); - foreach (var ga in genericInstanceMethod.GenericArguments) { - m.GenericArguments.Add (Resolve (ga)); - } - - methodReference = m; - } else { - methodReference = new MethodReference (method.Name, method.ReturnType, declaringType); - - foreach (var gp in method.GenericParameters) - methodReference.GenericParameters.Add (new GenericParameter (gp.Name, methodReference)); - - foreach (var p in method.Parameters) - methodReference.Parameters.Add (new ParameterDefinition (p.Name, p.Attributes, p.ParameterType)); - - methodReference.HasThis = method.HasThis; - } - - - return methodReference; - } - - public FieldReference Resolve (FieldReference field) - { - var declaringType = Resolve (field.DeclaringType); - - if (declaringType == field.DeclaringType) - return field; - - return new FieldReference (field.Name, field.FieldType, declaringType); - } - - public TypeReference ResolveReturnType (MethodReference method) - { - return Resolve (GenericParameterResolver.ResolveReturnTypeIfNeeded (method)); - } - - public TypeReference ResolveParameterType (MethodReference method, ParameterReference parameter) - { - return Resolve (GenericParameterResolver.ResolveParameterTypeIfNeeded (method, parameter)); - } - - public TypeReference ResolveVariableType (MethodReference method, VariableReference variable) - { - return Resolve (GenericParameterResolver.ResolveVariableTypeIfNeeded (method, variable)); - } - - public TypeReference ResolveFieldType (FieldReference field) - { - return Resolve (GenericParameterResolver.ResolveFieldTypeIfNeeded (field)); - } - - public TypeReference Resolve (TypeReference typeReference) - { - return Resolve (typeReference, true); - } - - public TypeReference Resolve (TypeReference typeReference, bool includeTypeDefinitions) - { - if (IsDummy ()) - return typeReference; - - if (_typeDefinitionContext != null && _typeDefinitionContext.GenericArguments.Contains (typeReference)) - return typeReference; - if (_methodDefinitionContext != null && _methodDefinitionContext.GenericArguments.Contains (typeReference)) - return typeReference; - - var genericParameter = typeReference as GenericParameter; - if (genericParameter != null) { - if (_typeDefinitionContext != null && _typeDefinitionContext.GenericArguments.Contains (genericParameter)) - return genericParameter; - if (_methodDefinitionContext != null && _methodDefinitionContext.GenericArguments.Contains (genericParameter)) - return genericParameter; - return ResolveGenericParameter (genericParameter); - } - - var arrayType = typeReference as ArrayType; - if (arrayType != null) - return new ArrayType (Resolve (arrayType.ElementType), arrayType.Rank); - - var pointerType = typeReference as PointerType; - if (pointerType != null) - return new PointerType (Resolve (pointerType.ElementType)); - - var byReferenceType = typeReference as ByReferenceType; - if (byReferenceType != null) - return new ByReferenceType (Resolve (byReferenceType.ElementType)); - - var pinnedType = typeReference as PinnedType; - if (pinnedType != null) - return new PinnedType (Resolve (pinnedType.ElementType)); - - var genericInstanceType = typeReference as GenericInstanceType; - if (genericInstanceType != null) { - var newGenericInstanceType = new GenericInstanceType (genericInstanceType.ElementType); - foreach (var genericArgument in genericInstanceType.GenericArguments) - newGenericInstanceType.GenericArguments.Add (Resolve (genericArgument)); - return newGenericInstanceType; - } - - var requiredModType = typeReference as RequiredModifierType; - if (requiredModType != null) - return Resolve (requiredModType.ElementType, includeTypeDefinitions); - - - if (includeTypeDefinitions) { - var typeDefinition = typeReference as TypeDefinition; - if (typeDefinition != null && typeDefinition.HasGenericParameters) { - var newGenericInstanceType = new GenericInstanceType (typeDefinition); - foreach (var gp in typeDefinition.GenericParameters) - newGenericInstanceType.GenericArguments.Add (Resolve (gp)); - return newGenericInstanceType; - } - } - - if (typeReference is TypeSpecification) - throw new NotSupportedException (string.Format ("The type {0} cannot be resolved correctly.", typeReference.FullName)); - - return typeReference; - } - - internal TypeResolver Nested (GenericInstanceMethod genericInstanceMethod) - { - return new TypeResolver (_typeDefinitionContext as GenericInstanceType, genericInstanceMethod); - } - - private TypeReference ResolveGenericParameter (GenericParameter genericParameter) - { - if (genericParameter.Owner == null) - return HandleOwnerlessInvalidILCode (genericParameter); - - var memberReference = genericParameter.Owner as MemberReference; - if (memberReference == null) - throw new NotSupportedException (); - - return genericParameter.Type == GenericParameterType.Type - ? _typeDefinitionContext.GenericArguments [genericParameter.Position] - : (_methodDefinitionContext != null ? _methodDefinitionContext.GenericArguments [genericParameter.Position] : genericParameter); - } - - private TypeReference HandleOwnerlessInvalidILCode (GenericParameter genericParameter) - { - // NOTE: If owner is null and we have a method parameter, then we'll assume that the method parameter - // is actually a type parameter, and we'll use the type parameter from the corresponding position. I think - // this assumption is valid, but if you're visiting this code then I might have been proven wrong. - if (genericParameter.Type == GenericParameterType.Method && (_typeDefinitionContext != null && genericParameter.Position < _typeDefinitionContext.GenericArguments.Count)) - return _typeDefinitionContext.GenericArguments [genericParameter.Position]; - - // NOTE: Owner cannot be null, but sometimes the Mono compiler generates invalid IL and we - // end up in this situation. - // When we do, we assume that the runtime doesn't care about the resolved type of the GenericParameter, - // thus we return a reference to System.Object. - return genericParameter.Module.TypeSystem.Object; - } - - private bool IsDummy () - { - return _typeDefinitionContext == null && _methodDefinitionContext == null; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeResolver.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeResolver.cs.meta deleted file mode 100644 index 9b42c4c..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeResolver.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 94140ae852ea8954489f238f1e59f865 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSpecification.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSpecification.cs deleted file mode 100644 index 4be061f..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSpecification.cs +++ /dev/null @@ -1,66 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil { - - public abstract class TypeSpecification : TypeReference { - - readonly TypeReference element_type; - - public TypeReference ElementType { - get { return element_type; } - } - - public override string Name { - get { return element_type.Name; } - set { throw new InvalidOperationException (); } - } - - public override string Namespace { - get { return element_type.Namespace; } - set { throw new InvalidOperationException (); } - } - - public override IMetadataScope Scope { - get { return element_type.Scope; } - set { throw new InvalidOperationException (); } - } - - public override ModuleDefinition Module { - get { return element_type.Module; } - } - - public override string FullName { - get { return element_type.FullName; } - } - - public override bool ContainsGenericParameter { - get { return element_type.ContainsGenericParameter; } - } - - public override MetadataType MetadataType { - get { return (MetadataType)etype; } - } - - internal TypeSpecification (TypeReference type) - : base (null, null) - { - this.element_type = type; - this.token = new MetadataToken (TokenType.TypeSpec); - } - - public override TypeReference GetElementType () - { - return element_type.GetElementType (); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSpecification.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSpecification.cs.meta deleted file mode 100644 index 2d6b903..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSpecification.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4c1d979e44d835a4dbcdefa35a45a07a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSystem.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSystem.cs deleted file mode 100644 index 686156c..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSystem.cs +++ /dev/null @@ -1,330 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Metadata; -using System; - -namespace MonoFN.Cecil { - - public abstract class TypeSystem { - - sealed class CoreTypeSystem : TypeSystem { - - public CoreTypeSystem (ModuleDefinition module) - : base (module) - { - } - - internal override TypeReference LookupType (string @namespace, string name) - { - var type = LookupTypeDefinition (@namespace, name) ?? LookupTypeForwarded (@namespace, name); - if (type != null) - return type; - - throw new NotSupportedException (); - } - - TypeReference LookupTypeDefinition (string @namespace, string name) - { - var metadata = module.MetadataSystem; - if (metadata.Types == null) - Initialize (module.Types); - - return module.Read (new Row (@namespace, name), (row, reader) => { - var types = reader.metadata.Types; - - for (int i = 0; i < types.Length; i++) { - if (types [i] == null) - types [i] = reader.GetTypeDefinition ((uint)i + 1); - - var type = types [i]; - - if (type.Name == row.Col2 && type.Namespace == row.Col1) - return type; - } - - return null; - }); - } - - TypeReference LookupTypeForwarded (string @namespace, string name) - { - if (!module.HasExportedTypes) - return null; - - var exported_types = module.ExportedTypes; - for (int i = 0; i < exported_types.Count; i++) { - var exported_type = exported_types [i]; - - if (exported_type.Name == name && exported_type.Namespace == @namespace) - return exported_type.CreateReference (); - } - - return null; - } - - static void Initialize (object obj) - { - } - } - - sealed class CommonTypeSystem : TypeSystem { - - AssemblyNameReference core_library; - - public CommonTypeSystem (ModuleDefinition module) - : base (module) - { - } - - internal override TypeReference LookupType (string @namespace, string name) - { - return CreateTypeReference (@namespace, name); - } - - public AssemblyNameReference GetCoreLibraryReference () - { - if (core_library != null) - return core_library; - - if (module.TryGetCoreLibraryReference (out core_library)) - return core_library; - - core_library = new AssemblyNameReference { - Name = Mixin.mscorlib, - Version = GetCorlibVersion (), - PublicKeyToken = new byte [] { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }, - }; - - module.AssemblyReferences.Add (core_library); - - return core_library; - } - - Version GetCorlibVersion () - { - switch (module.Runtime) { - case TargetRuntime.Net_1_0: - case TargetRuntime.Net_1_1: - return new Version (1, 0, 0, 0); - case TargetRuntime.Net_2_0: - return new Version (2, 0, 0, 0); - case TargetRuntime.Net_4_0: - return new Version (4, 0, 0, 0); - default: - throw new NotSupportedException (); - } - } - - TypeReference CreateTypeReference (string @namespace, string name) - { - return new TypeReference (@namespace, name, module, GetCoreLibraryReference ()); - } - } - - readonly ModuleDefinition module; - - TypeReference type_object; - TypeReference type_void; - TypeReference type_bool; - TypeReference type_char; - TypeReference type_sbyte; - TypeReference type_byte; - TypeReference type_int16; - TypeReference type_uint16; - TypeReference type_int32; - TypeReference type_uint32; - TypeReference type_int64; - TypeReference type_uint64; - TypeReference type_single; - TypeReference type_double; - TypeReference type_intptr; - TypeReference type_uintptr; - TypeReference type_string; - TypeReference type_typedref; - - TypeSystem (ModuleDefinition module) - { - this.module = module; - } - - internal static TypeSystem CreateTypeSystem (ModuleDefinition module) - { - if (module.IsCoreLibrary ()) - return new CoreTypeSystem (module); - - return new CommonTypeSystem (module); - } - - internal abstract TypeReference LookupType (string @namespace, string name); - - TypeReference LookupSystemType (ref TypeReference reference, string name, ElementType element_type) - { - lock (module.SyncRoot) { - if (reference != null) - return reference; - var type = LookupType ("System", name); - type.etype = element_type; - return reference = type; - } - } - - TypeReference LookupSystemValueType (ref TypeReference typeRef, string name, ElementType element_type) - { - lock (module.SyncRoot) { - if (typeRef != null) - return typeRef; - var type = LookupType ("System", name); - type.etype = element_type; - type.KnownValueType (); - return typeRef = type; - } - } - - [Obsolete ("Use CoreLibrary")] - public IMetadataScope Corlib { - get { return CoreLibrary; } - } - - public IMetadataScope CoreLibrary { - get { - var common = this as CommonTypeSystem; - if (common == null) - return module; - - return common.GetCoreLibraryReference (); - } - } - - public TypeReference Object { - get { return type_object ?? (LookupSystemType (ref type_object, "Object", ElementType.Object)); } - } - - public TypeReference Void { - get { return type_void ?? (LookupSystemType (ref type_void, "Void", ElementType.Void)); } - } - - public TypeReference Boolean { - get { return type_bool ?? (LookupSystemValueType (ref type_bool, "Boolean", ElementType.Boolean)); } - } - - public TypeReference Char { - get { return type_char ?? (LookupSystemValueType (ref type_char, "Char", ElementType.Char)); } - } - - public TypeReference SByte { - get { return type_sbyte ?? (LookupSystemValueType (ref type_sbyte, "SByte", ElementType.I1)); } - } - - public TypeReference Byte { - get { return type_byte ?? (LookupSystemValueType (ref type_byte, "Byte", ElementType.U1)); } - } - - public TypeReference Int16 { - get { return type_int16 ?? (LookupSystemValueType (ref type_int16, "Int16", ElementType.I2)); } - } - - public TypeReference UInt16 { - get { return type_uint16 ?? (LookupSystemValueType (ref type_uint16, "UInt16", ElementType.U2)); } - } - - public TypeReference Int32 { - get { return type_int32 ?? (LookupSystemValueType (ref type_int32, "Int32", ElementType.I4)); } - } - - public TypeReference UInt32 { - get { return type_uint32 ?? (LookupSystemValueType (ref type_uint32, "UInt32", ElementType.U4)); } - } - - public TypeReference Int64 { - get { return type_int64 ?? (LookupSystemValueType (ref type_int64, "Int64", ElementType.I8)); } - } - - public TypeReference UInt64 { - get { return type_uint64 ?? (LookupSystemValueType (ref type_uint64, "UInt64", ElementType.U8)); } - } - - public TypeReference Single { - get { return type_single ?? (LookupSystemValueType (ref type_single, "Single", ElementType.R4)); } - } - - public TypeReference Double { - get { return type_double ?? (LookupSystemValueType (ref type_double, "Double", ElementType.R8)); } - } - - public TypeReference IntPtr { - get { return type_intptr ?? (LookupSystemValueType (ref type_intptr, "IntPtr", ElementType.I)); } - } - - public TypeReference UIntPtr { - get { return type_uintptr ?? (LookupSystemValueType (ref type_uintptr, "UIntPtr", ElementType.U)); } - } - - public TypeReference String { - get { return type_string ?? (LookupSystemType (ref type_string, "String", ElementType.String)); } - } - - public TypeReference TypedReference { - get { return type_typedref ?? (LookupSystemValueType (ref type_typedref, "TypedReference", ElementType.TypedByRef)); } - } - } - - static partial class Mixin { - - public const string mscorlib = "mscorlib"; - public const string system_runtime = "System.Runtime"; - public const string system_private_corelib = "System.Private.CoreLib"; - public const string netstandard = "netstandard"; - - public static bool TryGetCoreLibraryReference (this ModuleDefinition module, out AssemblyNameReference reference) - { - var references = module.AssemblyReferences; - - for (int i = 0; i < references.Count; i++) { - reference = references [i]; - if (IsCoreLibrary (reference)) - return true; - } - - reference = null; - return false; - - } - - public static bool IsCoreLibrary (this ModuleDefinition module) - { - if (module.Assembly == null) - return false; - - if (!IsCoreLibrary (module.Assembly.Name)) - return false; - - if (module.HasImage && module.Read (module, (m, reader) => reader.image.GetTableLength (Table.AssemblyRef) > 0)) - return false; - - return true; - } - - public static void KnownValueType (this TypeReference type) - { - if (!type.IsDefinition) - type.IsValueType = true; - } - - static bool IsCoreLibrary (AssemblyNameReference reference) - { - var name = reference.Name; - return name == mscorlib - || name == system_runtime - || name == system_private_corelib - || name == netstandard; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSystem.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSystem.cs.meta deleted file mode 100644 index 20fec27..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/TypeSystem.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 68c81a3fab6a4ee4dbfc5e83e365d1c9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/VariantType.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/VariantType.cs deleted file mode 100644 index 9f5ed54..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/VariantType.cs +++ /dev/null @@ -1,37 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -namespace MonoFN.Cecil { - - public enum VariantType { - None = 0, - I2 = 2, - I4 = 3, - R4 = 4, - R8 = 5, - CY = 6, - Date = 7, - BStr = 8, - Dispatch = 9, - Error = 10, - Bool = 11, - Variant = 12, - Unknown = 13, - Decimal = 14, - I1 = 16, - UI1 = 17, - UI2 = 18, - UI4 = 19, - I8 = 20, - UI8 = 21, - Int = 22, - UInt = 23 - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/VariantType.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/VariantType.cs.meta deleted file mode 100644 index 5bc5518..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/VariantType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b01b9a572a6975b4c806b3269b858cb1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/WindowsRuntimeProjections.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/WindowsRuntimeProjections.cs deleted file mode 100644 index d505b28..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/WindowsRuntimeProjections.cs +++ /dev/null @@ -1,959 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; -using System.Collections.Generic; -using System.Threading; - -namespace MonoFN.Cecil { - - sealed class TypeDefinitionProjection { - - public readonly TypeAttributes Attributes; - public readonly string Name; - public readonly TypeDefinitionTreatment Treatment; - public readonly Collection RedirectedMethods; - public readonly Collection> RedirectedInterfaces; - - public TypeDefinitionProjection (TypeDefinition type, TypeDefinitionTreatment treatment, Collection redirectedMethods, Collection> redirectedInterfaces) - { - Attributes = type.Attributes; - Name = type.Name; - Treatment = treatment; - RedirectedMethods = redirectedMethods; - RedirectedInterfaces = redirectedInterfaces; - } - } - - sealed class TypeReferenceProjection { - - public readonly string Name; - public readonly string Namespace; - public readonly IMetadataScope Scope; - public readonly TypeReferenceTreatment Treatment; - - public TypeReferenceProjection (TypeReference type, TypeReferenceTreatment treatment) - { - Name = type.Name; - Namespace = type.Namespace; - Scope = type.Scope; - Treatment = treatment; - } - } - - sealed class MethodDefinitionProjection { - - public readonly MethodAttributes Attributes; - public readonly MethodImplAttributes ImplAttributes; - public readonly string Name; - public readonly MethodDefinitionTreatment Treatment; - - public MethodDefinitionProjection (MethodDefinition method, MethodDefinitionTreatment treatment) - { - Attributes = method.Attributes; - ImplAttributes = method.ImplAttributes; - Name = method.Name; - Treatment = treatment; - } - } - - sealed class FieldDefinitionProjection { - - public readonly FieldAttributes Attributes; - public readonly FieldDefinitionTreatment Treatment; - - public FieldDefinitionProjection (FieldDefinition field, FieldDefinitionTreatment treatment) - { - Attributes = field.Attributes; - Treatment = treatment; - } - } - - sealed class CustomAttributeValueProjection { - - public readonly AttributeTargets Targets; - public readonly CustomAttributeValueTreatment Treatment; - - public CustomAttributeValueProjection (AttributeTargets targets, CustomAttributeValueTreatment treatment) - { - Targets = targets; - Treatment = treatment; - } - } - - sealed class WindowsRuntimeProjections { - - struct ProjectionInfo { - - public readonly string WinRTNamespace; - public readonly string ClrNamespace; - public readonly string ClrName; - public readonly string ClrAssembly; - public readonly bool Attribute; - - public ProjectionInfo (string winrt_namespace, string clr_namespace, string clr_name, string clr_assembly, bool attribute = false) - { - WinRTNamespace = winrt_namespace; - ClrNamespace = clr_namespace; - ClrName = clr_name; - ClrAssembly = clr_assembly; - Attribute = attribute; - } - } - - static readonly Version version = new Version (4, 0, 0, 0); - - static readonly byte [] contract_pk_token = { - 0xB0, 0x3F, 0x5F, 0x7F, 0x11, 0xD5, 0x0A, 0x3A - }; - - static readonly byte [] contract_pk = { - 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, - 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x31, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, - 0x07, 0xD1, 0xFA, 0x57, 0xC4, 0xAE, 0xD9, 0xF0, 0xA3, 0x2E, 0x84, 0xAA, 0x0F, 0xAE, 0xFD, 0x0D, - 0xE9, 0xE8, 0xFD, 0x6A, 0xEC, 0x8F, 0x87, 0xFB, 0x03, 0x76, 0x6C, 0x83, 0x4C, 0x99, 0x92, 0x1E, - 0xB2, 0x3B, 0xE7, 0x9A, 0xD9, 0xD5, 0xDC, 0xC1, 0xDD, 0x9A, 0xD2, 0x36, 0x13, 0x21, 0x02, 0x90, - 0x0B, 0x72, 0x3C, 0xF9, 0x80, 0x95, 0x7F, 0xC4, 0xE1, 0x77, 0x10, 0x8F, 0xC6, 0x07, 0x77, 0x4F, - 0x29, 0xE8, 0x32, 0x0E, 0x92, 0xEA, 0x05, 0xEC, 0xE4, 0xE8, 0x21, 0xC0, 0xA5, 0xEF, 0xE8, 0xF1, - 0x64, 0x5C, 0x4C, 0x0C, 0x93, 0xC1, 0xAB, 0x99, 0x28, 0x5D, 0x62, 0x2C, 0xAA, 0x65, 0x2C, 0x1D, - 0xFA, 0xD6, 0x3D, 0x74, 0x5D, 0x6F, 0x2D, 0xE5, 0xF1, 0x7E, 0x5E, 0xAF, 0x0F, 0xC4, 0x96, 0x3D, - 0x26, 0x1C, 0x8A, 0x12, 0x43, 0x65, 0x18, 0x20, 0x6D, 0xC0, 0x93, 0x34, 0x4D, 0x5A, 0xD2, 0x93 - }; - - static Dictionary projections; - - static Dictionary Projections { - get { - if (projections != null) - return projections; - - - var new_projections = new Dictionary { - { "AttributeTargets", new ProjectionInfo ("Windows.Foundation.Metadata", "System", "AttributeTargets", "System.Runtime") }, - { "AttributeUsageAttribute", new ProjectionInfo ("Windows.Foundation.Metadata", "System", "AttributeUsageAttribute", "System.Runtime", attribute: true) }, - { "Color", new ProjectionInfo ("Windows.UI", "Windows.UI", "Color", "System.Runtime.WindowsRuntime") }, - { "CornerRadius", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "CornerRadius", "System.Runtime.WindowsRuntime.UI.Xaml") }, - { "DateTime", new ProjectionInfo ("Windows.Foundation", "System", "DateTimeOffset", "System.Runtime") }, - { "Duration", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "Duration", "System.Runtime.WindowsRuntime.UI.Xaml") }, - { "DurationType", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "DurationType", "System.Runtime.WindowsRuntime.UI.Xaml") }, - { "EventHandler`1", new ProjectionInfo ("Windows.Foundation", "System", "EventHandler`1", "System.Runtime") }, - { "EventRegistrationToken", new ProjectionInfo ("Windows.Foundation", "System.Runtime.InteropServices.WindowsRuntime", "EventRegistrationToken", "System.Runtime.InteropServices.WindowsRuntime") }, - { "GeneratorPosition", new ProjectionInfo ("Windows.UI.Xaml.Controls.Primitives", "Windows.UI.Xaml.Controls.Primitives", "GeneratorPosition", "System.Runtime.WindowsRuntime.UI.Xaml") }, - { "GridLength", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "GridLength", "System.Runtime.WindowsRuntime.UI.Xaml") }, - { "GridUnitType", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "GridUnitType", "System.Runtime.WindowsRuntime.UI.Xaml") }, - { "HResult", new ProjectionInfo ("Windows.Foundation", "System", "Exception", "System.Runtime") }, - { "IBindableIterable", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections", "IEnumerable", "System.Runtime") }, - { "IBindableVector", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections", "IList", "System.Runtime") }, - { "IClosable", new ProjectionInfo ("Windows.Foundation", "System", "IDisposable", "System.Runtime") }, - { "ICommand", new ProjectionInfo ("Windows.UI.Xaml.Input", "System.Windows.Input", "ICommand", "System.ObjectModel") }, - { "IIterable`1", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IEnumerable`1", "System.Runtime") }, - { "IKeyValuePair`2", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "KeyValuePair`2", "System.Runtime") }, - { "IMapView`2", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IReadOnlyDictionary`2", "System.Runtime") }, - { "IMap`2", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IDictionary`2", "System.Runtime") }, - { "INotifyCollectionChanged", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections.Specialized", "INotifyCollectionChanged", "System.ObjectModel") }, - { "INotifyPropertyChanged", new ProjectionInfo ("Windows.UI.Xaml.Data", "System.ComponentModel", "INotifyPropertyChanged", "System.ObjectModel") }, - { "IReference`1", new ProjectionInfo ("Windows.Foundation", "System", "Nullable`1", "System.Runtime") }, - { "IVectorView`1", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IReadOnlyList`1", "System.Runtime") }, - { "IVector`1", new ProjectionInfo ("Windows.Foundation.Collections", "System.Collections.Generic", "IList`1", "System.Runtime") }, - { "KeyTime", new ProjectionInfo ("Windows.UI.Xaml.Media.Animation", "Windows.UI.Xaml.Media.Animation", "KeyTime", "System.Runtime.WindowsRuntime.UI.Xaml") }, - { "Matrix", new ProjectionInfo ("Windows.UI.Xaml.Media", "Windows.UI.Xaml.Media", "Matrix", "System.Runtime.WindowsRuntime.UI.Xaml") }, - { "Matrix3D", new ProjectionInfo ("Windows.UI.Xaml.Media.Media3D", "Windows.UI.Xaml.Media.Media3D", "Matrix3D", "System.Runtime.WindowsRuntime.UI.Xaml") }, - { "Matrix3x2", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Matrix3x2", "System.Numerics.Vectors") }, - { "Matrix4x4", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Matrix4x4", "System.Numerics.Vectors") }, - { "NotifyCollectionChangedAction", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections.Specialized", "NotifyCollectionChangedAction", "System.ObjectModel") }, - { "NotifyCollectionChangedEventArgs", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections.Specialized", "NotifyCollectionChangedEventArgs", "System.ObjectModel") }, - { "NotifyCollectionChangedEventHandler", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System.Collections.Specialized", "NotifyCollectionChangedEventHandler", "System.ObjectModel") }, - { "Plane", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Plane", "System.Numerics.Vectors") }, - { "Point", new ProjectionInfo ("Windows.Foundation", "Windows.Foundation", "Point", "System.Runtime.WindowsRuntime") }, - { "PropertyChangedEventArgs", new ProjectionInfo ("Windows.UI.Xaml.Data", "System.ComponentModel", "PropertyChangedEventArgs", "System.ObjectModel") }, - { "PropertyChangedEventHandler", new ProjectionInfo ("Windows.UI.Xaml.Data", "System.ComponentModel", "PropertyChangedEventHandler", "System.ObjectModel") }, - { "Quaternion", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Quaternion", "System.Numerics.Vectors") }, - { "Rect", new ProjectionInfo ("Windows.Foundation", "Windows.Foundation", "Rect", "System.Runtime.WindowsRuntime") }, - { "RepeatBehavior", new ProjectionInfo ("Windows.UI.Xaml.Media.Animation", "Windows.UI.Xaml.Media.Animation", "RepeatBehavior", "System.Runtime.WindowsRuntime.UI.Xaml") }, - { "RepeatBehaviorType", new ProjectionInfo ("Windows.UI.Xaml.Media.Animation", "Windows.UI.Xaml.Media.Animation", "RepeatBehaviorType", "System.Runtime.WindowsRuntime.UI.Xaml") }, - { "Size", new ProjectionInfo ("Windows.Foundation", "Windows.Foundation", "Size", "System.Runtime.WindowsRuntime") }, - { "Thickness", new ProjectionInfo ("Windows.UI.Xaml", "Windows.UI.Xaml", "Thickness", "System.Runtime.WindowsRuntime.UI.Xaml") }, - { "TimeSpan", new ProjectionInfo ("Windows.Foundation", "System", "TimeSpan", "System.Runtime") }, - { "TypeName", new ProjectionInfo ("Windows.UI.Xaml.Interop", "System", "Type", "System.Runtime") }, - { "Uri", new ProjectionInfo ("Windows.Foundation", "System", "Uri", "System.Runtime") }, - { "Vector2", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Vector2", "System.Numerics.Vectors") }, - { "Vector3", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Vector3", "System.Numerics.Vectors") }, - { "Vector4", new ProjectionInfo ("Windows.Foundation.Numerics", "System.Numerics", "Vector4", "System.Numerics.Vectors") }, - }; - - Interlocked.CompareExchange (ref projections, new_projections, null); - return projections; - } - } - - readonly ModuleDefinition module; - Version corlib_version = new Version (255, 255, 255, 255); - AssemblyNameReference [] virtual_references; - - AssemblyNameReference [] VirtualReferences { - get { - if (virtual_references == null) { - // force module to read its assembly references. that will in turn initialize virtual_references - Mixin.Read (module.AssemblyReferences); - } - - return virtual_references; - } - } - - public WindowsRuntimeProjections (ModuleDefinition module) - { - this.module = module; - } - - public static void Project (TypeDefinition type) - { - var treatment = TypeDefinitionTreatment.None; - var metadata_kind = type.Module.MetadataKind; - Collection redirectedMethods = null; - Collection> redirectedInterfaces = null; - - if (type.IsWindowsRuntime) { - if (metadata_kind == MetadataKind.WindowsMetadata) { - treatment = GetWellKnownTypeDefinitionTreatment (type); - if (treatment != TypeDefinitionTreatment.None) { - ApplyProjection (type, new TypeDefinitionProjection (type, treatment, redirectedMethods, redirectedInterfaces)); - return; - } - - var base_type = type.BaseType; - if (base_type != null && IsAttribute (base_type)) { - treatment = TypeDefinitionTreatment.NormalAttribute; - } else { - treatment = GenerateRedirectionInformation (type, out redirectedMethods, out redirectedInterfaces); - } - } else if (metadata_kind == MetadataKind.ManagedWindowsMetadata && NeedsWindowsRuntimePrefix (type)) - treatment = TypeDefinitionTreatment.PrefixWindowsRuntimeName; - - if (treatment == TypeDefinitionTreatment.PrefixWindowsRuntimeName || treatment == TypeDefinitionTreatment.NormalType) - if (!type.IsInterface && HasAttribute (type, "Windows.UI.Xaml", "TreatAsAbstractComposableClassAttribute")) - treatment |= TypeDefinitionTreatment.Abstract; - } else if (metadata_kind == MetadataKind.ManagedWindowsMetadata && IsClrImplementationType (type)) - treatment = TypeDefinitionTreatment.UnmangleWindowsRuntimeName; - - if (treatment != TypeDefinitionTreatment.None) - ApplyProjection (type, new TypeDefinitionProjection (type, treatment, redirectedMethods, redirectedInterfaces)); - } - - static TypeDefinitionTreatment GetWellKnownTypeDefinitionTreatment (TypeDefinition type) - { - ProjectionInfo info; - if (!Projections.TryGetValue (type.Name, out info)) - return TypeDefinitionTreatment.None; - - var treatment = info.Attribute ? TypeDefinitionTreatment.RedirectToClrAttribute : TypeDefinitionTreatment.RedirectToClrType; - - if (type.Namespace == info.ClrNamespace) - return treatment; - - if (type.Namespace == info.WinRTNamespace) - return treatment | TypeDefinitionTreatment.Internal; - - return TypeDefinitionTreatment.None; - } - - private static TypeDefinitionTreatment GenerateRedirectionInformation (TypeDefinition type, out Collection redirectedMethods, out Collection> redirectedInterfaces) - { - bool implementsProjectedInterface = false; - redirectedMethods = null; - redirectedInterfaces = null; - - foreach (var implementedInterface in type.Interfaces) { - if (IsRedirectedType (implementedInterface.InterfaceType)) { - implementsProjectedInterface = true; - break; - } - } - - if (!implementsProjectedInterface) - return TypeDefinitionTreatment.NormalType; - - var allImplementedInterfaces = new HashSet (new TypeReferenceEqualityComparer ()); - redirectedMethods = new Collection (); - redirectedInterfaces = new Collection> (); - - foreach (var @interface in type.Interfaces) { - var interfaceType = @interface.InterfaceType; - - if (IsRedirectedType (interfaceType)) { - allImplementedInterfaces.Add (interfaceType); - CollectImplementedInterfaces (interfaceType, allImplementedInterfaces); - } - } - - foreach (var implementedInterface in type.Interfaces) { - var interfaceType = implementedInterface.InterfaceType; - if (IsRedirectedType (implementedInterface.InterfaceType)) { - var etype = interfaceType.GetElementType (); - var unprojectedType = new TypeReference (etype.Namespace, etype.Name, etype.Module, etype.Scope) { - DeclaringType = etype.DeclaringType, - projection = etype.projection - }; - - RemoveProjection (unprojectedType); - - var genericInstanceType = interfaceType as GenericInstanceType; - if (genericInstanceType != null) { - var genericUnprojectedType = new GenericInstanceType (unprojectedType); - foreach (var genericArgument in genericInstanceType.GenericArguments) - genericUnprojectedType.GenericArguments.Add (genericArgument); - - unprojectedType = genericUnprojectedType; - } - - var unprojectedInterface = new InterfaceImplementation (unprojectedType); - redirectedInterfaces.Add (new KeyValuePair (implementedInterface, unprojectedInterface)); - } - } - - // Interfaces don't inherit methods of the interfaces they implement - if (!type.IsInterface) { - foreach (var implementedInterface in allImplementedInterfaces) { - RedirectInterfaceMethods (implementedInterface, redirectedMethods); - } - } - - return TypeDefinitionTreatment.RedirectImplementedMethods; - } - - private static void CollectImplementedInterfaces (TypeReference type, HashSet results) - { - var typeResolver = TypeResolver.For (type); - var typeDef = type.Resolve (); - - foreach (var implementedInterface in typeDef.Interfaces) { - var interfaceType = typeResolver.Resolve (implementedInterface.InterfaceType); - results.Add (interfaceType); - CollectImplementedInterfaces (interfaceType, results); - } - } - - private static void RedirectInterfaceMethods (TypeReference interfaceType, Collection redirectedMethods) - { - var typeResolver = TypeResolver.For (interfaceType); - var typeDef = interfaceType.Resolve (); - - foreach (var method in typeDef.Methods) { - var redirectedMethod = new MethodDefinition (method.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot, typeResolver.Resolve (method.ReturnType)); - redirectedMethod.ImplAttributes = MethodImplAttributes.Runtime; - - foreach (var parameter in method.Parameters) { - redirectedMethod.Parameters.Add (new ParameterDefinition (parameter.Name, parameter.Attributes, typeResolver.Resolve (parameter.ParameterType))); - } - - redirectedMethod.Overrides.Add (typeResolver.Resolve (method)); - redirectedMethods.Add (redirectedMethod); - } - } - - private static bool IsRedirectedType (TypeReference type) - { - var typeRefProjection = type.GetElementType ().projection as TypeReferenceProjection; - return typeRefProjection != null && typeRefProjection.Treatment == TypeReferenceTreatment.UseProjectionInfo; - } - - static bool NeedsWindowsRuntimePrefix (TypeDefinition type) - { - if ((type.Attributes & (TypeAttributes.VisibilityMask | TypeAttributes.Interface)) != TypeAttributes.Public) - return false; - - var base_type = type.BaseType; - if (base_type == null || base_type.MetadataToken.TokenType != TokenType.TypeRef) - return false; - - if (base_type.Namespace == "System") - switch (base_type.Name) { - case "Attribute": - case "MulticastDelegate": - case "ValueType": - return false; - } - - return true; - } - - public static bool IsClrImplementationType (TypeDefinition type) - { - if ((type.Attributes & (TypeAttributes.VisibilityMask | TypeAttributes.SpecialName)) != TypeAttributes.SpecialName) - return false; - return type.Name.StartsWith (""); - } - - public static void ApplyProjection (TypeDefinition type, TypeDefinitionProjection projection) - { - if (projection == null) - return; - - var treatment = projection.Treatment; - - switch (treatment & TypeDefinitionTreatment.KindMask) { - case TypeDefinitionTreatment.NormalType: - type.Attributes |= TypeAttributes.WindowsRuntime | TypeAttributes.Import; - break; - - case TypeDefinitionTreatment.NormalAttribute: - type.Attributes |= TypeAttributes.WindowsRuntime | TypeAttributes.Sealed; - break; - - case TypeDefinitionTreatment.UnmangleWindowsRuntimeName: - type.Attributes = type.Attributes & ~TypeAttributes.SpecialName | TypeAttributes.Public; - type.Name = type.Name.Substring ("".Length); - break; - - case TypeDefinitionTreatment.PrefixWindowsRuntimeName: - type.Attributes = type.Attributes & ~TypeAttributes.Public | TypeAttributes.Import; - type.Name = "" + type.Name; - break; - - case TypeDefinitionTreatment.RedirectToClrType: - type.Attributes = type.Attributes & ~TypeAttributes.Public | TypeAttributes.Import; - break; - - case TypeDefinitionTreatment.RedirectToClrAttribute: - type.Attributes = type.Attributes & ~TypeAttributes.Public; - break; - - case TypeDefinitionTreatment.RedirectImplementedMethods: { - type.Attributes |= TypeAttributes.WindowsRuntime | TypeAttributes.Import; - - foreach (var redirectedInterfacePair in projection.RedirectedInterfaces) { - type.Interfaces.Add (redirectedInterfacePair.Value); - - foreach (var customAttribute in redirectedInterfacePair.Key.CustomAttributes) - redirectedInterfacePair.Value.CustomAttributes.Add (customAttribute); - - redirectedInterfacePair.Key.CustomAttributes.Clear (); - - foreach (var method in type.Methods) { - foreach (var @override in method.Overrides) { - if (TypeReferenceEqualityComparer.AreEqual (@override.DeclaringType, redirectedInterfacePair.Key.InterfaceType)) { - @override.DeclaringType = redirectedInterfacePair.Value.InterfaceType; - } - } - } - } - - foreach (var method in projection.RedirectedMethods) { - type.Methods.Add (method); - } - } - break; - } - - if ((treatment & TypeDefinitionTreatment.Abstract) != 0) - type.Attributes |= TypeAttributes.Abstract; - - if ((treatment & TypeDefinitionTreatment.Internal) != 0) - type.Attributes &= ~TypeAttributes.Public; - - type.WindowsRuntimeProjection = projection; - } - - public static TypeDefinitionProjection RemoveProjection (TypeDefinition type) - { - if (!type.IsWindowsRuntimeProjection) - return null; - - var projection = type.WindowsRuntimeProjection; - type.WindowsRuntimeProjection = null; - - type.Attributes = projection.Attributes; - type.Name = projection.Name; - - if (projection.Treatment == TypeDefinitionTreatment.RedirectImplementedMethods) { - foreach (var method in projection.RedirectedMethods) { - type.Methods.Remove (method); - } - - foreach (var redirectedInterfacePair in projection.RedirectedInterfaces) { - foreach (var method in type.Methods) { - foreach (var @override in method.Overrides) { - if (TypeReferenceEqualityComparer.AreEqual (@override.DeclaringType, redirectedInterfacePair.Value.InterfaceType)) { - @override.DeclaringType = redirectedInterfacePair.Key.InterfaceType; - } - } - } - - foreach (var customAttribute in redirectedInterfacePair.Value.CustomAttributes) - redirectedInterfacePair.Key.CustomAttributes.Add (customAttribute); - - redirectedInterfacePair.Value.CustomAttributes.Clear (); - type.Interfaces.Remove (redirectedInterfacePair.Value); - } - } - - return projection; - } - - public static void Project (TypeReference type) - { - TypeReferenceTreatment treatment; - - ProjectionInfo info; - if (Projections.TryGetValue (type.Name, out info) && info.WinRTNamespace == type.Namespace) - treatment = TypeReferenceTreatment.UseProjectionInfo; - else - treatment = GetSpecialTypeReferenceTreatment (type); - - if (treatment != TypeReferenceTreatment.None) - ApplyProjection (type, new TypeReferenceProjection (type, treatment)); - } - - static TypeReferenceTreatment GetSpecialTypeReferenceTreatment (TypeReference type) - { - if (type.Namespace == "System") { - if (type.Name == "MulticastDelegate") - return TypeReferenceTreatment.SystemDelegate; - if (type.Name == "Attribute") - return TypeReferenceTreatment.SystemAttribute; - } - - return TypeReferenceTreatment.None; - } - - static bool IsAttribute (TypeReference type) - { - if (type.MetadataToken.TokenType != TokenType.TypeRef) - return false; - return type.Name == "Attribute" && type.Namespace == "System"; - } - - static bool IsEnum (TypeReference type) - { - if (type.MetadataToken.TokenType != TokenType.TypeRef) - return false; - return type.Name == "Enum" && type.Namespace == "System"; - } - - public static void ApplyProjection (TypeReference type, TypeReferenceProjection projection) - { - if (projection == null) - return; - - switch (projection.Treatment) { - case TypeReferenceTreatment.SystemDelegate: - case TypeReferenceTreatment.SystemAttribute: - type.Scope = type.Module.Projections.GetAssemblyReference ("System.Runtime"); - break; - - case TypeReferenceTreatment.UseProjectionInfo: - var info = Projections [type.Name]; - type.Name = info.ClrName; - type.Namespace = info.ClrNamespace; - type.Scope = type.Module.Projections.GetAssemblyReference (info.ClrAssembly); - break; - } - - type.WindowsRuntimeProjection = projection; - } - - public static TypeReferenceProjection RemoveProjection (TypeReference type) - { - if (!type.IsWindowsRuntimeProjection) - return null; - - var projection = type.WindowsRuntimeProjection; - type.WindowsRuntimeProjection = null; - - type.Name = projection.Name; - type.Namespace = projection.Namespace; - type.Scope = projection.Scope; - - return projection; - } - - public static void Project (MethodDefinition method) - { - var treatment = MethodDefinitionTreatment.None; - var other = false; - var declaring_type = method.DeclaringType; - - if (declaring_type.IsWindowsRuntime) { - if (IsClrImplementationType (declaring_type)) - treatment = MethodDefinitionTreatment.None; - else if (declaring_type.IsNested) - treatment = MethodDefinitionTreatment.None; - else if (declaring_type.IsInterface) - treatment = MethodDefinitionTreatment.Runtime | MethodDefinitionTreatment.InternalCall; - else if (declaring_type.Module.MetadataKind == MetadataKind.ManagedWindowsMetadata && !method.IsPublic) - treatment = MethodDefinitionTreatment.None; - else { - other = true; - - var base_type = declaring_type.BaseType; - if (base_type != null && base_type.MetadataToken.TokenType == TokenType.TypeRef) { - switch (GetSpecialTypeReferenceTreatment (base_type)) { - case TypeReferenceTreatment.SystemDelegate: - treatment = MethodDefinitionTreatment.Runtime | MethodDefinitionTreatment.Public; - other = false; - break; - - case TypeReferenceTreatment.SystemAttribute: - treatment = MethodDefinitionTreatment.Runtime | MethodDefinitionTreatment.InternalCall; - other = false; - break; - } - } - } - } - - if (other) { - var seen_redirected = false; - var seen_non_redirected = false; - - foreach (var @override in method.Overrides) { - if (@override.MetadataToken.TokenType == TokenType.MemberRef && ImplementsRedirectedInterface (@override)) { - seen_redirected = true; - } else { - seen_non_redirected = true; - } - } - - if (seen_redirected && !seen_non_redirected) { - treatment = MethodDefinitionTreatment.Runtime | MethodDefinitionTreatment.InternalCall | MethodDefinitionTreatment.Private; - other = false; - } - } - - if (other) - treatment |= GetMethodDefinitionTreatmentFromCustomAttributes (method); - - if (treatment != MethodDefinitionTreatment.None) - ApplyProjection (method, new MethodDefinitionProjection (method, treatment)); - } - - static MethodDefinitionTreatment GetMethodDefinitionTreatmentFromCustomAttributes (MethodDefinition method) - { - var treatment = MethodDefinitionTreatment.None; - - foreach (var attribute in method.CustomAttributes) { - var type = attribute.AttributeType; - if (type.Namespace != "Windows.UI.Xaml") - continue; - if (type.Name == "TreatAsPublicMethodAttribute") - treatment |= MethodDefinitionTreatment.Public; - else if (type.Name == "TreatAsAbstractMethodAttribute") - treatment |= MethodDefinitionTreatment.Abstract; - } - - return treatment; - } - - public static void ApplyProjection (MethodDefinition method, MethodDefinitionProjection projection) - { - if (projection == null) - return; - - var treatment = projection.Treatment; - - if ((treatment & MethodDefinitionTreatment.Abstract) != 0) - method.Attributes |= MethodAttributes.Abstract; - - if ((treatment & MethodDefinitionTreatment.Private) != 0) - method.Attributes = (method.Attributes & ~MethodAttributes.MemberAccessMask) | MethodAttributes.Private; - - if ((treatment & MethodDefinitionTreatment.Public) != 0) - method.Attributes = (method.Attributes & ~MethodAttributes.MemberAccessMask) | MethodAttributes.Public; - - if ((treatment & MethodDefinitionTreatment.Runtime) != 0) - method.ImplAttributes |= MethodImplAttributes.Runtime; - - if ((treatment & MethodDefinitionTreatment.InternalCall) != 0) - method.ImplAttributes |= MethodImplAttributes.InternalCall; - - method.WindowsRuntimeProjection = projection; - } - - public static MethodDefinitionProjection RemoveProjection (MethodDefinition method) - { - if (!method.IsWindowsRuntimeProjection) - return null; - - var projection = method.WindowsRuntimeProjection; - method.WindowsRuntimeProjection = null; - - method.Attributes = projection.Attributes; - method.ImplAttributes = projection.ImplAttributes; - method.Name = projection.Name; - - return projection; - } - - public static void Project (FieldDefinition field) - { - var treatment = FieldDefinitionTreatment.None; - var declaring_type = field.DeclaringType; - - if (declaring_type.Module.MetadataKind == MetadataKind.WindowsMetadata && field.IsRuntimeSpecialName && field.Name == "value__") { - var base_type = declaring_type.BaseType; - if (base_type != null && IsEnum (base_type)) - treatment = FieldDefinitionTreatment.Public; - } - - if (treatment != FieldDefinitionTreatment.None) - ApplyProjection (field, new FieldDefinitionProjection (field, treatment)); - } - - public static void ApplyProjection (FieldDefinition field, FieldDefinitionProjection projection) - { - if (projection == null) - return; - - if (projection.Treatment == FieldDefinitionTreatment.Public) - field.Attributes = (field.Attributes & ~FieldAttributes.FieldAccessMask) | FieldAttributes.Public; - - field.WindowsRuntimeProjection = projection; - } - - public static FieldDefinitionProjection RemoveProjection (FieldDefinition field) - { - if (!field.IsWindowsRuntimeProjection) - return null; - - var projection = field.WindowsRuntimeProjection; - field.WindowsRuntimeProjection = null; - - field.Attributes = projection.Attributes; - - return projection; - } - - static bool ImplementsRedirectedInterface (MemberReference member) - { - var declaring_type = member.DeclaringType; - TypeReference type; - switch (declaring_type.MetadataToken.TokenType) { - case TokenType.TypeRef: - type = declaring_type; - break; - - case TokenType.TypeSpec: - if (!declaring_type.IsGenericInstance) - return false; - - type = ((TypeSpecification)declaring_type).ElementType; - if (type.MetadataType != MetadataType.Class || type.MetadataToken.TokenType != TokenType.TypeRef) - return false; - - break; - - default: - return false; - } - - var projection = RemoveProjection (type); - - var found = false; - - ProjectionInfo info; - if (Projections.TryGetValue (type.Name, out info) && type.Namespace == info.WinRTNamespace) { - found = true; - } - - ApplyProjection (type, projection); - - return found; - } - - - public void AddVirtualReferences (Collection references) - { - var corlib = GetCoreLibrary (references); - corlib_version = corlib.Version; - corlib.Version = version; - - if (virtual_references == null) { - var winrt_references = GetAssemblyReferences (corlib); - Interlocked.CompareExchange (ref virtual_references, winrt_references, null); - } - - foreach (var reference in virtual_references) - references.Add (reference); - } - - public void RemoveVirtualReferences (Collection references) - { - var corlib = GetCoreLibrary (references); - corlib.Version = corlib_version; - - foreach (var reference in VirtualReferences) - references.Remove (reference); - } - - static AssemblyNameReference [] GetAssemblyReferences (AssemblyNameReference corlib) - { - var system_runtime = new AssemblyNameReference ("System.Runtime", version); - var system_runtime_interopservices_windowsruntime = new AssemblyNameReference ("System.Runtime.InteropServices.WindowsRuntime", version); - var system_objectmodel = new AssemblyNameReference ("System.ObjectModel", version); - var system_runtime_windowsruntime = new AssemblyNameReference ("System.Runtime.WindowsRuntime", version); - var system_runtime_windowsruntime_ui_xaml = new AssemblyNameReference ("System.Runtime.WindowsRuntime.UI.Xaml", version); - var system_numerics_vectors = new AssemblyNameReference ("System.Numerics.Vectors", version); - - if (corlib.HasPublicKey) { - system_runtime_windowsruntime.PublicKey = - system_runtime_windowsruntime_ui_xaml.PublicKey = corlib.PublicKey; - - system_runtime.PublicKey = - system_runtime_interopservices_windowsruntime.PublicKey = - system_objectmodel.PublicKey = - system_numerics_vectors.PublicKey = contract_pk; - } else { - system_runtime_windowsruntime.PublicKeyToken = - system_runtime_windowsruntime_ui_xaml.PublicKeyToken = corlib.PublicKeyToken; - - system_runtime.PublicKeyToken = - system_runtime_interopservices_windowsruntime.PublicKeyToken = - system_objectmodel.PublicKeyToken = - system_numerics_vectors.PublicKeyToken = contract_pk_token; - } - - return new [] { - system_runtime, - system_runtime_interopservices_windowsruntime, - system_objectmodel, - system_runtime_windowsruntime, - system_runtime_windowsruntime_ui_xaml, - system_numerics_vectors, - }; - } - - static AssemblyNameReference GetCoreLibrary (Collection references) - { - foreach (var reference in references) - if (reference.Name == "mscorlib") - return reference; - - throw new BadImageFormatException ("Missing mscorlib reference in AssemblyRef table."); - } - - AssemblyNameReference GetAssemblyReference (string name) - { - foreach (var assembly in VirtualReferences) - if (assembly.Name == name) - return assembly; - - throw new Exception (); - } - - public static void Project (ICustomAttributeProvider owner, CustomAttribute attribute) - { - if (!IsWindowsAttributeUsageAttribute (owner, attribute)) - return; - - var treatment = CustomAttributeValueTreatment.None; - var type = (TypeDefinition)owner; - - if (type.Namespace == "Windows.Foundation.Metadata") { - if (type.Name == "VersionAttribute") - treatment = CustomAttributeValueTreatment.VersionAttribute; - else if (type.Name == "DeprecatedAttribute") - treatment = CustomAttributeValueTreatment.DeprecatedAttribute; - } - - if (treatment == CustomAttributeValueTreatment.None) { - var multiple = HasAttribute (type, "Windows.Foundation.Metadata", "AllowMultipleAttribute"); - treatment = multiple ? CustomAttributeValueTreatment.AllowMultiple : CustomAttributeValueTreatment.AllowSingle; - } - - if (treatment != CustomAttributeValueTreatment.None) { - var attribute_targets = (AttributeTargets)attribute.ConstructorArguments [0].Value; - ApplyProjection (attribute, new CustomAttributeValueProjection (attribute_targets, treatment)); - } - } - - static bool IsWindowsAttributeUsageAttribute (ICustomAttributeProvider owner, CustomAttribute attribute) - { - if (owner.MetadataToken.TokenType != TokenType.TypeDef) - return false; - - var constructor = attribute.Constructor; - - if (constructor.MetadataToken.TokenType != TokenType.MemberRef) - return false; - - var declaring_type = constructor.DeclaringType; - - if (declaring_type.MetadataToken.TokenType != TokenType.TypeRef) - return false; - - // declaring type is already projected - return declaring_type.Name == "AttributeUsageAttribute" && declaring_type.Namespace == /*"Windows.Foundation.Metadata"*/"System"; - } - - static bool HasAttribute (TypeDefinition type, string @namespace, string name) - { - foreach (var attribute in type.CustomAttributes) { - var attribute_type = attribute.AttributeType; - if (attribute_type.Name == name && attribute_type.Namespace == @namespace) - return true; - } - return false; - } - - public static void ApplyProjection (CustomAttribute attribute, CustomAttributeValueProjection projection) - { - if (projection == null) - return; - - bool version_or_deprecated; - bool multiple; - - switch (projection.Treatment) { - case CustomAttributeValueTreatment.AllowSingle: - version_or_deprecated = false; - multiple = false; - break; - - case CustomAttributeValueTreatment.AllowMultiple: - version_or_deprecated = false; - multiple = true; - break; - - case CustomAttributeValueTreatment.VersionAttribute: - case CustomAttributeValueTreatment.DeprecatedAttribute: - version_or_deprecated = true; - multiple = true; - break; - - default: - throw new ArgumentException (); - } - - var attribute_targets = (AttributeTargets)attribute.ConstructorArguments [0].Value; - if (version_or_deprecated) - attribute_targets |= AttributeTargets.Constructor | AttributeTargets.Property; - attribute.ConstructorArguments [0] = new CustomAttributeArgument (attribute.ConstructorArguments [0].Type, attribute_targets); - - attribute.Properties.Add (new CustomAttributeNamedArgument ("AllowMultiple", new CustomAttributeArgument (attribute.Module.TypeSystem.Boolean, multiple))); - - attribute.projection = projection; - } - - public static CustomAttributeValueProjection RemoveProjection (CustomAttribute attribute) - { - if (attribute.projection == null) - return null; - - var projection = attribute.projection; - attribute.projection = null; - - attribute.ConstructorArguments [0] = new CustomAttributeArgument (attribute.ConstructorArguments [0].Type, projection.Targets); - attribute.Properties.Clear (); - - return projection; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/WindowsRuntimeProjections.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/WindowsRuntimeProjections.cs.meta deleted file mode 100644 index c747763..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/WindowsRuntimeProjections.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4816f370ee0b9f64ca793643ba5481ae -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic.meta deleted file mode 100644 index 7ec9f6e..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: dc4bc1e600836e94f9bbc5bd8c7cc47a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/Collection.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/Collection.cs deleted file mode 100644 index 0c5caf2..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/Collection.cs +++ /dev/null @@ -1,427 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil; -using System; -using System.Collections; -using System.Collections.Generic; - -namespace MonoFN.Collections.Generic { - - public class Collection : IList, IList { - - internal T [] items; - internal int size; - int version; - - public int Count { - get { return size; } - } - - public T this [int index] { - get { - if (index >= size) - throw new ArgumentOutOfRangeException (); - - return items [index]; - } - set { - CheckIndex (index); - if (index == size) - throw new ArgumentOutOfRangeException (); - - OnSet (value, index); - - items [index] = value; - } - } - - public int Capacity { - get { return items.Length; } - set { - if (value < 0 || value < size) - throw new ArgumentOutOfRangeException (); - - Resize (value); - } - } - - bool ICollection.IsReadOnly { - get { return false; } - } - - bool IList.IsFixedSize { - get { return false; } - } - - bool IList.IsReadOnly { - get { return false; } - } - - object IList.this [int index] { - get { return this [index]; } - set { - CheckIndex (index); - - try { - this [index] = (T)value; - return; - } - catch (InvalidCastException) { - } - catch (NullReferenceException) { - } - - throw new ArgumentException (); - } - } - - int ICollection.Count { - get { return Count; } - } - - bool ICollection.IsSynchronized { - get { return false; } - } - - object ICollection.SyncRoot { - get { return this; } - } - - public Collection () - { - items = Empty.Array; - } - - public Collection (int capacity) - { - if (capacity < 0) - throw new ArgumentOutOfRangeException (); - - items = capacity == 0 - ? Empty.Array - : new T [capacity]; - } - - public Collection (ICollection items) - { - if (items == null) - throw new ArgumentNullException ("items"); - - this.items = new T [items.Count]; - items.CopyTo (this.items, 0); - this.size = this.items.Length; - } - - public void Add (T item) - { - if (size == items.Length) - Grow (1); - - OnAdd (item, size); - - items [size++] = item; - version++; - } - - public bool Contains (T item) - { - return IndexOf (item) != -1; - } - - public int IndexOf (T item) - { - return Array.IndexOf (items, item, 0, size); - } - - public void Insert (int index, T item) - { - CheckIndex (index); - if (size == items.Length) - Grow (1); - - OnInsert (item, index); - - Shift (index, 1); - items [index] = item; - version++; - } - - public void RemoveAt (int index) - { - if (index < 0 || index >= size) - throw new ArgumentOutOfRangeException (); - - var item = items [index]; - - OnRemove (item, index); - - Shift (index, -1); - version++; - } - - public bool Remove (T item) - { - var index = IndexOf (item); - if (index == -1) - return false; - - OnRemove (item, index); - - Shift (index, -1); - version++; - - return true; - } - - public void Clear () - { - OnClear (); - - Array.Clear (items, 0, size); - size = 0; - version++; - } - - public void CopyTo (T [] array, int arrayIndex) - { - Array.Copy (items, 0, array, arrayIndex, size); - } - - public T [] ToArray () - { - var array = new T [size]; - Array.Copy (items, 0, array, 0, size); - return array; - } - - void CheckIndex (int index) - { - if (index < 0 || index > size) - throw new ArgumentOutOfRangeException (); - } - - void Shift (int start, int delta) - { - if (delta < 0) - start -= delta; - - if (start < size) - Array.Copy (items, start, items, start + delta, size - start); - - size += delta; - - if (delta < 0) - Array.Clear (items, size, -delta); - } - - protected virtual void OnAdd (T item, int index) - { - } - - protected virtual void OnInsert (T item, int index) - { - } - - protected virtual void OnSet (T item, int index) - { - } - - protected virtual void OnRemove (T item, int index) - { - } - - protected virtual void OnClear () - { - } - - internal virtual void Grow (int desired) - { - int new_size = size + desired; - if (new_size <= items.Length) - return; - - const int default_capacity = 4; - - new_size = System.Math.Max ( - System.Math.Max (items.Length * 2, default_capacity), - new_size); - - Resize (new_size); - } - - protected void Resize (int new_size) - { - if (new_size == size) - return; - if (new_size < size) - throw new ArgumentOutOfRangeException (); - - items = items.Resize (new_size); - } - - int IList.Add (object value) - { - try { - Add ((T)value); - return size - 1; - } - catch (InvalidCastException) { - } - catch (NullReferenceException) { - } - - throw new ArgumentException (); - } - - void IList.Clear () - { - Clear (); - } - - bool IList.Contains (object value) - { - return ((IList)this).IndexOf (value) > -1; - } - - int IList.IndexOf (object value) - { - try { - return IndexOf ((T)value); - } - catch (InvalidCastException) { - } - catch (NullReferenceException) { - } - - return -1; - } - - void IList.Insert (int index, object value) - { - CheckIndex (index); - - try { - Insert (index, (T)value); - return; - } - catch (InvalidCastException) { - } - catch (NullReferenceException) { - } - - throw new ArgumentException (); - } - - void IList.Remove (object value) - { - try { - Remove ((T)value); - } - catch (InvalidCastException) { - } - catch (NullReferenceException) { - } - } - - void IList.RemoveAt (int index) - { - RemoveAt (index); - } - - void ICollection.CopyTo (Array array, int index) - { - Array.Copy (items, 0, array, index, size); - } - - public Enumerator GetEnumerator () - { - return new Enumerator (this); - } - - IEnumerator IEnumerable.GetEnumerator () - { - return new Enumerator (this); - } - - IEnumerator IEnumerable.GetEnumerator () - { - return new Enumerator (this); - } - - public struct Enumerator : IEnumerator, IDisposable { - - Collection collection; - T current; - - int next; - readonly int version; - - public T Current { - get { return current; } - } - - object IEnumerator.Current { - get { - CheckState (); - - if (next <= 0) - throw new InvalidOperationException (); - - return current; - } - } - - internal Enumerator (Collection collection) - : this () - { - this.collection = collection; - this.version = collection.version; - } - - public bool MoveNext () - { - CheckState (); - - if (next < 0) - return false; - - if (next < collection.size) { - current = collection.items [next++]; - return true; - } - - next = -1; - return false; - } - - public void Reset () - { - CheckState (); - - next = 0; - } - - void CheckState () - { - if (collection == null) - throw new ObjectDisposedException (GetType ().FullName); - - if (version != collection.version) - throw new InvalidOperationException (); - } - - public void Dispose () - { - collection = null; - } - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/Collection.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/Collection.cs.meta deleted file mode 100644 index 01bd872..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/Collection.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d1f0d8a176addda42a579d710c12a7ec -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/ReadOnlyCollection.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/ReadOnlyCollection.cs deleted file mode 100644 index 736f1c0..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/ReadOnlyCollection.cs +++ /dev/null @@ -1,101 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading; - -namespace MonoFN.Collections.Generic { - - public sealed class ReadOnlyCollection : Collection, ICollection, IList { - - static ReadOnlyCollection empty; - - public static ReadOnlyCollection Empty { - get { - if (empty != null) - return empty; - - Interlocked.CompareExchange (ref empty, new ReadOnlyCollection (), null); - return empty; - } - } - - bool ICollection.IsReadOnly { - get { return true; } - } - - bool IList.IsFixedSize { - get { return true; } - } - - bool IList.IsReadOnly { - get { return true; } - } - - ReadOnlyCollection () - { - } - - public ReadOnlyCollection (T [] array) - { - if (array == null) - throw new ArgumentNullException (); - - Initialize (array, array.Length); - } - - public ReadOnlyCollection (Collection collection) - { - if (collection == null) - throw new ArgumentNullException (); - - Initialize (collection.items, collection.size); - } - - void Initialize (T [] items, int size) - { - this.items = new T [size]; - Array.Copy (items, 0, this.items, 0, size); - this.size = size; - } - - internal override void Grow (int desired) - { - throw new InvalidOperationException (); - } - - protected override void OnAdd (T item, int index) - { - throw new InvalidOperationException (); - } - - protected override void OnClear () - { - throw new InvalidOperationException (); - } - - protected override void OnInsert (T item, int index) - { - throw new InvalidOperationException (); - } - - protected override void OnRemove (T item, int index) - { - throw new InvalidOperationException (); - } - - protected override void OnSet (T item, int index) - { - throw new InvalidOperationException (); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/ReadOnlyCollection.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/ReadOnlyCollection.cs.meta deleted file mode 100644 index a89c654..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Collections.Generic/ReadOnlyCollection.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d94cb0938831f1349b60e63292a04b67 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography.meta deleted file mode 100644 index 65c6957..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 83669b0a87b783648b0d69a7b37e00ab -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoConvert.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoConvert.cs deleted file mode 100644 index c6eacee..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoConvert.cs +++ /dev/null @@ -1,290 +0,0 @@ -// -// CryptoConvert.cs - Crypto Convertion Routines -// -// Author: -// Sebastien Pouliot -// -// (C) 2003 Motus Technologies Inc. (http://www.motus.com) -// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Security.Cryptography; - -namespace MonoFN.Security.Cryptography { - - static class CryptoConvert { - - static private int ToInt32LE (byte [] bytes, int offset) - { - return (bytes [offset + 3] << 24) | (bytes [offset + 2] << 16) | (bytes [offset + 1] << 8) | bytes [offset]; - } - - static private uint ToUInt32LE (byte [] bytes, int offset) - { - return (uint)((bytes [offset + 3] << 24) | (bytes [offset + 2] << 16) | (bytes [offset + 1] << 8) | bytes [offset]); - } - - static private byte [] GetBytesLE (int val) - { - return new byte [] { - (byte) (val & 0xff), - (byte) ((val >> 8) & 0xff), - (byte) ((val >> 16) & 0xff), - (byte) ((val >> 24) & 0xff) - }; - } - - static private byte [] Trim (byte [] array) - { - for (int i = 0; i < array.Length; i++) { - if (array [i] != 0x00) { - byte [] result = new byte [array.Length - i]; - Buffer.BlockCopy (array, i, result, 0, result.Length); - return result; - } - } - return null; - } - - static RSA FromCapiPrivateKeyBlob (byte [] blob, int offset) - { - RSAParameters rsap = new RSAParameters (); - try { - if ((blob [offset] != 0x07) || // PRIVATEKEYBLOB (0x07) - (blob [offset + 1] != 0x02) || // Version (0x02) - (blob [offset + 2] != 0x00) || // Reserved (word) - (blob [offset + 3] != 0x00) || - (ToUInt32LE (blob, offset + 8) != 0x32415352)) // DWORD magic = RSA2 - throw new CryptographicException ("Invalid blob header"); - - // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...) - // int algId = ToInt32LE (blob, offset+4); - - // DWORD bitlen - int bitLen = ToInt32LE (blob, offset + 12); - - // DWORD public exponent - byte [] exp = new byte [4]; - Buffer.BlockCopy (blob, offset + 16, exp, 0, 4); - Array.Reverse (exp); - rsap.Exponent = Trim (exp); - - int pos = offset + 20; - // BYTE modulus[rsapubkey.bitlen/8]; - int byteLen = (bitLen >> 3); - rsap.Modulus = new byte [byteLen]; - Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen); - Array.Reverse (rsap.Modulus); - pos += byteLen; - - // BYTE prime1[rsapubkey.bitlen/16]; - int byteHalfLen = (byteLen >> 1); - rsap.P = new byte [byteHalfLen]; - Buffer.BlockCopy (blob, pos, rsap.P, 0, byteHalfLen); - Array.Reverse (rsap.P); - pos += byteHalfLen; - - // BYTE prime2[rsapubkey.bitlen/16]; - rsap.Q = new byte [byteHalfLen]; - Buffer.BlockCopy (blob, pos, rsap.Q, 0, byteHalfLen); - Array.Reverse (rsap.Q); - pos += byteHalfLen; - - // BYTE exponent1[rsapubkey.bitlen/16]; - rsap.DP = new byte [byteHalfLen]; - Buffer.BlockCopy (blob, pos, rsap.DP, 0, byteHalfLen); - Array.Reverse (rsap.DP); - pos += byteHalfLen; - - // BYTE exponent2[rsapubkey.bitlen/16]; - rsap.DQ = new byte [byteHalfLen]; - Buffer.BlockCopy (blob, pos, rsap.DQ, 0, byteHalfLen); - Array.Reverse (rsap.DQ); - pos += byteHalfLen; - - // BYTE coefficient[rsapubkey.bitlen/16]; - rsap.InverseQ = new byte [byteHalfLen]; - Buffer.BlockCopy (blob, pos, rsap.InverseQ, 0, byteHalfLen); - Array.Reverse (rsap.InverseQ); - pos += byteHalfLen; - - // ok, this is hackish but CryptoAPI support it so... - // note: only works because CRT is used by default - // http://bugzilla.ximian.com/show_bug.cgi?id=57941 - rsap.D = new byte [byteLen]; // must be allocated - if (pos + byteLen + offset <= blob.Length) { - // BYTE privateExponent[rsapubkey.bitlen/8]; - Buffer.BlockCopy (blob, pos, rsap.D, 0, byteLen); - Array.Reverse (rsap.D); - } - } - catch (Exception e) { - throw new CryptographicException ("Invalid blob.", e); - } - - RSA rsa = null; - try { - rsa = RSA.Create (); - rsa.ImportParameters (rsap); - } - catch (CryptographicException) { - // this may cause problem when this code is run under - // the SYSTEM identity on Windows (e.g. ASP.NET). See - // http://bugzilla.ximian.com/show_bug.cgi?id=77559 - bool throws = false; - try { - CspParameters csp = new CspParameters (); - csp.Flags = CspProviderFlags.UseMachineKeyStore; - rsa = new RSACryptoServiceProvider (csp); - rsa.ImportParameters (rsap); - } - catch { - throws = true; - } - - if (throws) { - // rethrow original, not the latter, exception if this fails - throw; - } - } - return rsa; - } - - static RSA FromCapiPublicKeyBlob (byte [] blob, int offset) - { - try { - if ((blob [offset] != 0x06) || // PUBLICKEYBLOB (0x06) - (blob [offset + 1] != 0x02) || // Version (0x02) - (blob [offset + 2] != 0x00) || // Reserved (word) - (blob [offset + 3] != 0x00) || - (ToUInt32LE (blob, offset + 8) != 0x31415352)) // DWORD magic = RSA1 - throw new CryptographicException ("Invalid blob header"); - - // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...) - // int algId = ToInt32LE (blob, offset+4); - - // DWORD bitlen - int bitLen = ToInt32LE (blob, offset + 12); - - // DWORD public exponent - RSAParameters rsap = new RSAParameters (); - rsap.Exponent = new byte [3]; - rsap.Exponent [0] = blob [offset + 18]; - rsap.Exponent [1] = blob [offset + 17]; - rsap.Exponent [2] = blob [offset + 16]; - - int pos = offset + 20; - // BYTE modulus[rsapubkey.bitlen/8]; - int byteLen = (bitLen >> 3); - rsap.Modulus = new byte [byteLen]; - Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen); - Array.Reverse (rsap.Modulus); - - RSA rsa = null; - try { - rsa = RSA.Create (); - rsa.ImportParameters (rsap); - } - catch (CryptographicException) { - // this may cause problem when this code is run under - // the SYSTEM identity on Windows (e.g. ASP.NET). See - // http://bugzilla.ximian.com/show_bug.cgi?id=77559 - CspParameters csp = new CspParameters (); - csp.Flags = CspProviderFlags.UseMachineKeyStore; - rsa = new RSACryptoServiceProvider (csp); - rsa.ImportParameters (rsap); - } - return rsa; - } - catch (Exception e) { - throw new CryptographicException ("Invalid blob.", e); - } - } - - // PRIVATEKEYBLOB - // PUBLICKEYBLOB - static public RSA FromCapiKeyBlob (byte [] blob) - { - return FromCapiKeyBlob (blob, 0); - } - - static public RSA FromCapiKeyBlob (byte [] blob, int offset) - { - if (blob == null) - throw new ArgumentNullException ("blob"); - if (offset >= blob.Length) - throw new ArgumentException ("blob is too small."); - - switch (blob [offset]) { - case 0x00: - // this could be a public key inside an header - // like "sn -e" would produce - if (blob [offset + 12] == 0x06) { - return FromCapiPublicKeyBlob (blob, offset + 12); - } - break; - case 0x06: - return FromCapiPublicKeyBlob (blob, offset); - case 0x07: - return FromCapiPrivateKeyBlob (blob, offset); - } - throw new CryptographicException ("Unknown blob format."); - } - - static public byte [] ToCapiPublicKeyBlob (RSA rsa) - { - RSAParameters p = rsa.ExportParameters (false); - int keyLength = p.Modulus.Length; // in bytes - byte [] blob = new byte [20 + keyLength]; - - blob [0] = 0x06; // Type - PUBLICKEYBLOB (0x06) - blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02) - // [2], [3] // RESERVED - Always 0 - blob [5] = 0x24; // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN) - blob [8] = 0x52; // Magic - RSA1 (ASCII in hex) - blob [9] = 0x53; - blob [10] = 0x41; - blob [11] = 0x31; - - byte [] bitlen = GetBytesLE (keyLength << 3); - blob [12] = bitlen [0]; // bitlen - blob [13] = bitlen [1]; - blob [14] = bitlen [2]; - blob [15] = bitlen [3]; - - // public exponent (DWORD) - int pos = 16; - int n = p.Exponent.Length; - while (n > 0) - blob [pos++] = p.Exponent [--n]; - // modulus - pos = 20; - byte [] part = p.Modulus; - int len = part.Length; - Array.Reverse (part, 0, len); - Buffer.BlockCopy (part, 0, blob, pos, len); - pos += len; - return blob; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoConvert.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoConvert.cs.meta deleted file mode 100644 index ba086fa..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoConvert.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 40b945bb6ba518c4b8ce54b5e54a06b5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoService.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoService.cs deleted file mode 100644 index 5582b17..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoService.cs +++ /dev/null @@ -1,202 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.PE; -using MonoFN.Security.Cryptography; -using System; -using System.IO; -using System.Reflection; -using System.Runtime.Serialization; -using System.Security.Cryptography; - -namespace MonoFN.Cecil { - - // Most of this code has been adapted - // from Jeroen Frijters' fantastic work - // in IKVM.Reflection.Emit. Thanks! - - static class CryptoService { - - public static byte [] GetPublicKey (WriterParameters parameters) - { - using (var rsa = parameters.CreateRSA ()) { - var cspBlob = CryptoConvert.ToCapiPublicKeyBlob (rsa); - var publicKey = new byte [12 + cspBlob.Length]; - Buffer.BlockCopy (cspBlob, 0, publicKey, 12, cspBlob.Length); - // The first 12 bytes are documented at: - // http://msdn.microsoft.com/library/en-us/cprefadd/html/grfungethashfromfile.asp - // ALG_ID - Signature - publicKey [1] = 36; - // ALG_ID - Hash - publicKey [4] = 4; - publicKey [5] = 128; - // Length of Public Key (in bytes) - publicKey [8] = (byte)(cspBlob.Length >> 0); - publicKey [9] = (byte)(cspBlob.Length >> 8); - publicKey [10] = (byte)(cspBlob.Length >> 16); - publicKey [11] = (byte)(cspBlob.Length >> 24); - return publicKey; - } - } - - public static void StrongName (Stream stream, ImageWriter writer, WriterParameters parameters) - { - int strong_name_pointer; - - var strong_name = CreateStrongName (parameters, HashStream (stream, writer, out strong_name_pointer)); - PatchStrongName (stream, strong_name_pointer, strong_name); - } - - static void PatchStrongName (Stream stream, int strong_name_pointer, byte [] strong_name) - { - stream.Seek (strong_name_pointer, SeekOrigin.Begin); - stream.Write (strong_name, 0, strong_name.Length); - } - - static byte [] CreateStrongName (WriterParameters parameters, byte [] hash) - { - const string hash_algo = "SHA1"; - - using (var rsa = parameters.CreateRSA ()) { - var formatter = new RSAPKCS1SignatureFormatter (rsa); - formatter.SetHashAlgorithm (hash_algo); - - byte [] signature = formatter.CreateSignature (hash); - Array.Reverse (signature); - - return signature; - } - } - - static byte [] HashStream (Stream stream, ImageWriter writer, out int strong_name_pointer) - { - const int buffer_size = 8192; - - var text = writer.text; - var header_size = (int)writer.GetHeaderSize (); - var text_section_pointer = (int)text.PointerToRawData; - var strong_name_directory = writer.GetStrongNameSignatureDirectory (); - - if (strong_name_directory.Size == 0) - throw new InvalidOperationException (); - - strong_name_pointer = (int)(text_section_pointer - + (strong_name_directory.VirtualAddress - text.VirtualAddress)); - var strong_name_length = (int)strong_name_directory.Size; - - var sha1 = new SHA1Managed (); - var buffer = new byte [buffer_size]; - using (var crypto_stream = new CryptoStream (Stream.Null, sha1, CryptoStreamMode.Write)) { - stream.Seek (0, SeekOrigin.Begin); - CopyStreamChunk (stream, crypto_stream, buffer, header_size); - - stream.Seek (text_section_pointer, SeekOrigin.Begin); - CopyStreamChunk (stream, crypto_stream, buffer, (int)strong_name_pointer - text_section_pointer); - - stream.Seek (strong_name_length, SeekOrigin.Current); - CopyStreamChunk (stream, crypto_stream, buffer, (int)(stream.Length - (strong_name_pointer + strong_name_length))); - } - - return sha1.Hash; - } - - static void CopyStreamChunk (Stream stream, Stream dest_stream, byte [] buffer, int length) - { - while (length > 0) { - int read = stream.Read (buffer, 0, System.Math.Min (buffer.Length, length)); - dest_stream.Write (buffer, 0, read); - length -= read; - } - } - - public static byte [] ComputeHash (string file) - { - if (!File.Exists (file)) - return Empty.Array; - - using (var stream = new FileStream (file, FileMode.Open, FileAccess.Read, FileShare.Read)) - return ComputeHash (stream); - } - - public static byte [] ComputeHash (Stream stream) - { - const int buffer_size = 8192; - - var sha1 = new SHA1Managed (); - var buffer = new byte [buffer_size]; - - using (var crypto_stream = new CryptoStream (Stream.Null, sha1, CryptoStreamMode.Write)) - CopyStreamChunk (stream, crypto_stream, buffer, (int)stream.Length); - - return sha1.Hash; - } - - public static byte [] ComputeHash (params ByteBuffer [] buffers) - { - var sha1 = new SHA1Managed (); - - using (var crypto_stream = new CryptoStream (Stream.Null, sha1, CryptoStreamMode.Write)) { - for (int i = 0; i < buffers.Length; i++) { - crypto_stream.Write (buffers [i].buffer, 0, buffers [i].length); - } - } - - return sha1.Hash; - } - - public static Guid ComputeGuid (byte [] hash) - { - // From corefx/src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobContentId.cs - var guid = new byte [16]; - Buffer.BlockCopy (hash, 0, guid, 0, 16); - - // modify the guid data so it decodes to the form of a "random" guid ala rfc4122 - guid [7] = (byte)((guid [7] & 0x0f) | (4 << 4)); - guid [8] = (byte)((guid [8] & 0x3f) | (2 << 6)); - - return new Guid (guid); - } - } - - static partial class Mixin { - - public static RSA CreateRSA (this WriterParameters writer_parameters) - { - byte [] key; - string key_container; - - if (writer_parameters.StrongNameKeyBlob != null) - return CryptoConvert.FromCapiKeyBlob (writer_parameters.StrongNameKeyBlob); - - if (writer_parameters.StrongNameKeyContainer != null) - key_container = writer_parameters.StrongNameKeyContainer; - else if (!TryGetKeyContainer (writer_parameters.StrongNameKeyPair, out key, out key_container)) - return CryptoConvert.FromCapiKeyBlob (key); - - var parameters = new CspParameters { - Flags = CspProviderFlags.UseMachineKeyStore, - KeyContainerName = key_container, - KeyNumber = 2, - }; - - return new RSACryptoServiceProvider (parameters); - } - - static bool TryGetKeyContainer (ISerializable key_pair, out byte [] key, out string key_container) - { - var info = new SerializationInfo (typeof (StrongNameKeyPair), new FormatterConverter ()); - key_pair.GetObjectData (info, new StreamingContext ()); - - key = (byte [])info.GetValue ("_keyPairArray", typeof (byte [])); - key_container = info.GetString ("_keyPairContainer"); - return key_container != null; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoService.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoService.cs.meta deleted file mode 100644 index 13f5dd0..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Security.Cryptography/CryptoService.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c49085888b0afc047af3a03b536acdc2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.meta deleted file mode 100644 index 5cf9349..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e55573663ea38f0408c4c465c48fceac -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Disposable.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Disposable.cs deleted file mode 100644 index 37c3e93..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Disposable.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN { - - static class Disposable { - - public static Disposable Owned (T value) where T : class, IDisposable - { - return new Disposable (value, owned: true); - } - - public static Disposable NotOwned (T value) where T : class, IDisposable - { - return new Disposable (value, owned: false); - } - } - - struct Disposable : IDisposable where T : class, IDisposable { - - internal readonly T value; - readonly bool owned; - - public Disposable (T value, bool owned) - { - this.value = value; - this.owned = owned; - } - - public void Dispose () - { - if (value != null && owned) - value.Dispose (); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Disposable.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Disposable.cs.meta deleted file mode 100644 index 03c0571..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Disposable.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1aa8d86dc5c9323419e8b535d582fccf -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Empty.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Empty.cs deleted file mode 100644 index 63a91e3..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Empty.cs +++ /dev/null @@ -1,62 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Collections.Generic; -using System; - -namespace MonoFN { - - static class Empty { - - public static readonly T [] Array = new T [0]; - } - - class ArgumentNullOrEmptyException : ArgumentException { - - public ArgumentNullOrEmptyException (string paramName) - : base ("Argument null or empty", paramName) - { - } - } -} - -namespace MonoFN.Cecil { - - static partial class Mixin { - - public static bool IsNullOrEmpty (this T [] self) - { - return self == null || self.Length == 0; - } - - public static bool IsNullOrEmpty (this Collection self) - { - return self == null || self.size == 0; - } - - public static T [] Resize (this T [] self, int length) - { - Array.Resize (ref self, length); - return self; - } - - public static T [] Add (this T [] self, T item) - { - if (self == null) { - self = new [] { item }; - return self; - } - - self = self.Resize (self.Length + 1); - self [self.Length - 1] = item; - return self; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Empty.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Empty.cs.meta deleted file mode 100644 index 76bd34a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/Empty.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4662c38d1a951c24b89aeae3390acd39 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/MergeSort.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/MergeSort.cs deleted file mode 100644 index 4fde695..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/MergeSort.cs +++ /dev/null @@ -1,66 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; -using System.Collections.Generic; - -namespace MonoFN { - - class MergeSort { - private readonly T [] elements; - private readonly T [] buffer; - private readonly IComparer comparer; - - private MergeSort (T [] elements, IComparer comparer) - { - this.elements = elements; - this.buffer = new T [elements.Length]; - Array.Copy (this.elements, this.buffer, elements.Length); - this.comparer = comparer; - } - - public static void Sort (T [] source, IComparer comparer) - { - Sort (source, 0, source.Length, comparer); - } - - public static void Sort (T [] source, int start, int length, IComparer comparer) - { - new MergeSort (source, comparer).Sort (start, length); - } - - private void Sort (int start, int length) - { - TopDownSplitMerge (this.buffer, this.elements, start, length); - } - - private void TopDownSplitMerge (T [] a, T [] b, int start, int end) - { - if (end - start < 2) - return; - - int middle = (end + start) / 2; - TopDownSplitMerge (b, a, start, middle); - TopDownSplitMerge (b, a, middle, end); - TopDownMerge (a, b, start, middle, end); - } - - private void TopDownMerge (T [] a, T [] b, int start, int middle, int end) - { - for (int i = start, j = middle, k = start; k < end; k++) { - if (i < middle && (j >= end || comparer.Compare (a [i], a [j]) <= 0)) { - b [k] = a [i++]; - } else { - b [k] = a [j++]; - } - } - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/MergeSort.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/MergeSort.cs.meta deleted file mode 100644 index 5e6a613..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono/MergeSort.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3c35ecf3bff670b4c8b367ed632eee37 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/MonoFN.Cecil.asmdef b/Assets/FishNet/CodeGenerating/cecil-0.11.4/MonoFN.Cecil.asmdef deleted file mode 100644 index 1470137..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/MonoFN.Cecil.asmdef +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "FishNet.Codegen.Cecil", - "references": [], - "includePlatforms": [ - "Editor" - ], - "excludePlatforms": [], - "allowUnsafeCode": true, - "overrideReferences": true, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} \ No newline at end of file diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/ProjectInfo.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/ProjectInfo.cs deleted file mode 100644 index fe89134..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/ProjectInfo.cs +++ /dev/null @@ -1,20 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// -// Licensed under the MIT/X11 license. -// - -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyProduct (Consts.AssemblyName)] -[assembly: AssemblyCopyright ("Copyright © 2008 - 2018 Jb Evain")] - -[assembly: ComVisible (false)] - -[assembly: AssemblyVersion ("0.11.4.0")] -[assembly: AssemblyFileVersion ("0.11.4.0")] -[assembly: AssemblyInformationalVersion ("0.11.4.0")] diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/ProjectInfo.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/ProjectInfo.cs.meta deleted file mode 100644 index 8fac323..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/ProjectInfo.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 468fd5ab13cb01b4381e9c667167b2e0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/README.md b/Assets/FishNet/CodeGenerating/cecil-0.11.4/README.md deleted file mode 100644 index c052e4c..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/README.md +++ /dev/null @@ -1,17 +0,0 @@ -Cecil -===== - -Mono.Cecil is a library to generate and inspect programs and libraries in the ECMA CIL form. - -To put it simply, you can use Cecil to: - -* Analyze .NET binaries using a simple and powerful object model, without having to load assemblies to use Reflection. -* Modify .NET binaries, add new metadata structures and alter the IL code. - -Cecil has been around since 2004 and is [widely used](https://github.com/jbevain/cecil/wiki/Users) in the .NET community. If you're using Cecil, or depend on a framework, project, or product using it, please consider [sponsoring Cecil](https://github.com/sponsors/jbevain/). - -Read about the Cecil development on the [development log](http://cecil.pe). - -To discuss Cecil, the best place is the [mono-cecil](https://groups.google.com/group/mono-cecil) Google Group. - -Cecil is a project under the benevolent umbrella of the [.NET Foundation](http://www.dotnetfoundation.org/). diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/cecil.snk b/Assets/FishNet/CodeGenerating/cecil-0.11.4/cecil.snk deleted file mode 100644 index c0380d194f28fc76a32d609b60da01d7f75657ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50096iT%UggG;A_TF?RUV?t(kNEnx54!(WE| zo@MGjY|$Id%cG-Hy@5ZU6GjEe_m6m7Uv$xpOcIN1B2`p7e>sB3~cm zDW?cfd({<#QDET<$3xN#qdK`)4E<=-dHnFad3ts`>|GE5@D-l+8RrSv6_;LzzU!~G zDm71|RX2O{FNU*iu>_zkxxvYHzN7NP0U`%U6b2c#K#i!@kbU;m&G}wLoGQ8MzvN7I zVps}ItYiDqW&pNdSAEmIua6gslpwgz;|JK$fk347H3pq@PT~VnK2Cagr>-!#sS2uz z?Er147%=gTx1{Lwitv&hd-PjTZ*up+3wSwrgYZA@SdqYdIwefG0Jr1>3uCU`_Oz%+ zMjn{Y&tQb2iHN9%LAqS3jJRp%Gg_`=^CZ;s4Qs6+7iARLaJNyT32*%p!zfQ#{mx4S z^}RMT_mkhK%9Qzrqfd8knqfVM&6bEaW+rN;I$~OI74DrrYP|z(;tRA<^x+KVX6+Tg zCfUqOu zs^7YOICxFn@|;LrrzlTuQ-2P8i@R^W>ZK`(uUnbRg&hZ6grggv>|2HE2rKJ?CnnA8 zR{HQmyK%WDlW?y{ryW|@-1NcKWy;Fh^T>F;uh}LqMwg+;(p+)^E|s(wxvCLpH<1nQ i{y?rxRw8t*>j7s<@|KG8kMC+K`9c~&xPULDw@({VAtYk} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/cecil.snk.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/cecil.snk.meta deleted file mode 100644 index 1ad02ba..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/cecil.snk.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 71693fd731252cb4a9bd4d8abf7846c0 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks.meta deleted file mode 100644 index c070af3..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: c13f8d2e52ed89246b2f0dbc1f6ba1aa -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks.meta deleted file mode 100644 index ab82924..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 15700071751bd1349a26170e9f6a1f14 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs deleted file mode 100644 index 4c82583..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs +++ /dev/null @@ -1,15 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -//[assembly: AssemblyTitle ("MonoFN.Cecil.Rocks")] - -[assembly: CLSCompliant (false)] diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs.meta deleted file mode 100644 index a9fbe70..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/AssemblyInfo.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f9ceb0221cb78b247b676d0ea5d57fc8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/DocCommentId.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/DocCommentId.cs deleted file mode 100644 index 783dbde..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/DocCommentId.cs +++ /dev/null @@ -1,261 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; -using System.Collections.Generic; -using System.Text; - -namespace MonoFN.Cecil.Rocks { - - public class DocCommentId { - StringBuilder id; - - DocCommentId () - { - id = new StringBuilder (); - } - - void WriteField (FieldDefinition field) - { - WriteDefinition ('F', field); - } - - void WriteEvent (EventDefinition @event) - { - WriteDefinition ('E', @event); - } - - void WriteType (TypeDefinition type) - { - id.Append ('T').Append (':'); - WriteTypeFullName (type); - } - - void WriteMethod (MethodDefinition method) - { - WriteDefinition ('M', method); - - if (method.HasGenericParameters) { - id.Append ('`').Append ('`'); - id.Append (method.GenericParameters.Count); - } - - if (method.HasParameters) - WriteParameters (method.Parameters); - - if (IsConversionOperator (method)) - WriteReturnType (method); - } - - static bool IsConversionOperator (MethodDefinition self) - { - if (self == null) - throw new ArgumentNullException ("self"); - - return self.IsSpecialName - && (self.Name == "op_Explicit" || self.Name == "op_Implicit"); - } - - void WriteReturnType (MethodDefinition method) - { - id.Append ('~'); - WriteTypeSignature (method.ReturnType); - } - - void WriteProperty (PropertyDefinition property) - { - WriteDefinition ('P', property); - - if (property.HasParameters) - WriteParameters (property.Parameters); - } - - void WriteParameters (IList parameters) - { - id.Append ('('); - WriteList (parameters, p => WriteTypeSignature (p.ParameterType)); - id.Append (')'); - } - - void WriteTypeSignature (TypeReference type) - { - switch (type.MetadataType) { - case MetadataType.Array: - WriteArrayTypeSignature ((ArrayType)type); - break; - case MetadataType.ByReference: - WriteTypeSignature (((ByReferenceType)type).ElementType); - id.Append ('@'); - break; - case MetadataType.FunctionPointer: - WriteFunctionPointerTypeSignature ((FunctionPointerType)type); - break; - case MetadataType.GenericInstance: - WriteGenericInstanceTypeSignature ((GenericInstanceType)type); - break; - case MetadataType.Var: - id.Append ('`'); - id.Append (((GenericParameter)type).Position); - break; - case MetadataType.MVar: - id.Append ('`').Append ('`'); - id.Append (((GenericParameter)type).Position); - break; - case MetadataType.OptionalModifier: - WriteModiferTypeSignature ((OptionalModifierType)type, '!'); - break; - case MetadataType.RequiredModifier: - WriteModiferTypeSignature ((RequiredModifierType)type, '|'); - break; - case MetadataType.Pointer: - WriteTypeSignature (((PointerType)type).ElementType); - id.Append ('*'); - break; - default: - WriteTypeFullName (type); - break; - } - } - - void WriteGenericInstanceTypeSignature (GenericInstanceType type) - { - if (type.ElementType.IsTypeSpecification ()) - throw new NotSupportedException (); - - WriteTypeFullName (type.ElementType, stripGenericArity: true); - id.Append ('{'); - WriteList (type.GenericArguments, WriteTypeSignature); - id.Append ('}'); - } - - void WriteList (IList list, Action action) - { - for (int i = 0; i < list.Count; i++) { - if (i > 0) - id.Append (','); - - action (list [i]); - } - } - - void WriteModiferTypeSignature (IModifierType type, char id) - { - WriteTypeSignature (type.ElementType); - this.id.Append (id); - WriteTypeSignature (type.ModifierType); - } - - void WriteFunctionPointerTypeSignature (FunctionPointerType type) - { - id.Append ("=FUNC:"); - WriteTypeSignature (type.ReturnType); - - if (type.HasParameters) - WriteParameters (type.Parameters); - } - - void WriteArrayTypeSignature (ArrayType type) - { - WriteTypeSignature (type.ElementType); - - if (type.IsVector) { - id.Append ("[]"); - return; - } - - id.Append ("["); - - WriteList (type.Dimensions, dimension => { - if (dimension.LowerBound.HasValue) - id.Append (dimension.LowerBound.Value); - - id.Append (':'); - - if (dimension.UpperBound.HasValue) - id.Append (dimension.UpperBound.Value - (dimension.LowerBound.GetValueOrDefault () + 1)); - }); - - id.Append ("]"); - } - - void WriteDefinition (char id, IMemberDefinition member) - { - this.id.Append (id) - .Append (':'); - - WriteTypeFullName (member.DeclaringType); - this.id.Append ('.'); - WriteItemName (member.Name); - } - - void WriteTypeFullName (TypeReference type, bool stripGenericArity = false) - { - if (type.DeclaringType != null) { - WriteTypeFullName (type.DeclaringType); - id.Append ('.'); - } - - if (!string.IsNullOrEmpty (type.Namespace)) { - id.Append (type.Namespace); - id.Append ('.'); - } - - var name = type.Name; - - if (stripGenericArity) { - var index = name.LastIndexOf ('`'); - if (index > 0) - name = name.Substring (0, index); - } - - id.Append (name); - } - - void WriteItemName (string name) - { - id.Append (name.Replace ('.', '#').Replace ('<', '{').Replace ('>', '}')); - } - - public override string ToString () - { - return id.ToString (); - } - - public static string GetDocCommentId (IMemberDefinition member) - { - if (member == null) - throw new ArgumentNullException ("member"); - - var documentId = new DocCommentId (); - - switch (member.MetadataToken.TokenType) { - case TokenType.Field: - documentId.WriteField ((FieldDefinition)member); - break; - case TokenType.Method: - documentId.WriteMethod ((MethodDefinition)member); - break; - case TokenType.TypeDef: - documentId.WriteType ((TypeDefinition)member); - break; - case TokenType.Event: - documentId.WriteEvent ((EventDefinition)member); - break; - case TokenType.Property: - documentId.WriteProperty ((PropertyDefinition)member); - break; - default: - throw new NotSupportedException (member.FullName); - } - - return documentId.ToString (); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/DocCommentId.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/DocCommentId.cs.meta deleted file mode 100644 index 7cc833e..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/DocCommentId.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 370e40931a1b9cf478e08e66fd2a9eac -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/Functional.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/Functional.cs deleted file mode 100644 index 90c24ed..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/Functional.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; -using System.Collections.Generic; - -namespace MonoFN.Cecil.Rocks { - - static class Functional { - - public static System.Func Y (System.Func, System.Func> f) - { - System.Func g = null; - g = f (a => g (a)); - return g; - } - - public static IEnumerable Prepend (this IEnumerable source, TSource element) - { - if (source == null) - throw new ArgumentNullException ("source"); - - return PrependIterator (source, element); - } - - static IEnumerable PrependIterator (IEnumerable source, TSource element) - { - yield return element; - - foreach (var item in source) - yield return item; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/Functional.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/Functional.cs.meta deleted file mode 100644 index 15f593e..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/Functional.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b481a942e0bdf8649b6b5b20db207190 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ILParser.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ILParser.cs deleted file mode 100644 index 9e814a6..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ILParser.cs +++ /dev/null @@ -1,228 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Cil; -using MonoFN.Collections.Generic; -using System; - -namespace MonoFN.Cecil.Rocks { - -#if UNITY_EDITOR - public -#endif - interface IILVisitor { - void OnInlineNone (OpCode opcode); - void OnInlineSByte (OpCode opcode, sbyte value); - void OnInlineByte (OpCode opcode, byte value); - void OnInlineInt32 (OpCode opcode, int value); - void OnInlineInt64 (OpCode opcode, long value); - void OnInlineSingle (OpCode opcode, float value); - void OnInlineDouble (OpCode opcode, double value); - void OnInlineString (OpCode opcode, string value); - void OnInlineBranch (OpCode opcode, int offset); - void OnInlineSwitch (OpCode opcode, int [] offsets); - void OnInlineVariable (OpCode opcode, VariableDefinition variable); - void OnInlineArgument (OpCode opcode, ParameterDefinition parameter); - void OnInlineSignature (OpCode opcode, CallSite callSite); - void OnInlineType (OpCode opcode, TypeReference type); - void OnInlineField (OpCode opcode, FieldReference field); - void OnInlineMethod (OpCode opcode, MethodReference method); - } - -#if UNITY_EDITOR - public -#endif - static class ILParser { - - class ParseContext { - public CodeReader Code { get; set; } - public int Position { get; set; } - public MetadataReader Metadata { get; set; } - public Collection Variables { get; set; } - public IILVisitor Visitor { get; set; } - } - - public static void Parse (MethodDefinition method, IILVisitor visitor) - { - if (method == null) - throw new ArgumentNullException ("method"); - if (visitor == null) - throw new ArgumentNullException ("visitor"); - if (!method.HasBody || !method.HasImage) - throw new ArgumentException (); - - method.Module.Read (method, (m, _) => { - ParseMethod (m, visitor); - return true; - }); - } - - static void ParseMethod (MethodDefinition method, IILVisitor visitor) - { - var context = CreateContext (method, visitor); - var code = context.Code; - - var flags = code.ReadByte (); - - switch (flags & 0x3) { - case 0x2: // tiny - int code_size = flags >> 2; - ParseCode (code_size, context); - break; - case 0x3: // fat - code.Advance (-1); - ParseFatMethod (context); - break; - default: - throw new NotSupportedException (); - } - - code.MoveBackTo (context.Position); - } - - static ParseContext CreateContext (MethodDefinition method, IILVisitor visitor) - { - var code = method.Module.Read (method, (_, reader) => reader.code); - var position = code.MoveTo (method); - - return new ParseContext { - Code = code, - Position = position, - Metadata = code.reader, - Visitor = visitor, - }; - } - - static void ParseFatMethod (ParseContext context) - { - var code = context.Code; - - code.Advance (4); - var code_size = code.ReadInt32 (); - var local_var_token = code.ReadToken (); - - if (local_var_token != MetadataToken.Zero) - context.Variables = code.ReadVariables (local_var_token); - - ParseCode (code_size, context); - } - - static void ParseCode (int code_size, ParseContext context) - { - var code = context.Code; - var metadata = context.Metadata; - var visitor = context.Visitor; - - var start = code.Position; - var end = start + code_size; - - while (code.Position < end) { - var il_opcode = code.ReadByte (); - var opcode = il_opcode != 0xfe - ? OpCodes.OneByteOpCode [il_opcode] - : OpCodes.TwoBytesOpCode [code.ReadByte ()]; - - switch (opcode.OperandType) { - case OperandType.InlineNone: - visitor.OnInlineNone (opcode); - break; - case OperandType.InlineSwitch: - var length = code.ReadInt32 (); - var branches = new int [length]; - for (int i = 0; i < length; i++) - branches [i] = code.ReadInt32 (); - visitor.OnInlineSwitch (opcode, branches); - break; - case OperandType.ShortInlineBrTarget: - visitor.OnInlineBranch (opcode, code.ReadSByte ()); - break; - case OperandType.InlineBrTarget: - visitor.OnInlineBranch (opcode, code.ReadInt32 ()); - break; - case OperandType.ShortInlineI: - if (opcode == OpCodes.Ldc_I4_S) - visitor.OnInlineSByte (opcode, code.ReadSByte ()); - else - visitor.OnInlineByte (opcode, code.ReadByte ()); - break; - case OperandType.InlineI: - visitor.OnInlineInt32 (opcode, code.ReadInt32 ()); - break; - case OperandType.InlineI8: - visitor.OnInlineInt64 (opcode, code.ReadInt64 ()); - break; - case OperandType.ShortInlineR: - visitor.OnInlineSingle (opcode, code.ReadSingle ()); - break; - case OperandType.InlineR: - visitor.OnInlineDouble (opcode, code.ReadDouble ()); - break; - case OperandType.InlineSig: - visitor.OnInlineSignature (opcode, code.GetCallSite (code.ReadToken ())); - break; - case OperandType.InlineString: - visitor.OnInlineString (opcode, code.GetString (code.ReadToken ())); - break; - case OperandType.ShortInlineArg: - visitor.OnInlineArgument (opcode, code.GetParameter (code.ReadByte ())); - break; - case OperandType.InlineArg: - visitor.OnInlineArgument (opcode, code.GetParameter (code.ReadInt16 ())); - break; - case OperandType.ShortInlineVar: - visitor.OnInlineVariable (opcode, GetVariable (context, code.ReadByte ())); - break; - case OperandType.InlineVar: - visitor.OnInlineVariable (opcode, GetVariable (context, code.ReadInt16 ())); - break; - case OperandType.InlineTok: - case OperandType.InlineField: - case OperandType.InlineMethod: - case OperandType.InlineType: - var member = metadata.LookupToken (code.ReadToken ()); - switch (member.MetadataToken.TokenType) { - case TokenType.TypeDef: - case TokenType.TypeRef: - case TokenType.TypeSpec: - visitor.OnInlineType (opcode, (TypeReference)member); - break; - case TokenType.Method: - case TokenType.MethodSpec: - visitor.OnInlineMethod (opcode, (MethodReference)member); - break; - case TokenType.Field: - visitor.OnInlineField (opcode, (FieldReference)member); - break; - case TokenType.MemberRef: - var field_ref = member as FieldReference; - if (field_ref != null) { - visitor.OnInlineField (opcode, field_ref); - break; - } - - var method_ref = member as MethodReference; - if (method_ref != null) { - visitor.OnInlineMethod (opcode, method_ref); - break; - } - - throw new InvalidOperationException (); - } - break; - } - } - } - - static VariableDefinition GetVariable (ParseContext context, int index) - { - return context.Variables [index]; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ILParser.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ILParser.cs.meta deleted file mode 100644 index 65cbdbe..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ILParser.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2916628c81c279046adb746612d6067b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs deleted file mode 100644 index feaabbf..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs +++ /dev/null @@ -1,411 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using MonoFN.Cecil.Cil; -using System; - -namespace MonoFN.Cecil.Rocks { - -#if UNITY_EDITOR - public -#endif - static class MethodBodyRocks { - - public static void SimplifyMacros (this MethodBody self) - { - if (self == null) - throw new ArgumentNullException ("self"); - - foreach (var instruction in self.Instructions) { - if (instruction.OpCode.OpCodeType != OpCodeType.Macro) - continue; - - switch (instruction.OpCode.Code) { - case Code.Ldarg_0: - ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (0)); - break; - case Code.Ldarg_1: - ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (1)); - break; - case Code.Ldarg_2: - ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (2)); - break; - case Code.Ldarg_3: - ExpandMacro (instruction, OpCodes.Ldarg, self.GetParameter (3)); - break; - case Code.Ldloc_0: - ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [0]); - break; - case Code.Ldloc_1: - ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [1]); - break; - case Code.Ldloc_2: - ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [2]); - break; - case Code.Ldloc_3: - ExpandMacro (instruction, OpCodes.Ldloc, self.Variables [3]); - break; - case Code.Stloc_0: - ExpandMacro (instruction, OpCodes.Stloc, self.Variables [0]); - break; - case Code.Stloc_1: - ExpandMacro (instruction, OpCodes.Stloc, self.Variables [1]); - break; - case Code.Stloc_2: - ExpandMacro (instruction, OpCodes.Stloc, self.Variables [2]); - break; - case Code.Stloc_3: - ExpandMacro (instruction, OpCodes.Stloc, self.Variables [3]); - break; - case Code.Ldarg_S: - instruction.OpCode = OpCodes.Ldarg; - break; - case Code.Ldarga_S: - instruction.OpCode = OpCodes.Ldarga; - break; - case Code.Starg_S: - instruction.OpCode = OpCodes.Starg; - break; - case Code.Ldloc_S: - instruction.OpCode = OpCodes.Ldloc; - break; - case Code.Ldloca_S: - instruction.OpCode = OpCodes.Ldloca; - break; - case Code.Stloc_S: - instruction.OpCode = OpCodes.Stloc; - break; - case Code.Ldc_I4_M1: - ExpandMacro (instruction, OpCodes.Ldc_I4, -1); - break; - case Code.Ldc_I4_0: - ExpandMacro (instruction, OpCodes.Ldc_I4, 0); - break; - case Code.Ldc_I4_1: - ExpandMacro (instruction, OpCodes.Ldc_I4, 1); - break; - case Code.Ldc_I4_2: - ExpandMacro (instruction, OpCodes.Ldc_I4, 2); - break; - case Code.Ldc_I4_3: - ExpandMacro (instruction, OpCodes.Ldc_I4, 3); - break; - case Code.Ldc_I4_4: - ExpandMacro (instruction, OpCodes.Ldc_I4, 4); - break; - case Code.Ldc_I4_5: - ExpandMacro (instruction, OpCodes.Ldc_I4, 5); - break; - case Code.Ldc_I4_6: - ExpandMacro (instruction, OpCodes.Ldc_I4, 6); - break; - case Code.Ldc_I4_7: - ExpandMacro (instruction, OpCodes.Ldc_I4, 7); - break; - case Code.Ldc_I4_8: - ExpandMacro (instruction, OpCodes.Ldc_I4, 8); - break; - case Code.Ldc_I4_S: - ExpandMacro (instruction, OpCodes.Ldc_I4, (int)(sbyte)instruction.Operand); - break; - case Code.Br_S: - instruction.OpCode = OpCodes.Br; - break; - case Code.Brfalse_S: - instruction.OpCode = OpCodes.Brfalse; - break; - case Code.Brtrue_S: - instruction.OpCode = OpCodes.Brtrue; - break; - case Code.Beq_S: - instruction.OpCode = OpCodes.Beq; - break; - case Code.Bge_S: - instruction.OpCode = OpCodes.Bge; - break; - case Code.Bgt_S: - instruction.OpCode = OpCodes.Bgt; - break; - case Code.Ble_S: - instruction.OpCode = OpCodes.Ble; - break; - case Code.Blt_S: - instruction.OpCode = OpCodes.Blt; - break; - case Code.Bne_Un_S: - instruction.OpCode = OpCodes.Bne_Un; - break; - case Code.Bge_Un_S: - instruction.OpCode = OpCodes.Bge_Un; - break; - case Code.Bgt_Un_S: - instruction.OpCode = OpCodes.Bgt_Un; - break; - case Code.Ble_Un_S: - instruction.OpCode = OpCodes.Ble_Un; - break; - case Code.Blt_Un_S: - instruction.OpCode = OpCodes.Blt_Un; - break; - case Code.Leave_S: - instruction.OpCode = OpCodes.Leave; - break; - } - } - } - - static void ExpandMacro (Instruction instruction, OpCode opcode, object operand) - { - instruction.OpCode = opcode; - instruction.Operand = operand; - } - - static void MakeMacro (Instruction instruction, OpCode opcode) - { - instruction.OpCode = opcode; - instruction.Operand = null; - } - - public static void Optimize (this MethodBody self) - { - if (self == null) - throw new ArgumentNullException ("self"); - - OptimizeLongs (self); - OptimizeMacros (self); - } - - static void OptimizeLongs (this MethodBody self) - { - for (var i = 0; i < self.Instructions.Count; i++) { - var instruction = self.Instructions [i]; - if (instruction.OpCode.Code != Code.Ldc_I8) - continue; - var l = (long)instruction.Operand; - if (l >= int.MaxValue || l <= int.MinValue) - continue; - ExpandMacro (instruction, OpCodes.Ldc_I4, (int)l); - self.Instructions.Insert (++i, Instruction.Create (OpCodes.Conv_I8)); - } - } - - public static void OptimizeMacros (this MethodBody self) - { - if (self == null) - throw new ArgumentNullException ("self"); - - var method = self.Method; - - foreach (var instruction in self.Instructions) { - int index; - switch (instruction.OpCode.Code) { - case Code.Ldarg: - index = ((ParameterDefinition)instruction.Operand).Index; - if (index == -1 && instruction.Operand == self.ThisParameter) - index = 0; - else if (method.HasThis) - index++; - - switch (index) { - case 0: - MakeMacro (instruction, OpCodes.Ldarg_0); - break; - case 1: - MakeMacro (instruction, OpCodes.Ldarg_1); - break; - case 2: - MakeMacro (instruction, OpCodes.Ldarg_2); - break; - case 3: - MakeMacro (instruction, OpCodes.Ldarg_3); - break; - default: - if (index < 256) - ExpandMacro (instruction, OpCodes.Ldarg_S, instruction.Operand); - break; - } - break; - case Code.Ldloc: - index = ((VariableDefinition)instruction.Operand).Index; - switch (index) { - case 0: - MakeMacro (instruction, OpCodes.Ldloc_0); - break; - case 1: - MakeMacro (instruction, OpCodes.Ldloc_1); - break; - case 2: - MakeMacro (instruction, OpCodes.Ldloc_2); - break; - case 3: - MakeMacro (instruction, OpCodes.Ldloc_3); - break; - default: - if (index < 256) - ExpandMacro (instruction, OpCodes.Ldloc_S, instruction.Operand); - break; - } - break; - case Code.Stloc: - index = ((VariableDefinition)instruction.Operand).Index; - switch (index) { - case 0: - MakeMacro (instruction, OpCodes.Stloc_0); - break; - case 1: - MakeMacro (instruction, OpCodes.Stloc_1); - break; - case 2: - MakeMacro (instruction, OpCodes.Stloc_2); - break; - case 3: - MakeMacro (instruction, OpCodes.Stloc_3); - break; - default: - if (index < 256) - ExpandMacro (instruction, OpCodes.Stloc_S, instruction.Operand); - break; - } - break; - case Code.Ldarga: - index = ((ParameterDefinition)instruction.Operand).Index; - if (index == -1 && instruction.Operand == self.ThisParameter) - index = 0; - else if (method.HasThis) - index++; - if (index < 256) - ExpandMacro (instruction, OpCodes.Ldarga_S, instruction.Operand); - break; - case Code.Ldloca: - if (((VariableDefinition)instruction.Operand).Index < 256) - ExpandMacro (instruction, OpCodes.Ldloca_S, instruction.Operand); - break; - case Code.Ldc_I4: - int i = (int)instruction.Operand; - switch (i) { - case -1: - MakeMacro (instruction, OpCodes.Ldc_I4_M1); - break; - case 0: - MakeMacro (instruction, OpCodes.Ldc_I4_0); - break; - case 1: - MakeMacro (instruction, OpCodes.Ldc_I4_1); - break; - case 2: - MakeMacro (instruction, OpCodes.Ldc_I4_2); - break; - case 3: - MakeMacro (instruction, OpCodes.Ldc_I4_3); - break; - case 4: - MakeMacro (instruction, OpCodes.Ldc_I4_4); - break; - case 5: - MakeMacro (instruction, OpCodes.Ldc_I4_5); - break; - case 6: - MakeMacro (instruction, OpCodes.Ldc_I4_6); - break; - case 7: - MakeMacro (instruction, OpCodes.Ldc_I4_7); - break; - case 8: - MakeMacro (instruction, OpCodes.Ldc_I4_8); - break; - default: - if (i >= -128 && i < 128) - ExpandMacro (instruction, OpCodes.Ldc_I4_S, (sbyte)i); - break; - } - break; - } - } - - OptimizeBranches (self); - } - - static void OptimizeBranches (MethodBody body) - { - ComputeOffsets (body); - - foreach (var instruction in body.Instructions) { - if (instruction.OpCode.OperandType != OperandType.InlineBrTarget) - continue; - - if (OptimizeBranch (instruction)) - ComputeOffsets (body); - } - } - - static bool OptimizeBranch (Instruction instruction) - { - var offset = ((Instruction)instruction.Operand).Offset - (instruction.Offset + instruction.OpCode.Size + 4); - if (!(offset >= -128 && offset <= 127)) - return false; - - switch (instruction.OpCode.Code) { - case Code.Br: - instruction.OpCode = OpCodes.Br_S; - break; - case Code.Brfalse: - instruction.OpCode = OpCodes.Brfalse_S; - break; - case Code.Brtrue: - instruction.OpCode = OpCodes.Brtrue_S; - break; - case Code.Beq: - instruction.OpCode = OpCodes.Beq_S; - break; - case Code.Bge: - instruction.OpCode = OpCodes.Bge_S; - break; - case Code.Bgt: - instruction.OpCode = OpCodes.Bgt_S; - break; - case Code.Ble: - instruction.OpCode = OpCodes.Ble_S; - break; - case Code.Blt: - instruction.OpCode = OpCodes.Blt_S; - break; - case Code.Bne_Un: - instruction.OpCode = OpCodes.Bne_Un_S; - break; - case Code.Bge_Un: - instruction.OpCode = OpCodes.Bge_Un_S; - break; - case Code.Bgt_Un: - instruction.OpCode = OpCodes.Bgt_Un_S; - break; - case Code.Ble_Un: - instruction.OpCode = OpCodes.Ble_Un_S; - break; - case Code.Blt_Un: - instruction.OpCode = OpCodes.Blt_Un_S; - break; - case Code.Leave: - instruction.OpCode = OpCodes.Leave_S; - break; - } - - return true; - } - - static void ComputeOffsets (MethodBody body) - { - var offset = 0; - foreach (var instruction in body.Instructions) { - instruction.Offset = offset; - offset += instruction.GetSize (); - } - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs.meta deleted file mode 100644 index 3067d55..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodBodyRocks.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0c47d4756ed8120429bad0887cff0366 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs deleted file mode 100644 index 040f795..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs +++ /dev/null @@ -1,72 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil.Rocks { - -#if UNITY_EDITOR - public -#endif - static class MethodDefinitionRocks { - - public static MethodDefinition GetBaseMethod (this MethodDefinition self) - { - if (self == null) - throw new ArgumentNullException ("self"); - if (!self.IsVirtual) - return self; - if (self.IsNewSlot) - return self; - - var base_type = ResolveBaseType (self.DeclaringType); - while (base_type != null) { - var @base = GetMatchingMethod (base_type, self); - if (@base != null) - return @base; - - base_type = ResolveBaseType (base_type); - } - - return self; - } - - public static MethodDefinition GetOriginalBaseMethod (this MethodDefinition self) - { - if (self == null) - throw new ArgumentNullException ("self"); - - while (true) { - var @base = self.GetBaseMethod (); - if (@base == self) - return self; - - self = @base; - } - } - - static TypeDefinition ResolveBaseType (TypeDefinition type) - { - if (type == null) - return null; - - var base_type = type.BaseType; - if (base_type == null) - return null; - - return base_type.Resolve (); - } - - static MethodDefinition GetMatchingMethod (TypeDefinition type, MethodDefinition method) - { - return MetadataResolver.GetMethod (type.Methods, method); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs.meta deleted file mode 100644 index af399f1..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/MethodDefinitionRocks.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7a5d7596633ddb043b9785a7fa7bfa6f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs deleted file mode 100644 index 7eeab2b..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MonoFN.Cecil.Rocks { - -#if UNITY_EDITOR - public -#endif - static class ModuleDefinitionRocks { - - public static IEnumerable GetAllTypes (this ModuleDefinition self) - { - if (self == null) - throw new ArgumentNullException ("self"); - - // it was fun to write, but we need a somewhat less convoluted implementation - return self.Types.SelectMany ( - Functional.Y> (f => type => type.NestedTypes.SelectMany (f).Prepend (type))); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs.meta deleted file mode 100644 index 682485f..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ModuleDefinitionRocks.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d90334a1cd085c047b9b8eddaa65cf09 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ParameterReferenceRocks.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ParameterReferenceRocks.cs deleted file mode 100644 index 30bbb70..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ParameterReferenceRocks.cs +++ /dev/null @@ -1,11 +0,0 @@ - -namespace MonoFN.Cecil.Rocks { - - public static class ParameterReferenceRocks { - - public static int GetSequence (this ParameterReference self) - { - return self.Index + 1; - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ParameterReferenceRocks.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ParameterReferenceRocks.cs.meta deleted file mode 100644 index 30bde11..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/ParameterReferenceRocks.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d276fe9256961b847b51a9bfc735384b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs deleted file mode 100644 index bf22572..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs +++ /dev/null @@ -1,157 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -#if !NET_CORE - -using System; -using System.Security; -using SSP = System.Security.Permissions; - -namespace MonoFN.Cecil.Rocks { - -#if UNITY_EDITOR - public -#endif - static class SecurityDeclarationRocks { - - public static PermissionSet ToPermissionSet (this SecurityDeclaration self) - { - if (self == null) - throw new ArgumentNullException ("self"); - - PermissionSet set; - if (TryProcessPermissionSetAttribute (self, out set)) - return set; - - return CreatePermissionSet (self); - } - - static bool TryProcessPermissionSetAttribute (SecurityDeclaration declaration, out PermissionSet set) - { - set = null; - - if (!declaration.HasSecurityAttributes && declaration.SecurityAttributes.Count != 1) - return false; - - var security_attribute = declaration.SecurityAttributes [0]; - if (!security_attribute.AttributeType.IsTypeOf ("System.Security.Permissions", "PermissionSetAttribute")) - return false; - - var attribute = new SSP.PermissionSetAttribute ((SSP.SecurityAction)declaration.Action); - - var named_argument = security_attribute.Properties [0]; - string value = (string)named_argument.Argument.Value; - switch (named_argument.Name) { - case "XML": - attribute.XML = value; - break; - case "Name": - attribute.Name = value; - break; - default: - throw new NotImplementedException (named_argument.Name); - } - - set = attribute.CreatePermissionSet (); - return true; - } - - static PermissionSet CreatePermissionSet (SecurityDeclaration declaration) - { - var set = new PermissionSet (SSP.PermissionState.None); - - foreach (var attribute in declaration.SecurityAttributes) { - var permission = CreatePermission (declaration, attribute); - set.AddPermission (permission); - } - - return set; - } - - static IPermission CreatePermission (SecurityDeclaration declaration, SecurityAttribute attribute) - { - var attribute_type = Type.GetType (attribute.AttributeType.FullName); - if (attribute_type == null) - throw new ArgumentException ("attribute"); - - var security_attribute = CreateSecurityAttribute (attribute_type, declaration); - if (security_attribute == null) - throw new InvalidOperationException (); - - CompleteSecurityAttribute (security_attribute, attribute); - - return security_attribute.CreatePermission (); - } - - static void CompleteSecurityAttribute (SSP.SecurityAttribute security_attribute, SecurityAttribute attribute) - { - if (attribute.HasFields) - CompleteSecurityAttributeFields (security_attribute, attribute); - - if (attribute.HasProperties) - CompleteSecurityAttributeProperties (security_attribute, attribute); - } - - static void CompleteSecurityAttributeFields (SSP.SecurityAttribute security_attribute, SecurityAttribute attribute) - { - var type = security_attribute.GetType (); - - foreach (var named_argument in attribute.Fields) - type.GetField (named_argument.Name).SetValue (security_attribute, named_argument.Argument.Value); - } - - static void CompleteSecurityAttributeProperties (SSP.SecurityAttribute security_attribute, SecurityAttribute attribute) - { - var type = security_attribute.GetType (); - - foreach (var named_argument in attribute.Properties) - type.GetProperty (named_argument.Name).SetValue (security_attribute, named_argument.Argument.Value, null); - } - - static SSP.SecurityAttribute CreateSecurityAttribute (Type attribute_type, SecurityDeclaration declaration) - { - SSP.SecurityAttribute security_attribute; - try { - security_attribute = (SSP.SecurityAttribute)Activator.CreateInstance ( - attribute_type, new object [] { (SSP.SecurityAction)declaration.Action }); - } - catch (MissingMethodException) { - security_attribute = (SSP.SecurityAttribute)Activator.CreateInstance (attribute_type, new object [0]); - } - - return security_attribute; - } - - public static SecurityDeclaration ToSecurityDeclaration (this PermissionSet self, SecurityAction action, ModuleDefinition module) - { - if (self == null) - throw new ArgumentNullException ("self"); - if (module == null) - throw new ArgumentNullException ("module"); - - var declaration = new SecurityDeclaration (action); - - var attribute = new SecurityAttribute ( - module.TypeSystem.LookupType ("System.Security.Permissions", "PermissionSetAttribute")); - - attribute.Properties.Add ( - new CustomAttributeNamedArgument ( - "XML", - new CustomAttributeArgument ( - module.TypeSystem.String, self.ToXml ().ToString ()))); - - declaration.SecurityAttributes.Add (attribute); - - return declaration; - } - } -} - -#endif diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs.meta deleted file mode 100644 index c659e1a..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/SecurityDeclarationRocks.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e9d89d937b712004089aafb3a1391907 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs deleted file mode 100644 index 7b7d78f..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs +++ /dev/null @@ -1,65 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MonoFN.Cecil.Rocks { - -#if UNITY_EDITOR - public -#endif - static class TypeDefinitionRocks { - - public static IEnumerable GetConstructors (this TypeDefinition self) - { - if (self == null) - throw new ArgumentNullException ("self"); - - if (!self.HasMethods) - return Empty.Array; - - return self.Methods.Where (method => method.IsConstructor); - } - - public static MethodDefinition GetStaticConstructor (this TypeDefinition self) - { - if (self == null) - throw new ArgumentNullException ("self"); - - if (!self.HasMethods) - return null; - - return self.GetConstructors ().FirstOrDefault (ctor => ctor.IsStatic); - } - - public static IEnumerable GetMethods (this TypeDefinition self) - { - if (self == null) - throw new ArgumentNullException ("self"); - - if (!self.HasMethods) - return Empty.Array; - - return self.Methods.Where (method => !method.IsConstructor); - } - - public static TypeReference GetEnumUnderlyingType (this TypeDefinition self) - { - if (self == null) - throw new ArgumentNullException ("self"); - if (!self.IsEnum) - throw new ArgumentException (); - - return Mixin.GetEnumUnderlyingType (self); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs.meta deleted file mode 100644 index 620eacd..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeDefinitionRocks.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b4d5393ac3307a84ca5babfbdcad9eea -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs deleted file mode 100644 index 1fdd284..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs +++ /dev/null @@ -1,87 +0,0 @@ -// -// Author: -// Jb Evain (jbevain@gmail.com) -// -// Copyright (c) 2008 - 2015 Jb Evain -// Copyright (c) 2008 - 2011 Novell, Inc. -// -// Licensed under the MIT/X11 license. -// - -using System; - -namespace MonoFN.Cecil.Rocks { - -#if UNITY_EDITOR - public -#endif - static class TypeReferenceRocks { - - public static ArrayType MakeArrayType (this TypeReference self) - { - return new ArrayType (self); - } - - public static ArrayType MakeArrayType (this TypeReference self, int rank) - { - if (rank == 0) - throw new ArgumentOutOfRangeException ("rank"); - - var array = new ArrayType (self); - - for (int i = 1; i < rank; i++) - array.Dimensions.Add (new ArrayDimension ()); - - return array; - } - - public static PointerType MakePointerType (this TypeReference self) - { - return new PointerType (self); - } - - public static ByReferenceType MakeByReferenceType (this TypeReference self) - { - return new ByReferenceType (self); - } - - public static OptionalModifierType MakeOptionalModifierType (this TypeReference self, TypeReference modifierType) - { - return new OptionalModifierType (modifierType, self); - } - - public static RequiredModifierType MakeRequiredModifierType (this TypeReference self, TypeReference modifierType) - { - return new RequiredModifierType (modifierType, self); - } - - public static GenericInstanceType MakeGenericInstanceType (this TypeReference self, params TypeReference [] arguments) - { - if (self == null) - throw new ArgumentNullException ("self"); - if (arguments == null) - throw new ArgumentNullException ("arguments"); - if (arguments.Length == 0) - throw new ArgumentException (); - if (self.GenericParameters.Count != arguments.Length) - throw new ArgumentException (); - - var instance = new GenericInstanceType (self, arguments.Length); - - foreach (var argument in arguments) - instance.GenericArguments.Add (argument); - - return instance; - } - - public static PinnedType MakePinnedType (this TypeReference self) - { - return new PinnedType (self); - } - - public static SentinelType MakeSentinelType (this TypeReference self) - { - return new SentinelType (self); - } - } -} diff --git a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs.meta b/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs.meta deleted file mode 100644 index 0239366..0000000 --- a/Assets/FishNet/CodeGenerating/cecil-0.11.4/rocks/Mono.Cecil.Rocks/TypeReferenceRocks.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 25d089a650c8e0f45a6f9086aaf0004a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/DOCUMENTATION.txt b/Assets/FishNet/DOCUMENTATION.txt deleted file mode 100644 index 8318532..0000000 --- a/Assets/FishNet/DOCUMENTATION.txt +++ /dev/null @@ -1,3 +0,0 @@ -Please view our online documentation for the most up to date information: https://fish-networking.gitbook.io/docs/ - -Support is available on our discord. Please contact FirstGearGames#0001 @ https://discord.gg/Ta9HgDh4Hj \ No newline at end of file diff --git a/Assets/FishNet/Demos.meta b/Assets/FishNet/Demos.meta deleted file mode 100644 index 584457f..0000000 --- a/Assets/FishNet/Demos.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: ec29d7e4581430a4db9b879b3d950b84 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Demos/FishNet.Demos.asmdef b/Assets/FishNet/Demos/FishNet.Demos.asmdef deleted file mode 100644 index f82c292..0000000 --- a/Assets/FishNet/Demos/FishNet.Demos.asmdef +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "FishNet.Demos", - "references": [ - "GUID:7c88a4a7926ee5145ad2dfa06f454c67" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} \ No newline at end of file diff --git a/Assets/FishNet/Demos/FishNet.Demos.asmdef.meta b/Assets/FishNet/Demos/FishNet.Demos.asmdef.meta deleted file mode 100644 index 56eb043..0000000 --- a/Assets/FishNet/Demos/FishNet.Demos.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 0bb35fc3181999548a4abea731e00e89 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Demos/Network LOD.meta b/Assets/FishNet/Demos/Network LOD.meta deleted file mode 100644 index 362f1e8..0000000 --- a/Assets/FishNet/Demos/Network LOD.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 9842088b2698c394dbf5c7329faddb21 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Demos/Network LOD/Network LOD Demo README.txt b/Assets/FishNet/Demos/Network LOD/Network LOD Demo README.txt deleted file mode 100644 index d54ba7b..0000000 --- a/Assets/FishNet/Demos/Network LOD/Network LOD Demo README.txt +++ /dev/null @@ -1,7 +0,0 @@ -- Open scene. -- Select LOD Tester in scene and slide LOD Level. -- Press Play. - -Can only be tested as separate client and server. -LOD Level cannot be changed at runtime. -A level of 1 is the same as not using LOD. \ No newline at end of file diff --git a/Assets/FishNet/Demos/Network LOD/Network LOD Demo README.txt.meta b/Assets/FishNet/Demos/Network LOD/Network LOD Demo README.txt.meta deleted file mode 100644 index 839dcc1..0000000 --- a/Assets/FishNet/Demos/Network LOD/Network LOD Demo README.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: c373771d26a3af04a84bd1afd5aabfe8 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Demos/Network LOD/Prefabs.meta b/Assets/FishNet/Demos/Network LOD/Prefabs.meta deleted file mode 100644 index 158c421..0000000 --- a/Assets/FishNet/Demos/Network LOD/Prefabs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 3ff6d7c186e86974b94a6f0902aef961 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Demos/Network LOD/Prefabs/NetworkLOD_Prefab.prefab b/Assets/FishNet/Demos/Network LOD/Prefabs/NetworkLOD_Prefab.prefab deleted file mode 100644 index 2775029..0000000 --- a/Assets/FishNet/Demos/Network LOD/Prefabs/NetworkLOD_Prefab.prefab +++ /dev/null @@ -1,311 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &4512293259955182959 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4512293259955182957} - - component: {fileID: 4512293259955182956} - - component: {fileID: 6667641716399555817} - - component: {fileID: -5271135124957689192} - - component: {fileID: 247864930697348647} - - component: {fileID: 526411540949090343} - - component: {fileID: 6088059624252575348} - m_Layer: 0 - m_Name: NetworkLOD_Prefab - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &4512293259955182957 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4512293259955182959} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 3106622367778460228} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &4512293259955182956 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4512293259955182959} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - k__BackingField: 0 - k__BackingField: 0 - k__BackingField: {fileID: 0} - _networkBehaviours: - - {fileID: 6667641716399555817} - - {fileID: -5271135124957689192} - - {fileID: 526411540949090343} - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 - NetworkObserver: {fileID: 0} - k__BackingField: 2 - k__BackingField: 0 - _scenePathHash: 0 - k__BackingField: 0 - k__BackingField: 8082309187455287958 - _sceneNetworkObjects: - - {fileID: 4512293259955182956} ---- !u!114 &6667641716399555817 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4512293259955182959} - m_Enabled: 0 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9880e85651efd71469092ce519317f7b, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 0 - _addedNetworkObject: {fileID: 4512293259955182956} - _networkObjectCache: {fileID: 4512293259955182956} - _renderer: {fileID: 8565678507340770901} ---- !u!114 &-5271135124957689192 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4512293259955182959} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a2836e36774ca1c4bbbee976e17b649c, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 1 - _addedNetworkObject: {fileID: 4512293259955182956} - _networkObjectCache: {fileID: 4512293259955182956} - _componentConfiguration: 0 - _synchronizeParent: 0 - _packing: - Position: 1 - Rotation: 1 - Scale: 0 - _interpolation: 2 - _extrapolation: 2 - _enableTeleport: 0 - _teleportThreshold: 1 - _clientAuthoritative: 1 - _sendToOwner: 1 - _synchronizePosition: 1 - _positionSnapping: - X: 0 - Y: 0 - Z: 0 - _synchronizeRotation: 1 - _rotationSnapping: - X: 0 - Y: 0 - Z: 0 - _synchronizeScale: 1 - _scaleSnapping: - X: 0 - Y: 0 - Z: 0 ---- !u!143 &247864930697348647 -CharacterController: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4512293259955182959} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Height: 2 - m_Radius: 0.5 - m_SlopeLimit: 45 - m_StepOffset: 0.3 - m_SkinWidth: 0.08 - m_MinMoveDistance: 0.001 - m_Center: {x: 0, y: 0, z: 0} ---- !u!114 &526411540949090343 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4512293259955182959} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a31284a274f3c3c4993d760abda8520a, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 2 - _addedNetworkObject: {fileID: 4512293259955182956} - _networkObjectCache: {fileID: 4512293259955182956} - jumpSpeed: 6 - speed: 8 - gravity: 0 - spawnable: {fileID: 233110740096973422, guid: e05b94df3e7783a48ac1ed2d12a71774, type: 3} ---- !u!114 &6088059624252575348 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4512293259955182959} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 62899f850307741f2a39c98a8b639597, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Actions: {fileID: -944628639613478452, guid: c206aa4192994a34a8f932eb995f13b9, type: 3} - m_NotificationBehavior: 2 - m_UIInputModule: {fileID: 0} - m_DeviceLostEvent: - m_PersistentCalls: - m_Calls: [] - m_DeviceRegainedEvent: - m_PersistentCalls: - m_Calls: [] - m_ControlsChangedEvent: - m_PersistentCalls: - m_Calls: [] - m_ActionEvents: - - m_PersistentCalls: - m_Calls: - - m_Target: {fileID: 526411540949090343} - m_TargetAssemblyTypeName: PlayerInputDriver, mydef - m_MethodName: OnMovement - m_Mode: 0 - m_Arguments: - m_ObjectArgument: {fileID: 0} - m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine - m_IntArgument: 0 - m_FloatArgument: 0 - m_StringArgument: - m_BoolArgument: 0 - m_CallState: 2 - m_ActionId: 55dfdeea-331d-47f2-9a02-526e458aa5ed - m_ActionName: New action map/New action[/Keyboard/w,/Keyboard/s,/Keyboard/a,/Keyboard/d] - m_NeverAutoSwitchControlSchemes: 0 - m_DefaultControlScheme: - m_DefaultActionMap: New action map - m_SplitScreenIndex: -1 - m_Camera: {fileID: 0} ---- !u!1 &7544314590428355348 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 3106622367778460228} - - component: {fileID: 300268715198095524} - - component: {fileID: 8565678507340770901} - - component: {fileID: 6944568664394371648} - m_Layer: 0 - m_Name: Sphere - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &3106622367778460228 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7544314590428355348} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 4512293259955182957} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &300268715198095524 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7544314590428355348} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &8565678507340770901 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7544314590428355348} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 138cca86153614c4c8e24fc2768fba69, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!135 &6944568664394371648 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7544314590428355348} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} diff --git a/Assets/FishNet/Demos/Network LOD/Prefabs/NetworkLOD_Prefab.prefab.meta b/Assets/FishNet/Demos/Network LOD/Prefabs/NetworkLOD_Prefab.prefab.meta deleted file mode 100644 index de7ba26..0000000 --- a/Assets/FishNet/Demos/Network LOD/Prefabs/NetworkLOD_Prefab.prefab.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 300370bdf7819da41937e0beac65b32c -PrefabImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.cs b/Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.cs deleted file mode 100644 index 45db571..0000000 --- a/Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.cs +++ /dev/null @@ -1,196 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was auto-generated by com.unity.inputsystem:InputActionCodeGenerator -// version 1.4.4 -// from Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.inputactions -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine.InputSystem; -using UnityEngine.InputSystem.Utilities; - -public partial class @NewControls : IInputActionCollection2, IDisposable -{ - public InputActionAsset asset { get; } - public @NewControls() - { - asset = InputActionAsset.FromJson(@"{ - ""name"": ""New Controls"", - ""maps"": [ - { - ""name"": ""New action map"", - ""id"": ""d0f51457-a857-4fa4-98ce-e5cde69f5bba"", - ""actions"": [ - { - ""name"": ""New action"", - ""type"": ""Value"", - ""id"": ""55dfdeea-331d-47f2-9a02-526e458aa5ed"", - ""expectedControlType"": ""Vector2"", - ""processors"": """", - ""interactions"": ""Hold"", - ""initialStateCheck"": true - } - ], - ""bindings"": [ - { - ""name"": ""2D Vector"", - ""id"": ""ab43b81b-3869-467f-9684-e4f7a35d6c73"", - ""path"": ""2DVector"", - ""interactions"": """", - ""processors"": """", - ""groups"": """", - ""action"": ""New action"", - ""isComposite"": true, - ""isPartOfComposite"": false - }, - { - ""name"": ""up"", - ""id"": ""24cc63fc-7927-464b-acce-ad9f5d5de163"", - ""path"": ""/w"", - ""interactions"": """", - ""processors"": """", - ""groups"": """", - ""action"": ""New action"", - ""isComposite"": false, - ""isPartOfComposite"": true - }, - { - ""name"": ""down"", - ""id"": ""6fbbe716-aa97-412a-85c5-9597c0fea21c"", - ""path"": ""/s"", - ""interactions"": """", - ""processors"": """", - ""groups"": """", - ""action"": ""New action"", - ""isComposite"": false, - ""isPartOfComposite"": true - }, - { - ""name"": ""left"", - ""id"": ""3da6b6cd-13d7-4bd9-b943-010ef1aafb06"", - ""path"": ""/a"", - ""interactions"": """", - ""processors"": """", - ""groups"": """", - ""action"": ""New action"", - ""isComposite"": false, - ""isPartOfComposite"": true - }, - { - ""name"": ""right"", - ""id"": ""5dd39ce5-66ed-442e-af87-f9b09cb1b971"", - ""path"": ""/d"", - ""interactions"": """", - ""processors"": """", - ""groups"": """", - ""action"": ""New action"", - ""isComposite"": false, - ""isPartOfComposite"": true - } - ] - } - ], - ""controlSchemes"": [] -}"); - // New action map - m_Newactionmap = asset.FindActionMap("New action map", throwIfNotFound: true); - m_Newactionmap_Newaction = m_Newactionmap.FindAction("New action", throwIfNotFound: true); - } - - public void Dispose() - { - UnityEngine.Object.Destroy(asset); - } - - public InputBinding? bindingMask - { - get => asset.bindingMask; - set => asset.bindingMask = value; - } - - public ReadOnlyArray? devices - { - get => asset.devices; - set => asset.devices = value; - } - - public ReadOnlyArray controlSchemes => asset.controlSchemes; - - public bool Contains(InputAction action) - { - return asset.Contains(action); - } - - public IEnumerator GetEnumerator() - { - return asset.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - public void Enable() - { - asset.Enable(); - } - - public void Disable() - { - asset.Disable(); - } - public IEnumerable bindings => asset.bindings; - - public InputAction FindAction(string actionNameOrId, bool throwIfNotFound = false) - { - return asset.FindAction(actionNameOrId, throwIfNotFound); - } - public int FindBinding(InputBinding bindingMask, out InputAction action) - { - return asset.FindBinding(bindingMask, out action); - } - - // New action map - private readonly InputActionMap m_Newactionmap; - private INewactionmapActions m_NewactionmapActionsCallbackInterface; - private readonly InputAction m_Newactionmap_Newaction; - public struct NewactionmapActions - { - private @NewControls m_Wrapper; - public NewactionmapActions(@NewControls wrapper) { m_Wrapper = wrapper; } - public InputAction @Newaction => m_Wrapper.m_Newactionmap_Newaction; - public InputActionMap Get() { return m_Wrapper.m_Newactionmap; } - public void Enable() { Get().Enable(); } - public void Disable() { Get().Disable(); } - public bool enabled => Get().enabled; - public static implicit operator InputActionMap(NewactionmapActions set) { return set.Get(); } - public void SetCallbacks(INewactionmapActions instance) - { - if (m_Wrapper.m_NewactionmapActionsCallbackInterface != null) - { - @Newaction.started -= m_Wrapper.m_NewactionmapActionsCallbackInterface.OnNewaction; - @Newaction.performed -= m_Wrapper.m_NewactionmapActionsCallbackInterface.OnNewaction; - @Newaction.canceled -= m_Wrapper.m_NewactionmapActionsCallbackInterface.OnNewaction; - } - m_Wrapper.m_NewactionmapActionsCallbackInterface = instance; - if (instance != null) - { - @Newaction.started += instance.OnNewaction; - @Newaction.performed += instance.OnNewaction; - @Newaction.canceled += instance.OnNewaction; - } - } - } - public NewactionmapActions @Newactionmap => new NewactionmapActions(this); - public interface INewactionmapActions - { - void OnNewaction(InputAction.CallbackContext context); - } -} diff --git a/Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.cs.meta b/Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.cs.meta deleted file mode 100644 index 54ef850..0000000 --- a/Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d8c332b454deffe49b61a9c793d281f6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.inputactions b/Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.inputactions deleted file mode 100644 index 79c9cc5..0000000 --- a/Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.inputactions +++ /dev/null @@ -1,78 +0,0 @@ -{ - "name": "New Controls", - "maps": [ - { - "name": "New action map", - "id": "d0f51457-a857-4fa4-98ce-e5cde69f5bba", - "actions": [ - { - "name": "New action", - "type": "Value", - "id": "55dfdeea-331d-47f2-9a02-526e458aa5ed", - "expectedControlType": "Vector2", - "processors": "", - "interactions": "Hold", - "initialStateCheck": true - } - ], - "bindings": [ - { - "name": "2D Vector", - "id": "ab43b81b-3869-467f-9684-e4f7a35d6c73", - "path": "2DVector", - "interactions": "", - "processors": "", - "groups": "", - "action": "New action", - "isComposite": true, - "isPartOfComposite": false - }, - { - "name": "up", - "id": "24cc63fc-7927-464b-acce-ad9f5d5de163", - "path": "/w", - "interactions": "", - "processors": "", - "groups": "", - "action": "New action", - "isComposite": false, - "isPartOfComposite": true - }, - { - "name": "down", - "id": "6fbbe716-aa97-412a-85c5-9597c0fea21c", - "path": "/s", - "interactions": "", - "processors": "", - "groups": "", - "action": "New action", - "isComposite": false, - "isPartOfComposite": true - }, - { - "name": "left", - "id": "3da6b6cd-13d7-4bd9-b943-010ef1aafb06", - "path": "/a", - "interactions": "", - "processors": "", - "groups": "", - "action": "New action", - "isComposite": false, - "isPartOfComposite": true - }, - { - "name": "right", - "id": "5dd39ce5-66ed-442e-af87-f9b09cb1b971", - "path": "/d", - "interactions": "", - "processors": "", - "groups": "", - "action": "New action", - "isComposite": false, - "isPartOfComposite": true - } - ] - } - ], - "controlSchemes": [] -} \ No newline at end of file diff --git a/Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.inputactions.meta b/Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.inputactions.meta deleted file mode 100644 index dfe4196..0000000 --- a/Assets/FishNet/Demos/Network LOD/Prefabs/New Controls.inputactions.meta +++ /dev/null @@ -1,14 +0,0 @@ -fileFormatVersion: 2 -guid: c206aa4192994a34a8f932eb995f13b9 -ScriptedImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 2 - userData: - assetBundleName: - assetBundleVariant: - script: {fileID: 11500000, guid: 8404be70184654265930450def6a9037, type: 3} - generateWrapperCode: 1 - wrapperCodePath: - wrapperClassName: - wrapperCodeNamespace: diff --git a/Assets/FishNet/Demos/Network LOD/Prefabs/PlayerInputDriver.cs b/Assets/FishNet/Demos/Network LOD/Prefabs/PlayerInputDriver.cs deleted file mode 100644 index 909154f..0000000 --- a/Assets/FishNet/Demos/Network LOD/Prefabs/PlayerInputDriver.cs +++ /dev/null @@ -1,73 +0,0 @@ -using FishNet.Managing; -using FishNet.Managing.Statistic; -using FishNet.Object; -using UnityEngine; -using UnityEngine.InputSystem; - -[RequireComponent(typeof(CharacterController))] -[RequireComponent(typeof(PlayerInput))] -public class PlayerInputDriver : NetworkBehaviour -{ - private CharacterController _characterController; - private Vector2 _moveInput; - private Vector3 _moveDirection; - private bool _jump; - [SerializeField] public float jumpSpeed = 6f; - [SerializeField] public float speed = 8f; - [SerializeField] public float gravity = -9.8f; - [SerializeField] private GameObject spawnable; - private void Start() - { - _characterController = GetComponent(typeof(CharacterController)) as CharacterController; - _jump = false; - - } - private void Update() - { - - if (!base.IsOwner) - return; - if (_characterController.isGrounded||true) - { - _moveDirection = new Vector3(_moveInput.x, 0.0f, _moveInput.y); - _moveDirection *= speed; - - if (_jump) - { - _moveDirection.y = jumpSpeed; - _jump = false; - } - } - if (Input.GetKeyDown(KeyCode.Return)) - { - GameObject obj = Instantiate(spawnable); - ServerManager.Spawn(obj); - - - } - _moveDirection.y += gravity * Time.deltaTime; - _characterController.Move(_moveDirection * Time.deltaTime); - } - #region UnityEventCallbacks - public void OnMovement(InputAction.CallbackContext context) - { - - if (!base.IsOwner) - return; - _moveInput = context.ReadValue(); - } - public void OnJump(InputAction.CallbackContext context) - { - if (!base.IsOwner) - return; - if (context.started || context.performed) - { - _jump = true; - } - else if (context.canceled) - { - _jump = false; - } - } - #endregion -} \ No newline at end of file diff --git a/Assets/FishNet/Demos/Network LOD/Prefabs/PlayerInputDriver.cs.meta b/Assets/FishNet/Demos/Network LOD/Prefabs/PlayerInputDriver.cs.meta deleted file mode 100644 index 5c00340..0000000 --- a/Assets/FishNet/Demos/Network LOD/Prefabs/PlayerInputDriver.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a31284a274f3c3c4993d760abda8520a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Demos/Network LOD/Prefabs/PowerCore.prefab b/Assets/FishNet/Demos/Network LOD/Prefabs/PowerCore.prefab deleted file mode 100644 index 276a263..0000000 --- a/Assets/FishNet/Demos/Network LOD/Prefabs/PowerCore.prefab +++ /dev/null @@ -1,977 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &233110739957670801 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 233110739957670814} - - component: {fileID: 233110739957670812} - - component: {fileID: 233110739957670815} - m_Layer: 6 - m_Name: Sphere - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &233110739957670814 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110739957670801} - m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} - m_LocalPosition: {x: -0, y: 0, z: 0} - m_LocalScale: {x: 124.4, y: 124.4, z: 124.4} - m_ConstrainProportionsScale: 1 - m_Children: [] - m_Father: {fileID: 233110740096973423} - m_RootOrder: 3 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &233110739957670812 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110739957670801} - m_Mesh: {fileID: 4711208715938537054, guid: f069e13a4a4a541428ec1849320da3d2, type: 3} ---- !u!23 &233110739957670815 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110739957670801} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 257 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 097826b1552b779408ce530fd64c6cef, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &233110739991566131 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 233110739991566128} - - component: {fileID: 233110739991566142} - - component: {fileID: 233110739991566129} - m_Layer: 6 - m_Name: Visual Effect - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &233110739991566128 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110739991566131} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 233110740096973423} - m_RootOrder: 4 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!2083052967 &233110739991566142 -VisualEffect: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110739991566131} - m_Enabled: 1 - m_Asset: {fileID: 8926484042661614526, guid: 8e3b3549d5d7b134c9328c54a846ef6f, type: 3} - m_InitialEventName: OnPlay - m_InitialEventNameOverriden: 0 - m_StartSeed: 0 - m_ResetSeedOnPlay: 1 - m_ResourceVersion: 1 - m_PropertySheet: - m_Float: - m_Array: [] - m_Vector2f: - m_Array: [] - m_Vector3f: - m_Array: [] - m_Vector4f: - m_Array: [] - m_Uint: - m_Array: [] - m_Int: - m_Array: [] - m_Matrix4x4f: - m_Array: [] - m_AnimationCurve: - m_Array: [] - m_Gradient: - m_Array: [] - m_NamedObject: - m_Array: [] - m_Bool: - m_Array: [] ---- !u!73398921 &233110739991566129 -VFXRenderer: - serializedVersion: 1 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110739991566131} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 0 - m_LightProbeUsage: 0 - m_ReflectionProbeUsage: 0 - m_RayTracingMode: 0 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 257 - m_RendererPriority: 0 - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!1 &233110740096973422 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 233110740096973423} - - component: {fileID: 233110740096973418} - - component: {fileID: 233110740096973421} - - component: {fileID: 233110740096973420} - - component: {fileID: 233110740096973412} - - component: {fileID: 233110740096973419} - m_Layer: 6 - m_Name: PowerCore - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &233110740096973423 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740096973422} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -1.235, y: -3.799, z: 5.619998} - m_LocalScale: {x: 0.1, y: 0.1, z: 0.1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 233110740704357890} - - {fileID: 233110741301703014} - - {fileID: 233110740150710729} - - {fileID: 233110739957670814} - - {fileID: 233110739991566128} - - {fileID: 233110741542994721} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!65 &233110740096973418 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740096973422} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 6, y: 2, z: 2} - m_Center: {x: 0, y: 0, z: 0} ---- !u!54 &233110740096973421 -Rigidbody: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740096973422} - serializedVersion: 2 - m_Mass: 1 - m_Drag: 0 - m_AngularDrag: 0.05 - m_UseGravity: 1 - m_IsKinematic: 0 - m_Interpolate: 0 - m_Constraints: 112 - m_CollisionDetection: 0 ---- !u!114 &233110740096973420 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740096973422} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 051ddd707f17e1040b0fbe15645f75b6, type: 3} - m_Name: - m_EditorClassIdentifier: - itemName: Power Core 1 - itemSize: 1 - interactionCanvas: {fileID: 233110740704357889} - canPickup: 1 ---- !u!114 &233110740096973412 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740096973422} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a2836e36774ca1c4bbbee976e17b649c, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 0 - _addedNetworkObject: {fileID: 233110740096973419} - _networkObjectCache: {fileID: 233110740096973419} - _componentConfiguration: 0 - _synchronizeParent: 0 - _packing: - Position: 1 - Rotation: 1 - Scale: 0 - _interpolation: 2 - _extrapolation: 2 - _enableTeleport: 0 - _teleportThreshold: 1 - _clientAuthoritative: 0 - _sendToOwner: 1 - _synchronizePosition: 1 - _positionSnapping: - X: 0 - Y: 0 - Z: 0 - _synchronizeRotation: 1 - _rotationSnapping: - X: 0 - Y: 0 - Z: 0 - _synchronizeScale: 1 - _scaleSnapping: - X: 0 - Y: 0 - Z: 0 ---- !u!114 &233110740096973419 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740096973422} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - k__BackingField: 0 - k__BackingField: 0 - k__BackingField: {fileID: 0} - _networkBehaviours: - - {fileID: 233110740096973412} - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 - NetworkObserver: {fileID: 0} - k__BackingField: 0 - k__BackingField: 0 - _scenePathHash: 2359702710 - k__BackingField: 0 - k__BackingField: 10374466001253852714 - _sceneNetworkObjects: - - {fileID: 233110740096973419} - - {fileID: 0} ---- !u!1 &233110740150710728 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 233110740150710729} - - component: {fileID: 233110740150710743} - - component: {fileID: 233110740150710742} - m_Layer: 6 - m_Name: Icosphere - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &233110740150710729 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740150710728} - m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} - m_LocalPosition: {x: -0, y: 0, z: 0} - m_LocalScale: {x: 100, y: 100, z: 100} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 233110740096973423} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &233110740150710743 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740150710728} - m_Mesh: {fileID: 289301614986012343, guid: f069e13a4a4a541428ec1849320da3d2, type: 3} ---- !u!23 &233110740150710742 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740150710728} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 257 - m_RendererPriority: 0 - m_Materials: - - {fileID: -876546973899608171, guid: f069e13a4a4a541428ec1849320da3d2, type: 3} - - {fileID: -6478536213147159724, guid: f069e13a4a4a541428ec1849320da3d2, type: 3} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &233110740357066692 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 233110740357066693} - - component: {fileID: 233110740357066691} - - component: {fileID: 233110740357066690} - m_Layer: 6 - m_Name: Interaction Text - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &233110740357066693 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740357066692} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 233110740704357890} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 1394, y: -1189} - m_SizeDelta: {x: 1000, y: 500} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!222 &233110740357066691 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740357066692} - m_CullTransparentMesh: 1 ---- !u!114 &233110740357066690 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740357066692} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_text: Collect Power Core - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: 54538dddc94c4d74ea7a8561e9c8c658, type: 2} - m_sharedMaterial: {fileID: 1503351390517901866, guid: 54538dddc94c4d74ea7a8561e9c8c658, type: 2} - m_fontSharedMaterials: [] - m_fontMaterial: {fileID: 0} - m_fontMaterials: [] - m_fontColor32: - serializedVersion: 2 - rgba: 4294967295 - m_fontColor: {r: 1, g: 1, b: 1, a: 1} - m_enableVertexGradient: 0 - m_colorMode: 3 - m_fontColorGradient: - topLeft: {r: 1, g: 1, b: 1, a: 1} - topRight: {r: 1, g: 1, b: 1, a: 1} - bottomLeft: {r: 1, g: 1, b: 1, a: 1} - bottomRight: {r: 1, g: 1, b: 1, a: 1} - m_fontColorGradientPreset: {fileID: 0} - m_spriteAsset: {fileID: 0} - m_tintAllSprites: 0 - m_StyleSheet: {fileID: 0} - m_TextStyleHashCode: -1183493901 - m_overrideHtmlColors: 0 - m_faceColor: - serializedVersion: 2 - rgba: 4294967295 - m_fontSize: 219 - m_fontSizeBase: 36 - m_fontWeight: 400 - m_enableAutoSizing: 1 - m_fontSizeMin: 18 - m_fontSizeMax: 1000 - m_fontStyle: 1 - m_HorizontalAlignment: 2 - m_VerticalAlignment: 512 - m_textAlignment: 65535 - m_characterSpacing: 0 - m_wordSpacing: 0 - m_lineSpacing: 0 - m_lineSpacingMax: 0 - m_paragraphSpacing: 0 - m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 - m_wordWrappingRatios: 0.4 - m_overflowMode: 0 - m_linkedTextComponent: {fileID: 0} - parentLinkedComponent: {fileID: 0} - m_enableKerning: 1 - m_enableExtraPadding: 0 - checkPaddingRequired: 0 - m_isRichText: 1 - m_parseCtrlCharacters: 1 - m_isOrthographic: 1 - m_isCullingEnabled: 0 - m_horizontalMapping: 0 - m_verticalMapping: 0 - m_uvLineOffset: 0 - m_geometrySortingOrder: 0 - m_IsTextObjectScaleStatic: 0 - m_VertexBufferAutoSizeReduction: 0 - m_useMaxVisibleDescender: 1 - m_pageToDisplay: 1 - m_margin: {x: -207.84943, y: -213.57129, z: -243.51343, w: -115.010254} - m_isUsingLegacyAnimationComponent: 0 - m_isVolumetricText: 0 - m_hasFontAssetChanged: 0 - m_baseMaterial: {fileID: 0} - m_maskOffset: {x: 0, y: 0, z: 0, w: 0} ---- !u!1 &233110740704357893 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 233110740704357890} - - component: {fileID: 233110740704357889} - - component: {fileID: 233110740704357888} - - component: {fileID: 233110740704357891} - m_Layer: 6 - m_Name: Canvas - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &233110740704357890 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740704357893} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 2.2000027} - m_LocalScale: {x: 0.010000001, y: 0.010000001, z: 0.010000001} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 233110740357066693} - m_Father: {fileID: 233110740096973423} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: -2.7, y: 15.610002} - m_SizeDelta: {x: 1920, y: 1080} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!223 &233110740704357889 -Canvas: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740704357893} - m_Enabled: 1 - serializedVersion: 3 - m_RenderMode: 2 - m_Camera: {fileID: 0} - m_PlaneDistance: 100 - m_PixelPerfect: 0 - m_ReceivesEvents: 1 - m_OverrideSorting: 0 - m_OverridePixelPerfect: 0 - m_SortingBucketNormalizedSize: 0 - m_AdditionalShaderChannelsFlag: 25 - m_SortingLayerID: 0 - m_SortingOrder: 0 - m_TargetDisplay: 0 ---- !u!114 &233110740704357888 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740704357893} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} - m_Name: - m_EditorClassIdentifier: - m_UiScaleMode: 0 - m_ReferencePixelsPerUnit: 100 - m_ScaleFactor: 1 - m_ReferenceResolution: {x: 800, y: 600} - m_ScreenMatchMode: 0 - m_MatchWidthOrHeight: 0 - m_PhysicalUnit: 3 - m_FallbackScreenDPI: 96 - m_DefaultSpriteDPI: 96 - m_DynamicPixelsPerUnit: 1 - m_PresetInfoIsWorld: 1 ---- !u!114 &233110740704357891 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110740704357893} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} - m_Name: - m_EditorClassIdentifier: - m_IgnoreReversedGraphics: 1 - m_BlockingObjects: 0 - m_BlockingMask: - serializedVersion: 2 - m_Bits: 4294967295 ---- !u!1 &233110741301703001 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 233110741301703014} - - component: {fileID: 233110741301703012} - - component: {fileID: 233110741301703015} - m_Layer: 6 - m_Name: Cube - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &233110741301703014 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110741301703001} - m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} - m_LocalPosition: {x: -0, y: 0, z: 0} - m_LocalScale: {x: 300, y: 100, z: 100} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 233110740096973423} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &233110741301703012 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110741301703001} - m_Mesh: {fileID: -5495902117074765545, guid: f069e13a4a4a541428ec1849320da3d2, type: 3} ---- !u!23 &233110741301703015 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110741301703001} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 257 - m_RendererPriority: 0 - m_Materials: - - {fileID: -876546973899608171, guid: f069e13a4a4a541428ec1849320da3d2, type: 3} - - {fileID: 4874126678125670354, guid: f069e13a4a4a541428ec1849320da3d2, type: 3} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &233110741542994720 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 233110741542994721} - - component: {fileID: 233110741542994735} - - component: {fileID: 233110741542994734} - m_Layer: 6 - m_Name: Point Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &233110741542994721 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110741542994720} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 233110740096973423} - m_RootOrder: 5 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!108 &233110741542994735 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110741542994720} - m_Enabled: 1 - serializedVersion: 10 - m_Type: 2 - m_Shape: 0 - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_Intensity: 23.873241 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 0 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 4 - m_LightShadowCasterMode: 2 - m_AreaSize: {x: 0.5, y: 0.5} - m_BounceIntensity: 1 - m_ColorTemperature: 20000 - m_UseColorTemperature: 1 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_UseViewFrustumForShadowCasterCull: 1 - m_ShadowRadius: 0 - m_ShadowAngle: 0 ---- !u!114 &233110741542994734 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 233110741542994720} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 7a68c43fe1f2a47cfa234b5eeaa98012, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Intensity: 300 - m_EnableSpotReflector: 1 - m_LuxAtDistance: 1 - m_InnerSpotPercent: 0 - m_SpotIESCutoffPercent: 100 - m_LightDimmer: 1 - m_VolumetricDimmer: 1 - m_LightUnit: 0 - m_FadeDistance: 10000 - m_VolumetricFadeDistance: 10000 - m_AffectDiffuse: 1 - m_AffectSpecular: 1 - m_NonLightmappedOnly: 0 - m_ShapeWidth: 0.5 - m_ShapeHeight: 0.5 - m_AspectRatio: 1 - m_ShapeRadius: 0.025 - m_SoftnessScale: 1 - m_UseCustomSpotLightShadowCone: 0 - m_CustomSpotLightShadowCone: 30 - m_MaxSmoothness: 0.99 - m_ApplyRangeAttenuation: 1 - m_DisplayAreaLightEmissiveMesh: 0 - m_AreaLightCookie: {fileID: 0} - m_IESPoint: {fileID: 0} - m_IESSpot: {fileID: 0} - m_IncludeForRayTracing: 1 - m_AreaLightShadowCone: 120 - m_UseScreenSpaceShadows: 0 - m_InteractsWithSky: 1 - m_AngularDiameter: 0.5 - m_FlareSize: 2 - m_FlareTint: {r: 1, g: 1, b: 1, a: 1} - m_FlareFalloff: 4 - m_SurfaceTexture: {fileID: 0} - m_SurfaceTint: {r: 1, g: 1, b: 1, a: 1} - m_Distance: 1.5e+11 - m_UseRayTracedShadows: 0 - m_NumRayTracingSamples: 4 - m_FilterTracedShadow: 1 - m_FilterSizeTraced: 16 - m_SunLightConeAngle: 0.5 - m_LightShadowRadius: 0.5 - m_SemiTransparentShadow: 0 - m_ColorShadow: 1 - m_DistanceBasedFiltering: 0 - m_EvsmExponent: 15 - m_EvsmLightLeakBias: 0 - m_EvsmVarianceBias: 0.00001 - m_EvsmBlurPasses: 0 - m_LightlayersMask: 1 - m_LinkShadowLayers: 1 - m_ShadowNearPlane: 0.1 - m_BlockerSampleCount: 24 - m_FilterSampleCount: 16 - m_MinFilterSize: 0.1 - m_KernelSize: 5 - m_LightAngle: 1 - m_MaxDepthBias: 0.001 - m_ShadowResolution: - m_Override: 512 - m_UseOverride: 1 - m_Level: 0 - m_ShadowDimmer: 1 - m_VolumetricShadowDimmer: 1 - m_ShadowFadeDistance: 10000 - m_UseContactShadow: - m_Override: 0 - m_UseOverride: 1 - m_Level: 0 - m_RayTracedContactShadow: 0 - m_ShadowTint: {r: 0, g: 0, b: 0, a: 1} - m_PenumbraTint: 0 - m_NormalBias: 0.75 - m_SlopeBias: 0.5 - m_ShadowUpdateMode: 0 - m_AlwaysDrawDynamicShadows: 0 - m_UpdateShadowOnLightMovement: 0 - m_CachedShadowTranslationThreshold: 0.01 - m_CachedShadowAngularThreshold: 0.5 - m_BarnDoorAngle: 90 - m_BarnDoorLength: 0.05 - m_preserveCachedShadow: 0 - m_OnDemandShadowRenderOnPlacement: 1 - m_ShadowCascadeRatios: - - 0.05 - - 0.2 - - 0.3 - m_ShadowCascadeBorders: - - 0.2 - - 0.2 - - 0.2 - - 0.2 - m_ShadowAlgorithm: 0 - m_ShadowVariant: 0 - m_ShadowPrecision: 0 - useOldInspector: 0 - useVolumetric: 1 - featuresFoldout: 1 - m_AreaLightEmissiveMeshShadowCastingMode: 0 - m_AreaLightEmissiveMeshMotionVectorGenerationMode: 0 - m_AreaLightEmissiveMeshLayer: -1 - m_Version: 11 - m_ObsoleteShadowResolutionTier: 1 - m_ObsoleteUseShadowQualitySettings: 0 - m_ObsoleteCustomShadowResolution: 512 - m_ObsoleteContactShadows: 0 - m_PointlightHDType: 0 - m_SpotLightShape: 0 - m_AreaLightShape: 0 diff --git a/Assets/FishNet/Demos/Network LOD/Prefabs/PowerCore.prefab.meta b/Assets/FishNet/Demos/Network LOD/Prefabs/PowerCore.prefab.meta deleted file mode 100644 index 3ee49cd..0000000 --- a/Assets/FishNet/Demos/Network LOD/Prefabs/PowerCore.prefab.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: e05b94df3e7783a48ac1ed2d12a71774 -PrefabImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Demos/Network LOD/Prefabs/mydef.asmdef b/Assets/FishNet/Demos/Network LOD/Prefabs/mydef.asmdef deleted file mode 100644 index a37792f..0000000 --- a/Assets/FishNet/Demos/Network LOD/Prefabs/mydef.asmdef +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "mydef", - "rootNamespace": "", - "references": [ - "GUID:75469ad4d38634e559750d17036d5f7c", - "GUID:7c88a4a7926ee5145ad2dfa06f454c67" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} \ No newline at end of file diff --git a/Assets/FishNet/Demos/Network LOD/Prefabs/mydef.asmdef.meta b/Assets/FishNet/Demos/Network LOD/Prefabs/mydef.asmdef.meta deleted file mode 100644 index c56daff..0000000 --- a/Assets/FishNet/Demos/Network LOD/Prefabs/mydef.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: df3b7b8b65e22ea4487176804c62c5f0 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Demos/Network LOD/Scenes.meta b/Assets/FishNet/Demos/Network LOD/Scenes.meta deleted file mode 100644 index 1cfe0c6..0000000 --- a/Assets/FishNet/Demos/Network LOD/Scenes.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 00e8cf37496d4954d876a194be050368 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Demos/Network LOD/Scenes/NetworkLOD_Demo.unity b/Assets/FishNet/Demos/Network LOD/Scenes/NetworkLOD_Demo.unity deleted file mode 100644 index d1bd189..0000000 --- a/Assets/FishNet/Demos/Network LOD/Scenes/NetworkLOD_Demo.unity +++ /dev/null @@ -1,1395 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 262.3369, g: 325.0498, b: 430.21924, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 12 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 256 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 1 - m_PVRDenoiserTypeDirect: 1 - m_PVRDenoiserTypeIndirect: 1 - m_PVRDenoiserTypeAO: 1 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 1 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_LightingSettings: {fileID: 0} ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - maxJobWorkers: 0 - preserveTilesOutsideBounds: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!114 &370472794 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886575219563} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 756c28cd3141c4140ae776188ee26729, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkTraffic: - _updateInteval: 1 - _updateClient: 0 - _updateServer: 1 ---- !u!114 &370472795 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886575219563} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 8bc8f0363ddc75946a958043c5e49a83, type: 3} - m_Name: - m_EditorClassIdentifier: - _color: {r: 0, g: 1, b: 0.8124151, a: 1} - _placement: 2 - _showOutgoing: 1 - _showIncoming: 0 ---- !u!114 &370472796 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886575219563} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 3fdaae44044276a49a52229c1597e33b, type: 3} - m_Name: - m_EditorClassIdentifier: - _updateOrder: 0 - _timingType: 0 - _allowTickDropping: 0 - _maximumFrameTicks: 2 - _tickRate: 30 - _pingInterval: 1 - _timingInterval: 2 - _physicsMode: 0 ---- !u!1 &442045874 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 442045875} - - component: {fileID: 442045876} - - component: {fileID: 442045877} - m_Layer: 0 - m_Name: --LOD Tester - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &442045875 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 442045874} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 1453871496} - m_Father: {fileID: 0} - m_RootOrder: 3 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &442045876 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 442045874} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - k__BackingField: 0 - k__BackingField: 0 - k__BackingField: {fileID: 0} - _networkBehaviours: - - {fileID: 442045877} - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 - NetworkObserver: {fileID: 0} - k__BackingField: 0 - k__BackingField: 0 - _scenePathHash: 2359702710 - k__BackingField: 10134845970961547977 - k__BackingField: 0 - _sceneNetworkObjects: - - {fileID: 442045876} ---- !u!114 &442045877 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 442045874} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 3e21cdbd259430f4ea77e1f3a6c88fc4, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 0 - _addedNetworkObject: {fileID: 442045876} - _networkObjectCache: {fileID: 442045876} - _prefab: {fileID: 4512293259955182956, guid: 300370bdf7819da41937e0beac65b32c, type: 3} - _observerManager: {fileID: 1776591436} - _lodLevel: 8 ---- !u!1 &584355000 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 584355002} - - component: {fileID: 584355001} - - component: {fileID: 584355003} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!108 &584355001 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 584355000} - m_Enabled: 1 - serializedVersion: 10 - m_Type: 1 - m_Shape: 0 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 100000 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 4 - m_LightShadowCasterMode: 2 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 1 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_UseViewFrustumForShadowCasterCull: 1 - m_ShadowRadius: 0 - m_ShadowAngle: 0 ---- !u!4 &584355002 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 584355000} - m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: 0, y: 3, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!114 &584355003 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 584355000} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 7a68c43fe1f2a47cfa234b5eeaa98012, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Intensity: 100000 - m_EnableSpotReflector: 1 - m_LuxAtDistance: 1 - m_InnerSpotPercent: 0 - m_SpotIESCutoffPercent: 100 - m_LightDimmer: 1 - m_VolumetricDimmer: 1 - m_LightUnit: 2 - m_FadeDistance: 10000 - m_VolumetricFadeDistance: 10000 - m_AffectDiffuse: 1 - m_AffectSpecular: 1 - m_NonLightmappedOnly: 0 - m_ShapeWidth: 0.5 - m_ShapeHeight: 0.5 - m_AspectRatio: 1 - m_ShapeRadius: 0.025 - m_SoftnessScale: 1 - m_UseCustomSpotLightShadowCone: 0 - m_CustomSpotLightShadowCone: 30 - m_MaxSmoothness: 0.99 - m_ApplyRangeAttenuation: 1 - m_DisplayAreaLightEmissiveMesh: 0 - m_AreaLightCookie: {fileID: 0} - m_IESPoint: {fileID: 0} - m_IESSpot: {fileID: 0} - m_IncludeForRayTracing: 1 - m_AreaLightShadowCone: 120 - m_UseScreenSpaceShadows: 0 - m_InteractsWithSky: 1 - m_AngularDiameter: 0.5 - m_FlareSize: 2 - m_FlareTint: {r: 1, g: 1, b: 1, a: 1} - m_FlareFalloff: 4 - m_SurfaceTexture: {fileID: 0} - m_SurfaceTint: {r: 1, g: 1, b: 1, a: 1} - m_Distance: 1.5e+11 - m_UseRayTracedShadows: 0 - m_NumRayTracingSamples: 4 - m_FilterTracedShadow: 1 - m_FilterSizeTraced: 16 - m_SunLightConeAngle: 0.5 - m_LightShadowRadius: 0.5 - m_SemiTransparentShadow: 0 - m_ColorShadow: 1 - m_DistanceBasedFiltering: 0 - m_EvsmExponent: 15 - m_EvsmLightLeakBias: 0 - m_EvsmVarianceBias: 0.00001 - m_EvsmBlurPasses: 0 - m_LightlayersMask: 1 - m_LinkShadowLayers: 1 - m_ShadowNearPlane: 0.1 - m_BlockerSampleCount: 24 - m_FilterSampleCount: 16 - m_MinFilterSize: 0.1 - m_KernelSize: 5 - m_LightAngle: 1 - m_MaxDepthBias: 0.001 - m_ShadowResolution: - m_Override: 512 - m_UseOverride: 1 - m_Level: 0 - m_ShadowDimmer: 1 - m_VolumetricShadowDimmer: 1 - m_ShadowFadeDistance: 10000 - m_UseContactShadow: - m_Override: 0 - m_UseOverride: 1 - m_Level: 0 - m_RayTracedContactShadow: 0 - m_ShadowTint: {r: 0, g: 0, b: 0, a: 1} - m_PenumbraTint: 0 - m_NormalBias: 0.75 - m_SlopeBias: 0.5 - m_ShadowUpdateMode: 0 - m_AlwaysDrawDynamicShadows: 0 - m_UpdateShadowOnLightMovement: 0 - m_CachedShadowTranslationThreshold: 0.01 - m_CachedShadowAngularThreshold: 0.5 - m_BarnDoorAngle: 90 - m_BarnDoorLength: 0.05 - m_preserveCachedShadow: 0 - m_OnDemandShadowRenderOnPlacement: 1 - m_ShadowCascadeRatios: - - 0.05 - - 0.2 - - 0.3 - m_ShadowCascadeBorders: - - 0.2 - - 0.2 - - 0.2 - - 0.2 - m_ShadowAlgorithm: 0 - m_ShadowVariant: 0 - m_ShadowPrecision: 0 - useOldInspector: 0 - useVolumetric: 1 - featuresFoldout: 1 - m_AreaLightEmissiveMeshShadowCastingMode: 0 - m_AreaLightEmissiveMeshMotionVectorGenerationMode: 0 - m_AreaLightEmissiveMeshLayer: -1 - m_Version: 11 - m_ObsoleteShadowResolutionTier: 1 - m_ObsoleteUseShadowQualitySettings: 0 - m_ObsoleteCustomShadowResolution: 512 - m_ObsoleteContactShadows: 0 - m_PointlightHDType: 0 - m_SpotLightShape: 0 - m_AreaLightShape: 0 ---- !u!1 &585532990 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 585532993} - - component: {fileID: 585532992} - - component: {fileID: 585532991} - - component: {fileID: 585532994} - m_Layer: 0 - m_Name: Main Camera - m_TagString: MainCamera - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!81 &585532991 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 585532990} - m_Enabled: 1 ---- !u!20 &585532992 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 585532990} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_FocalLength: 50 - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: -1 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 0 - m_AllowMSAA: 0 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!4 &585532993 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 585532990} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 1, z: -10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &585532994 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 585532990} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 23c1ce4fb46143f46bc5cb5224c934f6, type: 3} - m_Name: - m_EditorClassIdentifier: - clearColorMode: 0 - backgroundColorHDR: {r: 0.025, g: 0.07, b: 0.19, a: 0} - clearDepth: 1 - volumeLayerMask: - serializedVersion: 2 - m_Bits: 1 - volumeAnchorOverride: {fileID: 0} - antialiasing: 0 - SMAAQuality: 2 - dithering: 0 - stopNaNs: 0 - taaSharpenStrength: 0.5 - TAAQuality: 1 - taaHistorySharpening: 0.35 - taaAntiFlicker: 0.5 - taaMotionVectorRejection: 0 - taaAntiHistoryRinging: 0 - taaBaseBlendFactor: 0.875 - taaJitterScale: 1 - physicalParameters: - m_Iso: 200 - m_ShutterSpeed: 0.005 - m_Aperture: 16 - m_FocusDistance: 10 - m_BladeCount: 5 - m_Curvature: {x: 2, y: 11} - m_BarrelClipping: 0.25 - m_Anamorphism: 0 - flipYMode: 0 - xrRendering: 1 - fullscreenPassthrough: 0 - allowDynamicResolution: 0 - customRenderingSettings: 0 - invertFaceCulling: 0 - probeLayerMask: - serializedVersion: 2 - m_Bits: 4294967295 - hasPersistentHistory: 0 - allowDeepLearningSuperSampling: 1 - deepLearningSuperSamplingUseCustomQualitySettings: 0 - deepLearningSuperSamplingQuality: 0 - deepLearningSuperSamplingUseCustomAttributes: 0 - deepLearningSuperSamplingUseOptimalSettings: 1 - deepLearningSuperSamplingSharpening: 0 - exposureTarget: {fileID: 0} - materialMipBias: 0 - m_RenderingPathCustomFrameSettings: - bitDatas: - data1: 72198260625768269 - data2: 13763000477350330392 - lodBias: 1 - lodBiasMode: 0 - lodBiasQualityLevel: 0 - maximumLODLevel: 0 - maximumLODLevelMode: 0 - maximumLODLevelQualityLevel: 0 - sssQualityMode: 0 - sssQualityLevel: 0 - sssCustomSampleBudget: 20 - msaaMode: 1 - materialQuality: 0 - renderingPathCustomFrameSettingsOverrideMask: - mask: - data1: 0 - data2: 0 - defaultFrameSettings: 0 - m_Version: 8 - m_ObsoleteRenderingPath: 0 - m_ObsoleteFrameSettings: - overrides: 0 - enableShadow: 0 - enableContactShadows: 0 - enableShadowMask: 0 - enableSSR: 0 - enableSSAO: 0 - enableSubsurfaceScattering: 0 - enableTransmission: 0 - enableAtmosphericScattering: 0 - enableVolumetrics: 0 - enableReprojectionForVolumetrics: 0 - enableLightLayers: 0 - enableExposureControl: 1 - diffuseGlobalDimmer: 0 - specularGlobalDimmer: 0 - shaderLitMode: 0 - enableDepthPrepassWithDeferredRendering: 0 - enableTransparentPrepass: 0 - enableMotionVectors: 0 - enableObjectMotionVectors: 0 - enableDecals: 0 - enableRoughRefraction: 0 - enableTransparentPostpass: 0 - enableDistortion: 0 - enablePostprocess: 0 - enableOpaqueObjects: 0 - enableTransparentObjects: 0 - enableRealtimePlanarReflection: 0 - enableMSAA: 0 - enableAsyncCompute: 0 - runLightListAsync: 0 - runSSRAsync: 0 - runSSAOAsync: 0 - runContactShadowsAsync: 0 - runVolumeVoxelizationAsync: 0 - lightLoopSettings: - overrides: 0 - enableDeferredTileAndCluster: 0 - enableComputeLightEvaluation: 0 - enableComputeLightVariants: 0 - enableComputeMaterialVariants: 0 - enableFptlForForwardOpaque: 0 - enableBigTilePrepass: 0 - isFptlEnabled: 0 ---- !u!1 &1453871495 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1453871496} - m_Layer: 0 - m_Name: GameObject - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1453871496 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1453871495} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -20} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 442045875} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &1776591436 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886575219563} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 7d331f979d46e8e4a9fc90070c596d44, type: 3} - m_Name: - m_EditorClassIdentifier: - _useNetworkLod: 1 - _levelOfDetailDistances: - - 5 - - 10 - - 15 - - 30 - - 50 - - 70 - - 90 - - 100 - _updateHostVisibility: 1 - _defaultConditions: [] ---- !u!114 &1424052073952814568 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2480283714076101889} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2b3dca501a9d8c8479dc71dd068aa8b8, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!1 &2480283714076101889 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 9139860295505404435} - - component: {fileID: 6745855428728600859} - - component: {fileID: 1424052073952814568} - m_Layer: 5 - m_Name: Indicator - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &3965864432884103650 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4808982256728133663} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2b3dca501a9d8c8479dc71dd068aa8b8, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!114 &4393252310954709616 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252310954709618} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 3 - m_WrapAround: 0 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Selected - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 4393252310954709631} - m_OnClick: - m_PersistentCalls: - m_Calls: - - m_Target: {fileID: 4393252311495835464} - m_TargetAssemblyTypeName: - m_MethodName: OnClick_Client - m_Mode: 1 - m_Arguments: - m_ObjectArgument: {fileID: 0} - m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine - m_IntArgument: 0 - m_FloatArgument: 0 - m_StringArgument: - m_BoolArgument: 0 - m_CallState: 2 ---- !u!224 &4393252310954709617 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252310954709618} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 9139860295505404435} - m_Father: {fileID: 4393252311495835476} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 16, y: -96} - m_SizeDelta: {x: 256, y: 64} - m_Pivot: {x: 0, y: 1} ---- !u!1 &4393252310954709618 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4393252310954709617} - - component: {fileID: 4393252310954709630} - - component: {fileID: 4393252310954709631} - - component: {fileID: 4393252310954709616} - m_Layer: 5 - m_Name: Client - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!222 &4393252310954709630 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252310954709618} - m_CullTransparentMesh: 0 ---- !u!114 &4393252310954709631 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252310954709618} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2d50394614f8feb4eb0567fb7618d84d, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!114 &4393252311105513456 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311105513458} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 3 - m_WrapAround: 0 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Selected - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 4393252311105513471} - m_OnClick: - m_PersistentCalls: - m_Calls: - - m_Target: {fileID: 4393252311495835464} - m_TargetAssemblyTypeName: - m_MethodName: OnClick_Server - m_Mode: 1 - m_Arguments: - m_ObjectArgument: {fileID: 0} - m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine - m_IntArgument: 0 - m_FloatArgument: 0 - m_StringArgument: - m_BoolArgument: 0 - m_CallState: 2 ---- !u!224 &4393252311105513457 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311105513458} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 7233259200116312561} - m_Father: {fileID: 4393252311495835476} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 16, y: -16} - m_SizeDelta: {x: 256, y: 64} - m_Pivot: {x: 0, y: 1} ---- !u!1 &4393252311105513458 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4393252311105513457} - - component: {fileID: 4393252311105513470} - - component: {fileID: 4393252311105513471} - - component: {fileID: 4393252311105513456} - m_Layer: 5 - m_Name: Server - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!222 &4393252311105513470 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311105513458} - m_CullTransparentMesh: 0 ---- !u!114 &4393252311105513471 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311105513458} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 1b187e63031bf7849b249c8212440c3b, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!114 &4393252311495835464 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311495835465} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6d3606bfdac5a4743890fc1a5ecd8f24, type: 3} - m_Name: - m_EditorClassIdentifier: - _autoStartType: 1 - _stoppedColor: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - _changingColor: {r: 0.78431374, g: 0.6862745, b: 0, a: 1} - _startedColor: {r: 0, g: 0.5882353, b: 0.64705884, a: 1} - _serverIndicator: {fileID: 3965864432884103650} - _clientIndicator: {fileID: 1424052073952814568} ---- !u!1 &4393252311495835465 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4393252311495835476} - - component: {fileID: 4393252311495835464} - - component: {fileID: 4393252311495835477} - - component: {fileID: 4393252311495835478} - - component: {fileID: 4393252311495835479} - m_Layer: 5 - m_Name: NetworkHudCanvas - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &4393252311495835476 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311495835465} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0, y: 0, z: 0} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 4393252311105513457} - - {fileID: 4393252310954709617} - m_Father: {fileID: 7443408886575219561} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0, y: 0} ---- !u!223 &4393252311495835477 -Canvas: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311495835465} - m_Enabled: 1 - serializedVersion: 3 - m_RenderMode: 0 - m_Camera: {fileID: 0} - m_PlaneDistance: 100 - m_PixelPerfect: 0 - m_ReceivesEvents: 1 - m_OverrideSorting: 0 - m_OverridePixelPerfect: 0 - m_SortingBucketNormalizedSize: 0 - m_AdditionalShaderChannelsFlag: 0 - m_SortingLayerID: 0 - m_SortingOrder: 0 - m_TargetDisplay: 0 ---- !u!114 &4393252311495835478 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311495835465} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} - m_Name: - m_EditorClassIdentifier: - m_UiScaleMode: 1 - m_ReferencePixelsPerUnit: 100 - m_ScaleFactor: 1 - m_ReferenceResolution: {x: 1920, y: 1080} - m_ScreenMatchMode: 0 - m_MatchWidthOrHeight: 0.5 - m_PhysicalUnit: 3 - m_FallbackScreenDPI: 96 - m_DefaultSpriteDPI: 96 - m_DynamicPixelsPerUnit: 1 - m_PresetInfoIsWorld: 0 ---- !u!114 &4393252311495835479 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311495835465} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} - m_Name: - m_EditorClassIdentifier: - m_IgnoreReversedGraphics: 1 - m_BlockingObjects: 0 - m_BlockingMask: - serializedVersion: 2 - m_Bits: 4294967295 ---- !u!1 &4808982256728133663 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7233259200116312561} - - component: {fileID: 5104387649625413016} - - component: {fileID: 3965864432884103650} - m_Layer: 5 - m_Name: Indicator - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!222 &5104387649625413016 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4808982256728133663} - m_CullTransparentMesh: 0 ---- !u!222 &6745855428728600859 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2480283714076101889} - m_CullTransparentMesh: 0 ---- !u!224 &7233259200116312561 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4808982256728133663} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -1} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 4393252311105513457} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &7443408886575219556 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886575219563} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 211a9f6ec51ddc14f908f5acc0cd0423, type: 3} - m_Name: - m_EditorClassIdentifier: - _playerPrefab: {fileID: 4512293259955182956, guid: 300370bdf7819da41937e0beac65b32c, type: 3} - _addToDefaultScene: 1 - Spawns: [] ---- !u!4 &7443408886575219561 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886575219563} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 4393252311495835476} - m_Father: {fileID: 0} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &7443408886575219562 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886575219563} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d2c95dfde7d73b54dbbdc23155d35d36, type: 3} - m_Name: - m_EditorClassIdentifier: - _refreshDefaultPrefabs: 1 - _runInBackground: 1 - _dontDestroyOnLoad: 1 - _objectPool: {fileID: 0} - _persistence: 0 - _logging: {fileID: 0} - _spawnablePrefabs: {fileID: 11400000, guid: e6b71f999cc8fc647a3f73f7088802e0, type: 2} ---- !u!1 &7443408886575219563 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7443408886575219561} - - component: {fileID: 7443408886575219562} - - component: {fileID: 1776591436} - - component: {fileID: 7443408886575219556} - - component: {fileID: 370472794} - - component: {fileID: 370472795} - - component: {fileID: 370472796} - - component: {fileID: 7443408886575219565} - - component: {fileID: 7443408886575219564} - m_Layer: 0 - m_Name: NetworkManager - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &7443408886575219564 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886575219563} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9da90c29836670c49809661c5c09cd5d, type: 3} - m_Name: - m_EditorClassIdentifier: - _steamAppID: 480 - _serverBindAddress: 76561198308605766 - _port: 27015 - _maximumClients: 16 - _clientAddress: 76561198308605766 - _timeout: 25 ---- !u!114 &7443408886575219565 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886575219563} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 34e4a322dca349547989b14021da4e23, type: 3} - m_Name: - m_EditorClassIdentifier: - Transport: {fileID: 7443408886575219564} - _intermediateLayer: {fileID: 0} - _latencySimulator: - _enabled: 0 - _simulateHost: 1 - _latency: 0 - _outOfOrder: 0 - _packetLoss: 0 ---- !u!224 &9139860295505404435 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2480283714076101889} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -1} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 4393252310954709617} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0.5, y: 0.5} diff --git a/Assets/FishNet/Demos/Network LOD/Scenes/NetworkLOD_Demo.unity.meta b/Assets/FishNet/Demos/Network LOD/Scenes/NetworkLOD_Demo.unity.meta deleted file mode 100644 index d5f8856..0000000 --- a/Assets/FishNet/Demos/Network LOD/Scenes/NetworkLOD_Demo.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 961b96636e4c7644584dc8dfd0d0aad6 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Demos/Network LOD/Scripts.meta b/Assets/FishNet/Demos/Network LOD/Scripts.meta deleted file mode 100644 index 3be5703..0000000 --- a/Assets/FishNet/Demos/Network LOD/Scripts.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: d7351117344cad34c815771255551da8 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Demos/Network LOD/Scripts/MoveRandomly.cs b/Assets/FishNet/Demos/Network LOD/Scripts/MoveRandomly.cs deleted file mode 100644 index 7644b59..0000000 --- a/Assets/FishNet/Demos/Network LOD/Scripts/MoveRandomly.cs +++ /dev/null @@ -1,66 +0,0 @@ -using FishNet.Object; -using UnityEngine; - -namespace FishNet.Demo.NetworkLod -{ - - public class MoveRandomly : NetworkBehaviour - { - //Colors green for client. - [SerializeField] - private Renderer _renderer; - - //Time to move to new position. - private const float _moveRate = 3f; - //Maximum range for new position. - private const float _range = 10f; - //Position to move towards. - private Vector3 _goal; - //Position at spawn. - private Vector3 _start; - - private void Update() - { - //Client should not move these. - if (base.IsClientOnly) - { - - return; - } - - - //Server shouldn't move client one. - if (base.Owner.IsValid) - return; - if (base.IsOwner) - { - - } - else - { - - } - - ///transform.position = Vector3.MoveTowards(transform.position, _goal, _moveRate * Time.deltaTime); - //if (transform.position == _goal) - // RandomizeGoal(); - } - - public override void OnStartNetwork() - { - base.OnStartNetwork(); - _start = transform.position; - RandomizeGoal(); - - if (_renderer != null && base.Owner.IsActive) - _renderer.material.color = Color.green; - } - - private void RandomizeGoal() - { - _goal = _start + (Random.insideUnitSphere * _range); - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Demos/Network LOD/Scripts/MoveRandomly.cs.meta b/Assets/FishNet/Demos/Network LOD/Scripts/MoveRandomly.cs.meta deleted file mode 100644 index bd16c3d..0000000 --- a/Assets/FishNet/Demos/Network LOD/Scripts/MoveRandomly.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9880e85651efd71469092ce519317f7b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Demos/Network LOD/Scripts/NetworkLodTester.cs b/Assets/FishNet/Demos/Network LOD/Scripts/NetworkLodTester.cs deleted file mode 100644 index 26958a7..0000000 --- a/Assets/FishNet/Demos/Network LOD/Scripts/NetworkLodTester.cs +++ /dev/null @@ -1,51 +0,0 @@ -using FishNet.Managing.Observing; -using FishNet.Object; -using System.Collections.Generic; -using UnityEngine; - - -namespace FishNet.Demo.NetworkLod -{ - - public class NetworkLodTester : NetworkBehaviour - { - [SerializeField] - private NetworkObject _prefab; - [SerializeField] - private ObserverManager _observerManager; - [Range(1, 8)] - [SerializeField] - private byte _lodLevel = 8; - - private const int _count = 500; - private const float _xyRange = 15f; - private const float _zRange = 100f; - - private void Awake() - { - List distances = _observerManager.GetLevelOfDetailDistances(); - while (distances.Count > _lodLevel) - distances.RemoveAt(distances.Count - 1); - } - - public override void OnStartServer() - { - base.OnStartServer(); - - for (int i = 0; i < _count; i++) - { - float x = Random.Range(-_xyRange, _xyRange); - float y = Random.Range(-_xyRange, _xyRange); - float z = Random.Range(0f, _zRange); - - Vector3 position = new Vector3(x, y, z); - NetworkObject obj = Instantiate(_prefab, position, Quaternion.identity); - obj.name = $"Obj {i.ToString("0000")}"; - base.Spawn(obj); - } - - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Demos/Network LOD/Scripts/NetworkLodTester.cs.meta b/Assets/FishNet/Demos/Network LOD/Scripts/NetworkLodTester.cs.meta deleted file mode 100644 index b83bb07..0000000 --- a/Assets/FishNet/Demos/Network LOD/Scripts/NetworkLodTester.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3e21cdbd259430f4ea77e1f3a6c88fc4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example.meta b/Assets/FishNet/Example.meta deleted file mode 100644 index ad5b2cf..0000000 --- a/Assets/FishNet/Example.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 79bbd25806bd92d4c90cd527b542fd2f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All.meta b/Assets/FishNet/Example/All.meta deleted file mode 100644 index 1b57a73..0000000 --- a/Assets/FishNet/Example/All.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 3b7816b0f21ed6947b4bdfa22c415e42 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Authenticator.meta b/Assets/FishNet/Example/All/Authenticator.meta deleted file mode 100644 index 2152fd0..0000000 --- a/Assets/FishNet/Example/All/Authenticator.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: faf238f4c9ee3f24eaf0485ba10b8baa -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Authenticator/Authenticator.unity b/Assets/FishNet/Example/All/Authenticator/Authenticator.unity deleted file mode 100644 index 8ae9a47..0000000 --- a/Assets/FishNet/Example/All/Authenticator/Authenticator.unity +++ /dev/null @@ -1,360 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 262.3369, g: 325.0498, b: 430.21924, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 12 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 256 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 1 - m_PVRDenoiserTypeDirect: 1 - m_PVRDenoiserTypeIndirect: 1 - m_PVRDenoiserTypeAO: 1 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 1 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_LightingSettings: {fileID: 0} ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - maxJobWorkers: 0 - preserveTilesOutsideBounds: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &279669268 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 279669271} - - component: {fileID: 279669270} - - component: {fileID: 279669269} - m_Layer: 0 - m_Name: EventSystem - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &279669269 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 279669268} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} - m_Name: - m_EditorClassIdentifier: - m_SendPointerHoverToParent: 1 - m_HorizontalAxis: Horizontal - m_VerticalAxis: Vertical - m_SubmitButton: Submit - m_CancelButton: Cancel - m_InputActionsPerSecond: 10 - m_RepeatDelay: 0.5 - m_ForceModuleActive: 0 ---- !u!114 &279669270 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 279669268} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} - m_Name: - m_EditorClassIdentifier: - m_FirstSelected: {fileID: 0} - m_sendNavigationEvents: 1 - m_DragThreshold: 10 ---- !u!4 &279669271 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 279669268} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1001 &1689326519 -PrefabInstance: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Modification: - m_TransformParent: {fileID: 0} - m_Modifications: - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_Pivot.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_Pivot.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_RootOrder - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_AnchorMax.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_AnchorMax.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_AnchorMin.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_AnchorMin.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_SizeDelta.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_SizeDelta.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalPosition.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalRotation.w - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalRotation.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalRotation.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalRotation.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_AnchoredPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_AnchoredPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalEulerAnglesHint.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalEulerAnglesHint.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalEulerAnglesHint.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058994, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: _autoStartType - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058995, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_Name - value: NetworkHudCanvas - objectReference: {fileID: 0} - m_RemovedComponents: [] - m_SourcePrefab: {fileID: 100100000, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} ---- !u!114 &1759771918 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886491481971} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 226e4eaf2fa685f48bdc3dfaa87c1453, type: 3} - m_Name: - m_EditorClassIdentifier: - _allowHostAuthentication: 0 - _password: HelloWorld ---- !u!4 &7443408886491481969 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886491481971} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &7443408886491481970 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886491481971} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d2c95dfde7d73b54dbbdc23155d35d36, type: 3} - m_Name: - m_EditorClassIdentifier: - _refreshDefaultPrefabs: 0 - _runInBackground: 1 - _dontDestroyOnLoad: 1 - _objectPool: {fileID: 0} - _persistence: 0 - _logging: {fileID: 0} - _spawnablePrefabs: {fileID: 11400000, guid: e6b71f999cc8fc647a3f73f7088802e0, type: 2} ---- !u!1 &7443408886491481971 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7443408886491481969} - - component: {fileID: 7443408886491481970} - - component: {fileID: 1759771918} - m_Layer: 0 - m_Name: NetworkManager - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 diff --git a/Assets/FishNet/Example/All/Authenticator/Authenticator.unity.meta b/Assets/FishNet/Example/All/Authenticator/Authenticator.unity.meta deleted file mode 100644 index 13af204..0000000 --- a/Assets/FishNet/Example/All/Authenticator/Authenticator.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 0bc02b628363de5499d5e7c00bd63b1b -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Authenticator/Scripts.meta b/Assets/FishNet/Example/All/Authenticator/Scripts.meta deleted file mode 100644 index fbd38e5..0000000 --- a/Assets/FishNet/Example/All/Authenticator/Scripts.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: a21030a9aa6adbe409485ca049602ba6 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Authenticator/Scripts/Broadcasts.cs b/Assets/FishNet/Example/All/Authenticator/Scripts/Broadcasts.cs deleted file mode 100644 index 9991b66..0000000 --- a/Assets/FishNet/Example/All/Authenticator/Scripts/Broadcasts.cs +++ /dev/null @@ -1,21 +0,0 @@ - -using FishNet.Broadcast; - -namespace FishNet.Example.Authenticating -{ - public struct HostPasswordBroadcast : IBroadcast - { - public string Password; - } - - public struct PasswordBroadcast : IBroadcast - { - public string Password; - } - - public struct ResponseBroadcast : IBroadcast - { - public bool Passed; - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Example/All/Authenticator/Scripts/Broadcasts.cs.meta b/Assets/FishNet/Example/All/Authenticator/Scripts/Broadcasts.cs.meta deleted file mode 100644 index c2d9e65..0000000 --- a/Assets/FishNet/Example/All/Authenticator/Scripts/Broadcasts.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d26bb0c99070e9b49bc8632dc0b68214 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Authenticator/Scripts/HostAuthenticator.cs b/Assets/FishNet/Example/All/Authenticator/Scripts/HostAuthenticator.cs deleted file mode 100644 index ea250f5..0000000 --- a/Assets/FishNet/Example/All/Authenticator/Scripts/HostAuthenticator.cs +++ /dev/null @@ -1,152 +0,0 @@ -using FishNet.Connection; -using FishNet.Example.Authenticating; -using FishNet.Managing; -using FishNet.Transporting; -using System; -using System.Security.Cryptography; -using System.Text; -using UnityEngine; - -namespace FishNet.Authenticating -{ - - /// - /// This authenticator is an example of how to let host bypass the authentication process. - /// When checking to authenticate on the client side call AuthenticateAsHost, and if returned true skip normal authentication. - /// - public abstract class HostAuthenticator : Authenticator - { - #region Serialized. - /// - /// True to enable use of AuthenticateAsHost. - /// - [Tooltip("True to enable use of AuthenticateAsHost.")] - [SerializeField] - private bool _allowHostAuthentication; - /// - /// Sets if to allow host authentication. - /// - /// - public void SetAllowHostAuthentication(bool value) => _allowHostAuthentication = value; - /// - /// Returns if AllowHostAuthentication is enabled. - /// - /// - public bool GetAllowHostAuthentication() => _allowHostAuthentication; - #endregion - - #region Private. - /// - /// A random hash which only exist if the server is started. - /// - private static string _hostHash = string.Empty; - #endregion - - /// - /// Initializes this script for use. - /// - /// - public override void InitializeOnce(NetworkManager networkManager) - { - base.InitializeOnce(networkManager); - //Listen for connection state of local server to set hash. - base.NetworkManager.ServerManager.OnServerConnectionState += ServerManager_OnServerConnectionState; - //Listen for broadcast from client. Be sure to set requireAuthentication to false. - base.NetworkManager.ServerManager.RegisterBroadcast(OnHostPasswordBroadcast, false); - } - - /// - /// Called after the local server connection state changes. - /// - private void ServerManager_OnServerConnectionState(ServerConnectionStateArgs obj) - { - int length = (obj.ConnectionState == LocalConnectionState.Started) ? 25 : 0; - SetHostHash(length); - } - - /// - /// Received on server when a client sends the password broadcast message. - /// - /// Connection sending broadcast. - /// - private void OnHostPasswordBroadcast(NetworkConnection conn, HostPasswordBroadcast hpb) - { - //Not accepting host authentications. This could be an attack. - if (!_allowHostAuthentication) - { - conn.Disconnect(true); - return; - } - /* If client is already authenticated this could be an attack. Connections - * are removed when a client disconnects so there is no reason they should - * already be considered authenticated. */ - if (conn.Authenticated) - { - conn.Disconnect(true); - return; - } - - bool correctPassword = (hpb.Password == _hostHash); - OnHostAuthenticationResult(conn, correctPassword); - } - - /// - /// Called after handling a host authentication result. - /// - /// Connection authenticating. - /// True if authentication passed. - protected abstract void OnHostAuthenticationResult(NetworkConnection conn, bool authenticated); - - /// - /// Sets a host hash of length. - /// - /// https://stackoverflow.com/questions/32932679/using-rngcryptoserviceprovider-to-generate-random-string - private void SetHostHash(int length) - { - if (length <= 0) - { - _hostHash = string.Empty; - } - else - { - const string charPool = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()"; - StringBuilder result = new StringBuilder(); - using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) - { - byte[] uintBuffer = new byte[sizeof(uint)]; - while (length-- > 0) - { - rng.GetBytes(uintBuffer); - uint num = BitConverter.ToUInt32(uintBuffer, 0); - result.Append(charPool[(int)(num % (uint)charPool.Length)]); - } - } - - _hostHash = result.ToString(); - } - } - - /// - /// Returns true if authentication was sent as host. - /// - /// - protected bool AuthenticateAsHost() - { - if (!_allowHostAuthentication) - return false; - if (_hostHash == string.Empty) - return false; - - HostPasswordBroadcast hpb = new HostPasswordBroadcast() - { - Password = _hostHash, - }; - - base.NetworkManager.ClientManager.Broadcast(hpb); - return true; - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Example/All/Authenticator/Scripts/HostAuthenticator.cs.meta b/Assets/FishNet/Example/All/Authenticator/Scripts/HostAuthenticator.cs.meta deleted file mode 100644 index d26ea1d..0000000 --- a/Assets/FishNet/Example/All/Authenticator/Scripts/HostAuthenticator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c7497d751bb68f444b4343e3edc28e39 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Authenticator/Scripts/PasswordAuthenticator.cs b/Assets/FishNet/Example/All/Authenticator/Scripts/PasswordAuthenticator.cs deleted file mode 100644 index 6bc7627..0000000 --- a/Assets/FishNet/Example/All/Authenticator/Scripts/PasswordAuthenticator.cs +++ /dev/null @@ -1,132 +0,0 @@ -using FishNet.Authenticating; -using FishNet.Connection; -using FishNet.Managing; -using FishNet.Managing.Logging; -using FishNet.Transporting; -using System; -using UnityEngine; - -namespace FishNet.Example.Authenticating -{ - /// - /// This is an example of a password authenticator. - /// Never send passwords without encryption. - /// - public class PasswordAuthenticator : HostAuthenticator - { - #region Public. - /// - /// Called when authenticator has concluded a result for a connection. Boolean is true if authentication passed, false if failed. - /// Server listens for this event automatically. - /// - public override event Action OnAuthenticationResult; - #endregion - - #region Serialized. - /// - /// Password to authenticate. - /// - [Tooltip("Password to authenticate.")] - [SerializeField] - private string _password = "HelloWorld"; - #endregion - - public override void InitializeOnce(NetworkManager networkManager) - { - base.InitializeOnce(networkManager); - - //Listen for connection state change as client. - base.NetworkManager.ClientManager.OnClientConnectionState += ClientManager_OnClientConnectionState; - //Listen for broadcast from client. Be sure to set requireAuthentication to false. - base.NetworkManager.ServerManager.RegisterBroadcast(OnPasswordBroadcast, false); - //Listen to response from server. - base.NetworkManager.ClientManager.RegisterBroadcast(OnResponseBroadcast); - } - - /// - /// Called when a connection state changes for the local client. - /// - private void ClientManager_OnClientConnectionState(ClientConnectionStateArgs args) - { - /* If anything but the started state then exit early. - * Only try to authenticate on started state. The server - * doesn't have to send an authentication request before client - * can authenticate, that is entirely optional and up to you. In this - * example the client tries to authenticate soon as they connect. */ - if (args.ConnectionState != LocalConnectionState.Started) - return; - //Authentication was sent as host, no need to authenticate normally. - if (AuthenticateAsHost()) - return; - - PasswordBroadcast pb = new PasswordBroadcast() - { - Password = _password - }; - - base.NetworkManager.ClientManager.Broadcast(pb); - } - - - /// - /// Received on server when a client sends the password broadcast message. - /// - /// Connection sending broadcast. - /// - private void OnPasswordBroadcast(NetworkConnection conn, PasswordBroadcast pb) - { - /* If client is already authenticated this could be an attack. Connections - * are removed when a client disconnects so there is no reason they should - * already be considered authenticated. */ - if (conn.Authenticated) - { - conn.Disconnect(true); - return; - } - - bool correctPassword = (pb.Password == _password); - SendAuthenticationResponse(conn, correctPassword); - /* Invoke result. This is handled internally to complete the connection or kick client. - * It's important to call this after sending the broadcast so that the broadcast - * makes it out to the client before the kick. */ - OnAuthenticationResult?.Invoke(conn, correctPassword); - } - - /// - /// Received on client after server sends an authentication response. - /// - /// - private void OnResponseBroadcast(ResponseBroadcast rb) - { - string result = (rb.Passed) ? "Authentication complete." : "Authenitcation failed."; - NetworkManager.Log(result); - } - - /// - /// Sends an authentication result to a connection. - /// - private void SendAuthenticationResponse(NetworkConnection conn, bool authenticated) - { - /* Tell client if they authenticated or not. This is - * entirely optional but does demonstrate that you can send - * broadcasts to client on pass or fail. */ - ResponseBroadcast rb = new ResponseBroadcast() - { - Passed = authenticated - }; - base.NetworkManager.ServerManager.Broadcast(conn, rb, false); - } - /// - /// Called after handling a host authentication result. - /// - /// Connection authenticating. - /// True if authentication passed. - protected override void OnHostAuthenticationResult(NetworkConnection conn, bool authenticated) - { - SendAuthenticationResponse(conn, authenticated); - OnAuthenticationResult?.Invoke(conn, authenticated); - } - } - - -} diff --git a/Assets/FishNet/Example/All/Authenticator/Scripts/PasswordAuthenticator.cs.meta b/Assets/FishNet/Example/All/Authenticator/Scripts/PasswordAuthenticator.cs.meta deleted file mode 100644 index 135ee06..0000000 --- a/Assets/FishNet/Example/All/Authenticator/Scripts/PasswordAuthenticator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 226e4eaf2fa685f48bdc3dfaa87c1453 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/CustomSyncType.meta b/Assets/FishNet/Example/All/CustomSyncType.meta deleted file mode 100644 index b828a51..0000000 --- a/Assets/FishNet/Example/All/CustomSyncType.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: f8bfe7bb849f1524fb53a1029c93cddc -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/CustomSyncType/Component State Sync.meta b/Assets/FishNet/Example/All/CustomSyncType/Component State Sync.meta deleted file mode 100644 index e8dbf47..0000000 --- a/Assets/FishNet/Example/All/CustomSyncType/Component State Sync.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: bca1763a5b81adc4f8a467bb085aa78a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/AMonoScript.cs b/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/AMonoScript.cs deleted file mode 100644 index 8a62bed..0000000 --- a/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/AMonoScript.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UnityEngine; - -namespace FishNet.Example.ComponentStateSync -{ - - - public class AMonoScript : MonoBehaviour - { - - private void Start() - { - //Start is here to show enabled toggle within inspector. - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/AMonoScript.cs.meta b/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/AMonoScript.cs.meta deleted file mode 100644 index 703535d..0000000 --- a/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/AMonoScript.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a5821b28e5b90ef44b4910a640482c15 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentStateSync.cs b/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentStateSync.cs deleted file mode 100644 index 9ef6626..0000000 --- a/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentStateSync.cs +++ /dev/null @@ -1,155 +0,0 @@ -using FishNet.Documenting; -using FishNet.Managing.Logging; -using FishNet.Object.Synchronizing; -using FishNet.Object.Synchronizing.Internal; -using FishNet.Serializing; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Example.ComponentStateSync -{ - - - /// - /// It's very important to exclude this from codegen. - /// However, whichever value you are synchronizing must not be excluded. This is why the value is outside the StructySync class. - /// - public class ComponentStateSync : SyncBase, ICustomSync where T : MonoBehaviour - { - #region Public. - /// - /// Gets or Sets the enabled state for Component. - /// - public bool Enabled - { - get => (Component == null) ? false : GetState(); - set => SetState(value); - } - /// - /// Component to state sync. - /// - public T Component { get; private set; } - /// - /// Delegate signature for when the component changes. - /// - public delegate void StateChanged(T component, bool prevState, bool nextState, bool asServer); - /// - /// Called when the component state changes. - /// - public event StateChanged OnChange; - #endregion - - /// - /// Initializes this StateSync with a component. - /// - /// - public void Initialize(T component) - { - Component = component; - } - - /// - /// Sets the enabled state for Component. - /// - /// - private void SetState(bool enabled) - { - if (base.NetworkManager == null) - return; - - if (Component == null) - NetworkManager.LogError($"State cannot be changed as Initialize has not been called with a valid component."); - - //If hasn't changed then ignore. - bool prev = GetState(); - if (enabled == prev) - return; - - //Set to new value and add operation. - Component.enabled = enabled; - AddOperation(Component, prev, enabled); - } - - /// - /// Gets the enabled state for Component. - /// - /// - private bool GetState() - { - return Component.enabled; - } - - /// - /// Adds an operation to synchronize. - /// - private void AddOperation(T component, bool prev, bool next) - { - if (!base.IsRegistered) - return; - - if (base.NetworkManager != null && !base.NetworkBehaviour.IsServer) - { - NetworkManager.LogWarning($"Cannot complete operation as server when server is not active."); - return; - } - - base.Dirty(); - - //Data can currently only be set from server, so this is always asServer. - bool asServer = true; - OnChange?.Invoke(component, prev, next, asServer); - } - /// - /// Writes all changed values. - /// - ///True to set the next time data may sync. - public override void WriteDelta(PooledWriter writer, bool resetSyncTick = true) - { - base.WriteDelta(writer, resetSyncTick); - writer.WriteBoolean(Component.enabled); - } - - /// - /// Writes all values. - /// - public override void WriteFull(PooledWriter writer) - { - /* Always write full for this custom sync type. - * It would be difficult to know if the - * state has changed given it's a boolean, and - * may or may not be true/false after pooling is added. */ - WriteDelta(writer, false); - } - - /// - /// Reads and sets the current values for server or client. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [APIExclude] - public override void Read(PooledReader reader, bool asServer) - { - bool nextValue = reader.ReadBoolean(); - if (base.NetworkManager == null) - return; - - bool prevValue = GetState(); - - /* When !asServer don't make changes if server is running. - * This is because changes would have already been made on - * the server side and doing so again would result in duplicates - * and potentially overwrite data not yet sent. */ - bool asClientAndHost = (!asServer && base.NetworkManager.IsServer); - if (!asClientAndHost) - Component.enabled = nextValue; - - OnChange?.Invoke(Component, prevValue, nextValue, asServer); - } - - /// - /// Return the serialized type. - /// - /// - public object GetSerializedType() => typeof(bool); - } -} diff --git a/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentStateSync.cs.meta b/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentStateSync.cs.meta deleted file mode 100644 index 7ba490b..0000000 --- a/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentStateSync.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ce7cdae4a8f3d914fa9141b4bd760faa -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentSyncStateBehaviour.cs b/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentSyncStateBehaviour.cs deleted file mode 100644 index f9adbce..0000000 --- a/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentSyncStateBehaviour.cs +++ /dev/null @@ -1,43 +0,0 @@ -using FishNet.Object; -using FishNet.Object.Synchronizing; -using UnityEngine; - -namespace FishNet.Example.ComponentStateSync -{ - - public class ComponentSyncStateBehaviour : NetworkBehaviour - { - /// - /// Using my custom SyncType for Structy. - /// - [SyncObject] - private readonly ComponentStateSync _syncScript = new ComponentStateSync(); - - private void Awake() - { - AMonoScript ams = GetComponent(); - //Initialize with the component of your choice. - _syncScript.Initialize(ams); - //Optionally listen for changes. - _syncScript.OnChange += _syncScript_OnChange; - } - - /// - /// Called when enabled state changes for SyncScript. - /// - private void _syncScript_OnChange(AMonoScript component, bool prevState, bool nextState, bool asServer) - { - Debug.Log($"Change received on {component.GetType().Name}. New value is {nextState}. Received asServer {asServer}."); - } - - private void Update() - { - //Every so often flip the state of the component. - if (base.IsServer && Time.frameCount % 200 == 0) - _syncScript.Enabled = !_syncScript.Enabled; - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentSyncStateBehaviour.cs.meta b/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentSyncStateBehaviour.cs.meta deleted file mode 100644 index eba67fc..0000000 --- a/Assets/FishNet/Example/All/CustomSyncType/Component State Sync/ComponentSyncStateBehaviour.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a7327b94eff9c7d4aa876aa54ca6b439 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync.meta b/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync.meta deleted file mode 100644 index 5cc762d..0000000 --- a/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 449825c1f60f1e443b081834b84df95d -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructSyncBehaviour.cs b/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructSyncBehaviour.cs deleted file mode 100644 index 1746ad2..0000000 --- a/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructSyncBehaviour.cs +++ /dev/null @@ -1,41 +0,0 @@ -using FishNet.Object; -using FishNet.Object.Synchronizing; -using UnityEngine; - -namespace FishNet.Example.CustomSyncObject -{ - - public class StructSyncBehaviour : NetworkBehaviour - { - /// - /// Using my custom SyncType for Structy. - /// - [SyncObject] - private readonly StructySync _structy = new StructySync(); - - private void Awake() - { - //Listen for change events. - _structy.OnChange += _structy_OnChange; - } - - private void _structy_OnChange(StructySync.CustomOperation op, Structy oldItem, Structy newItem, bool asServer) - { - Debug.Log("Changed " + op.ToString() + ", " + newItem.Age + ", " + asServer); - } - - private void Update() - { - //Every so often increase the age property on structy using StructySync, my custom sync type. - if (base.IsServer && Time.frameCount % 200 == 0) - { - //Increase the age and set that values have changed. - _structy.Value.Age += 1; - _structy.ValuesChanged(); - } - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructSyncBehaviour.cs.meta b/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructSyncBehaviour.cs.meta deleted file mode 100644 index fc5e85e..0000000 --- a/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructSyncBehaviour.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c2cc7cbbeb4170642ac60367303222ef -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructySync.cs b/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructySync.cs deleted file mode 100644 index 2787bb1..0000000 --- a/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructySync.cs +++ /dev/null @@ -1,256 +0,0 @@ -using FishNet.Documenting; -using FishNet.Object.Synchronizing; -using FishNet.Object.Synchronizing.Internal; -using FishNet.Serializing; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace FishNet.Example.CustomSyncObject -{ - /// - /// This is the data type I want to create a custom SyncType for. - /// - public struct Structy - { - public string Name; - public ushort Age; - - public Structy(string name, ushort age) - { - Name = name; - Age = age; - } - } - - /// - /// It's very important to exclude this from codegen. - /// However, whichever value you are synchronizing must not be excluded. This is why the value is outside the StructySync class. - /// - public class StructySync : SyncBase, ICustomSync - { - #region Types. - /// - /// Information about how the struct has changed. - /// You could send the entire struct on every change - /// but this is an example of how you might send individual changed - /// fields. - /// - private struct ChangeData - { - internal CustomOperation Operation; - internal Structy Data; - - public ChangeData(CustomOperation operation, Structy data) - { - Operation = operation; - Data = data; - } - } - /// - /// Types of changes. This is related to ChangedData - /// where you can specify what has changed. - /// - public enum CustomOperation : byte - { - Full = 0, - Name = 1, - Age = 2 - } - #endregion - - #region Public. - /// - /// Delegate signature for when Structy changes. - /// - /// - /// - /// - public delegate void CustomChanged(CustomOperation op, Structy oldItem, Structy newItem, bool asServer); - /// - /// Called when the Structy changes. - /// - public event CustomChanged OnChange; - /// - /// Current value of Structy. - /// - public Structy Value = new Structy(); - #endregion - - #region Private. - /// - /// Initial value when initialized. Used to reset this sync type. - /// - private Structy _initialValue; - /// - /// Changed data which will be sent next tick. - /// - private readonly List _changed = new List(); - /// - /// True if values have changed since initialization. - /// - private bool _valuesChanged; - /// - /// Last value after dirty call. - /// - private Structy _lastDirtied = new Structy(); - #endregion - - protected override void Registered() - { - base.Registered(); - _initialValue = Value; - } - - /// - /// Adds an operation and invokes locally. - /// - /// - /// - /// - /// - private void AddOperation(CustomOperation operation, Structy prev, Structy next) - { - if (!base.IsRegistered) - return; - - if (base.NetworkManager != null && !base.NetworkBehaviour.IsServer) - { - NetworkManager.LogWarning($"Cannot complete operation as server when server is not active."); - return; - } - - /* Set as changed even if cannot dirty. - * Dirty is only set when there are observers, - * but even if there are not observers - * values must be marked as changed so when - * there are observers, new values are sent. */ - _valuesChanged = true; - base.Dirty(); - - //Data can currently only be set from server, so this is always asServer. - bool asServer = true; - //Add to changed. - ChangeData cd = new ChangeData(operation, next); - _changed.Add(cd); - OnChange?.Invoke(operation, prev, next, asServer); - } - - /// - /// Writes all changed values. - /// - /// - ///True to set the next time data may sync. - public override void WriteDelta(PooledWriter writer, bool resetSyncTick = true) - { - base.WriteDelta(writer, resetSyncTick); - writer.WriteInt32(_changed.Count); - - for (int i = 0; i < _changed.Count; i++) - { - ChangeData change = _changed[i]; - writer.WriteByte((byte)change.Operation); - - //Clear does not need to write anymore data so it is not included in checks. - if (change.Operation == CustomOperation.Age) - { - writer.WriteUInt16(change.Data.Age); - } - else if (change.Operation == CustomOperation.Name) - { - writer.WriteString(change.Data.Name); - } - } - - _changed.Clear(); - } - - /// - /// Writes all values if not initial values. - /// - /// - public override void WriteFull(PooledWriter writer) - { - if (!_valuesChanged) - return; - - base.WriteHeader(writer, false); - //Write one change. - writer.WriteInt32(1); - //Write if changed is from the server, so always use the server _value. - writer.WriteByte((byte)CustomOperation.Full); - //Write value. - writer.Write(Value); - } - - /// - /// Reads and sets the current values for server or client. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [APIExclude] - public override void Read(PooledReader reader, bool asServer) - { - /* When !asServer don't make changes if server is running. - * This is because changes would have already been made on - * the server side and doing so again would result in duplicates - * and potentially overwrite data not yet sent. */ - bool asClientAndHost = (!asServer && base.NetworkManager.IsServer); - - int changes = reader.ReadInt32(); - for (int i = 0; i < changes; i++) - { - CustomOperation operation = (CustomOperation)reader.ReadByte(); - Structy prev = Value; - Structy next = prev; - - //Full. - if (operation == CustomOperation.Full) - next = reader.Read(); - //Name. - else if (operation == CustomOperation.Name) - next.Name = reader.ReadString(); - //Age - else if (operation == CustomOperation.Age) - next.Age = reader.ReadUInt16(); - - OnChange?.Invoke(operation, prev, next, asServer); - - if (!asClientAndHost) - Value = next; - } - - } - - /// - /// Checks Value for changes and sends them to clients. - /// - public void ValuesChanged() - { - Structy prev = _lastDirtied; - Structy current = Value; - - if (prev.Name != current.Name) - AddOperation(CustomOperation.Name, prev, current); - if (prev.Age != current.Age) - AddOperation(CustomOperation.Age, prev, current); - - _lastDirtied = Value; - } - - /// - /// Resets to initialized values. - /// - public override void Reset() - { - base.Reset(); - _changed.Clear(); - Value = _initialValue; - _valuesChanged = false; - } - - /// - /// Return the serialized type. - /// - /// - public object GetSerializedType() => typeof(Structy); - } -} diff --git a/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructySync.cs.meta b/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructySync.cs.meta deleted file mode 100644 index 68e9a15..0000000 --- a/Assets/FishNet/Example/All/CustomSyncType/Custom Struct Sync/StructySync.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4c0a84e32efc60f4aa471e3a42cf2e0b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction.meta b/Assets/FishNet/Example/All/Prediction.meta deleted file mode 100644 index 9306c8c..0000000 --- a/Assets/FishNet/Example/All/Prediction.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 311aaa607bcf0c142a09726e4f6038ad -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/CharacterController.meta b/Assets/FishNet/Example/All/Prediction/CharacterController.meta deleted file mode 100644 index ad3e5b6..0000000 --- a/Assets/FishNet/Example/All/Prediction/CharacterController.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 79558f739187b5848bff30f39a16aaa7 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/CharacterController/CharacterControllerPrediction.unity b/Assets/FishNet/Example/All/Prediction/CharacterController/CharacterControllerPrediction.unity deleted file mode 100644 index 413e4d3..0000000 --- a/Assets/FishNet/Example/All/Prediction/CharacterController/CharacterControllerPrediction.unity +++ /dev/null @@ -1,1276 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 256 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 1 - m_PVRDenoiserTypeDirect: 1 - m_PVRDenoiserTypeIndirect: 1 - m_PVRDenoiserTypeAO: 1 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 1 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_UseShadowmask: 1 ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!114 &192429404 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886491487334} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 3fdaae44044276a49a52229c1597e33b, type: 3} - m_Name: - m_EditorClassIdentifier: - _updateOrder: 0 - _timingType: 0 - _allowTickDropping: 0 - _maximumFrameTicks: 2 - _tickRate: 15 - _pingInterval: 1 - _timingInterval: 2 - _physicsMode: 1 ---- !u!1 &555580081 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 555580085} - - component: {fileID: 555580084} - - component: {fileID: 555580083} - - component: {fileID: 555580082} - m_Layer: 0 - m_Name: Sphere - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &555580082 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 555580081} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &555580083 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 555580081} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 49a3799e31595ea478b5dd6fa163fcbd, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &555580084 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 555580081} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &555580085 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 555580081} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -9.16, y: -3.4, z: 13.1} - m_LocalScale: {x: 15, y: 15, z: 15} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 4 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &872683029 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 872683031} - - component: {fileID: 872683030} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!108 &872683030 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 872683029} - m_Enabled: 1 - serializedVersion: 10 - m_Type: 1 - m_Shape: 0 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 4 - m_LightShadowCasterMode: 0 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 0 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_ShadowRadius: 0 - m_ShadowAngle: 0 ---- !u!4 &872683031 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 872683029} - m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: 0, y: 3, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 3 - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!1 &1112005912 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1112005916} - - component: {fileID: 1112005915} - - component: {fileID: 1112005914} - - component: {fileID: 1112005913} - m_Layer: 0 - m_Name: Cube - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!65 &1112005913 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1112005912} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1112005914 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1112005912} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 0bb31cf72dfcef449a1a4a5aab857f63, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1112005915 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1112005912} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &1112005916 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1112005912} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -2, z: 0} - m_LocalScale: {x: 100, y: 1, z: 100} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1470934487 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1470934491} - - component: {fileID: 1470934490} - - component: {fileID: 1470934489} - - component: {fileID: 1470934488} - m_Layer: 0 - m_Name: Cube (1) - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!65 &1470934488 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1470934487} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1470934489 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1470934487} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 49a3799e31595ea478b5dd6fa163fcbd, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1470934490 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1470934487} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &1470934491 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1470934487} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 12.11, y: -0.08, z: 0} - m_LocalScale: {x: 1, y: 5, z: 20} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1784594014 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1784594015} - m_Layer: 0 - m_Name: Level - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1784594015 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1784594014} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 1112005916} - - {fileID: 1470934491} - - {fileID: 1852016427} - - {fileID: 872683031} - - {fileID: 555580085} - m_Father: {fileID: 0} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1852016424 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1852016427} - - component: {fileID: 1852016426} - m_Layer: 0 - m_Name: Main Camera - m_TagString: MainCamera - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!20 &1852016426 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1852016424} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_FocalLength: 50 - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: -1 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!4 &1852016427 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1852016424} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 1, z: -10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &1424052073902602981 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2480283714093027852} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2b3dca501a9d8c8479dc71dd068aa8b8, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!1 &2480283714093027852 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 9139860295689780510} - - component: {fileID: 6745855428745291286} - - component: {fileID: 1424052073902602981} - m_Layer: 5 - m_Name: Indicator - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &3965864432699664111 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4808982256744730386} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2b3dca501a9d8c8479dc71dd068aa8b8, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!114 &4393252310837120370 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252310837120383} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2d50394614f8feb4eb0567fb7618d84d, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!222 &4393252310837120371 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252310837120383} - m_CullTransparentMesh: 0 ---- !u!224 &4393252310837120380 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252310837120383} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 9139860295689780510} - m_Father: {fileID: 4393252311378272345} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 16, y: -96} - m_SizeDelta: {x: 256, y: 64} - m_Pivot: {x: 0, y: 1} ---- !u!114 &4393252310837120381 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252310837120383} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 3 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Selected - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 4393252310837120370} - m_OnClick: - m_PersistentCalls: - m_Calls: - - m_Target: {fileID: 4393252311378272325} - m_MethodName: OnClick_Client - m_Mode: 1 - m_Arguments: - m_ObjectArgument: {fileID: 0} - m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine - m_IntArgument: 0 - m_FloatArgument: 0 - m_StringArgument: - m_BoolArgument: 0 - m_CallState: 2 ---- !u!1 &4393252310837120383 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4393252310837120380} - - component: {fileID: 4393252310837120371} - - component: {fileID: 4393252310837120370} - - component: {fileID: 4393252310837120381} - m_Layer: 5 - m_Name: Client - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &4393252311222810866 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311222810879} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 1b187e63031bf7849b249c8212440c3b, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!222 &4393252311222810867 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311222810879} - m_CullTransparentMesh: 0 ---- !u!224 &4393252311222810876 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311222810879} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 7233259200132978428} - m_Father: {fileID: 4393252311378272345} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 16, y: -16} - m_SizeDelta: {x: 256, y: 64} - m_Pivot: {x: 0, y: 1} ---- !u!114 &4393252311222810877 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311222810879} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 3 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Selected - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 4393252311222810866} - m_OnClick: - m_PersistentCalls: - m_Calls: - - m_Target: {fileID: 4393252311378272325} - m_MethodName: OnClick_Server - m_Mode: 1 - m_Arguments: - m_ObjectArgument: {fileID: 0} - m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine - m_IntArgument: 0 - m_FloatArgument: 0 - m_StringArgument: - m_BoolArgument: 0 - m_CallState: 2 ---- !u!1 &4393252311222810879 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4393252311222810876} - - component: {fileID: 4393252311222810867} - - component: {fileID: 4393252311222810866} - - component: {fileID: 4393252311222810877} - m_Layer: 5 - m_Name: Server - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &4393252311378272324 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4393252311378272345} - - component: {fileID: 4393252311378272325} - - component: {fileID: 4393252311378272344} - - component: {fileID: 4393252311378272347} - - component: {fileID: 4393252311378272346} - m_Layer: 5 - m_Name: NetworkHudCanvas - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &4393252311378272325 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311378272324} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6d3606bfdac5a4743890fc1a5ecd8f24, type: 3} - m_Name: - m_EditorClassIdentifier: - _autoStartType: 1 - _stoppedColor: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - _changingColor: {r: 0.78431374, g: 0.6862745, b: 0, a: 1} - _startedColor: {r: 0, g: 0.5882353, b: 0.64705884, a: 1} - _serverIndicator: {fileID: 3965864432699664111} - _clientIndicator: {fileID: 1424052073902602981} ---- !u!223 &4393252311378272344 -Canvas: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311378272324} - m_Enabled: 1 - serializedVersion: 3 - m_RenderMode: 0 - m_Camera: {fileID: 0} - m_PlaneDistance: 100 - m_PixelPerfect: 0 - m_ReceivesEvents: 1 - m_OverrideSorting: 0 - m_OverridePixelPerfect: 0 - m_SortingBucketNormalizedSize: 0 - m_AdditionalShaderChannelsFlag: 0 - m_SortingLayerID: 0 - m_SortingOrder: 0 - m_TargetDisplay: 0 ---- !u!224 &4393252311378272345 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311378272324} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0, y: 0, z: 0} - m_Children: - - {fileID: 4393252311222810876} - - {fileID: 4393252310837120380} - m_Father: {fileID: 7443408886491487332} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0, y: 0} ---- !u!114 &4393252311378272346 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311378272324} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} - m_Name: - m_EditorClassIdentifier: - m_IgnoreReversedGraphics: 1 - m_BlockingObjects: 0 - m_BlockingMask: - serializedVersion: 2 - m_Bits: 4294967295 ---- !u!114 &4393252311378272347 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311378272324} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} - m_Name: - m_EditorClassIdentifier: - m_UiScaleMode: 1 - m_ReferencePixelsPerUnit: 100 - m_ScaleFactor: 1 - m_ReferenceResolution: {x: 1920, y: 1080} - m_ScreenMatchMode: 0 - m_MatchWidthOrHeight: 0.5 - m_PhysicalUnit: 3 - m_FallbackScreenDPI: 96 - m_DefaultSpriteDPI: 96 - m_DynamicPixelsPerUnit: 1 ---- !u!1 &4808982256744730386 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7233259200132978428} - - component: {fileID: 5104387649508117141} - - component: {fileID: 3965864432699664111} - m_Layer: 5 - m_Name: Indicator - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!222 &5104387649508117141 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4808982256744730386} - m_CullTransparentMesh: 0 ---- !u!222 &6745855428745291286 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2480283714093027852} - m_CullTransparentMesh: 0 ---- !u!224 &7233259200132978428 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4808982256744730386} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -1} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 4393252311222810876} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!4 &7443408886491487332 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886491487334} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 4393252311378272345} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &7443408886491487334 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7443408886491487332} - - component: {fileID: 7443408886491487335} - - component: {fileID: 7443408886491487337} - - component: {fileID: 192429404} - - component: {fileID: 7443408886491487336} - - component: {fileID: 7443408886491487339} - - component: {fileID: 7443408886491487338} - m_Layer: 0 - m_Name: NetworkManager - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &7443408886491487335 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886491487334} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d2c95dfde7d73b54dbbdc23155d35d36, type: 3} - m_Name: - m_EditorClassIdentifier: - _logging: {fileID: 0} - _spawnablePrefabs: {fileID: 11400000, guid: 3a54436bdb916194f99da0d17231e617, type: 2} - _refreshDefaultPrefabs: 0 - _runInBackground: 1 - _dontDestroyOnLoad: 1 - _objectPool: {fileID: 0} - _persistence: 0 ---- !u!114 &7443408886491487336 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886491487334} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f9b6b565cd9533c4ebc18003f0fc18a2, type: 3} - m_Name: - m_EditorClassIdentifier: - _color: {r: 1, g: 1, b: 1, a: 1} - _placement: 1 - _hideTickRate: 1 ---- !u!114 &7443408886491487337 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886491487334} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 211a9f6ec51ddc14f908f5acc0cd0423, type: 3} - m_Name: - m_EditorClassIdentifier: - _playerPrefab: {fileID: 9117857247562382210, guid: b2991431a5f893e49937d01b6da44ff8, - type: 3} - _addToDefaultScene: 1 - Spawns: [] ---- !u!114 &7443408886491487338 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886491487334} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6f48f002b825cbd45a19bd96d90f9edb, type: 3} - m_Name: - m_EditorClassIdentifier: - _unreliableMTU: 1023 - _ipv4BindAddress: - _ipv6BindAddress: - _port: 7771 - _maximumClients: 9999 - _clientAddress: localhost - _timeout: 15 ---- !u!114 &7443408886491487339 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408886491487334} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 34e4a322dca349547989b14021da4e23, type: 3} - m_Name: - m_EditorClassIdentifier: - Transport: {fileID: 7443408886491487338} - _intermediateLayer: {fileID: 0} - _latencySimulator: - _enabled: 0 - _simulateHost: 1 - _latency: 0 - _outOfOrder: 0 - _packetLoss: 0 ---- !u!224 &9139860295689780510 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2480283714093027852} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -1} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 4393252310837120380} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0.5, y: 0.5} diff --git a/Assets/FishNet/Example/All/Prediction/CharacterController/CharacterControllerPrediction.unity.meta b/Assets/FishNet/Example/All/Prediction/CharacterController/CharacterControllerPrediction.unity.meta deleted file mode 100644 index 0530583..0000000 --- a/Assets/FishNet/Example/All/Prediction/CharacterController/CharacterControllerPrediction.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: ec1a6e85f57626a4cbacaf306766bdfd -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/CharacterController/Prefabs.meta b/Assets/FishNet/Example/All/Prediction/CharacterController/Prefabs.meta deleted file mode 100644 index 1be0a57..0000000 --- a/Assets/FishNet/Example/All/Prediction/CharacterController/Prefabs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 26b1206536a5ae44792afd5292ad29b7 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/CharacterController/Prefabs/CharacterControllerPrediction.prefab b/Assets/FishNet/Example/All/Prediction/CharacterController/Prefabs/CharacterControllerPrediction.prefab deleted file mode 100644 index 65e8301..0000000 --- a/Assets/FishNet/Example/All/Prediction/CharacterController/Prefabs/CharacterControllerPrediction.prefab +++ /dev/null @@ -1,272 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &50058147544064912 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 8274935638305073705} - - component: {fileID: 5937955550093657123} - - component: {fileID: 8512892203317417748} - m_Layer: 0 - m_Name: Capsule - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &8274935638305073705 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 50058147544064912} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 9117857247562382215} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &5937955550093657123 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 50058147544064912} - m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &8512892203317417748 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 50058147544064912} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!1 &9117857247562382221 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 9117857247562382215} - - component: {fileID: 9117857247562382208} - - component: {fileID: 9117857247562382210} - - component: {fileID: 9144896207351220584} - - component: {fileID: 9144896207351220583} - - component: {fileID: 4742920392281400910} - - component: {fileID: -947403508163804576} - m_Layer: 0 - m_Name: CharacterControllerPrediction - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &9117857247562382215 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 9117857247562382221} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 1, z: -10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 8274935638305073705} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!136 &9117857247562382208 -CapsuleCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 9117857247562382221} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - m_Radius: 0.5 - m_Height: 2 - m_Direction: 1 - m_Center: {x: 0, y: 0, z: 0} ---- !u!114 &9117857247562382210 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 9117857247562382221} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkObserver: {fileID: 0} - k__BackingField: 0 - k__BackingField: 0 - _scenePathHash: 0 - k__BackingField: 0 - k__BackingField: 14762131302109388384 - _sceneNetworkObjects: [] - k__BackingField: 0 - k__BackingField: 0 - k__BackingField: {fileID: 0} - _networkBehaviours: - - {fileID: 9144896207351220584} - - {fileID: 4742920392281400910} - - {fileID: -947403508163804576} - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 ---- !u!114 &9144896207351220584 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 9117857247562382221} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6bb7bd88fd11b5d4aa7fca3d42172ab8, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 0 - _addedNetworkObject: {fileID: 9117857247562382210} - _networkObjectCache: {fileID: 9117857247562382210} - _moveRate: 5 ---- !u!143 &9144896207351220583 -CharacterController: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 9117857247562382221} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Height: 2 - m_Radius: 0.5 - m_SlopeLimit: 45 - m_StepOffset: 0.3 - m_SkinWidth: 0.08 - m_MinMoveDistance: 0.001 - m_Center: {x: 0, y: 0, z: 0} ---- !u!114 &4742920392281400910 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 9117857247562382221} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 402926ef33e0a894d9fec352693988ac, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 1 - _addedNetworkObject: {fileID: 0} - _networkObjectCache: {fileID: 9117857247562382210} - _implementsPredictionMethods: 1 - _graphicalObject: {fileID: 8274935638305073705} - _enableTeleport: 0 - _teleportThreshold: 1 - _ownerSmoothPosition: 1 - _ownerSmoothRotation: 1 - _ownerInterpolation: 1 - _predictionType: 0 - _rigidbody: {fileID: 0} - _rigidbody2d: {fileID: 0} - _spectatorSmoothPosition: 1 - _spectatorSmoothRotation: 1 - _spectatorInterpolation: 4 - _overflowMultiplier: 0.1 - _maintainedVelocity: 0 - _resendType: 0 - _resendInterval: 30 - _networkTransform: {fileID: -947403508163804576} ---- !u!114 &-947403508163804576 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 9117857247562382221} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a2836e36774ca1c4bbbee976e17b649c, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 2 - _addedNetworkObject: {fileID: 9117857247562382210} - _networkObjectCache: {fileID: 9117857247562382210} - _synchronizeParent: 0 - _packing: - Position: 1 - Rotation: 1 - Scale: 0 - _interpolation: 2 - _extrapolation: 2 - _enableTeleport: 0 - _teleportThreshold: 1 - _clientAuthoritative: 1 - _sendToOwner: 1 - _synchronizePosition: 1 - _positionSnapping: - X: 0 - Y: 0 - Z: 0 - _synchronizeRotation: 1 - _rotationSnapping: - X: 0 - Y: 0 - Z: 0 - _synchronizeScale: 1 - _scaleSnapping: - X: 0 - Y: 0 - Z: 0 diff --git a/Assets/FishNet/Example/All/Prediction/CharacterController/Prefabs/CharacterControllerPrediction.prefab.meta b/Assets/FishNet/Example/All/Prediction/CharacterController/Prefabs/CharacterControllerPrediction.prefab.meta deleted file mode 100644 index 2ffd376..0000000 --- a/Assets/FishNet/Example/All/Prediction/CharacterController/Prefabs/CharacterControllerPrediction.prefab.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: b2991431a5f893e49937d01b6da44ff8 -PrefabImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/CharacterController/Scripts.meta b/Assets/FishNet/Example/All/Prediction/CharacterController/Scripts.meta deleted file mode 100644 index e18185d..0000000 --- a/Assets/FishNet/Example/All/Prediction/CharacterController/Scripts.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 17c942141382c1c45abd049b9f01c633 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/CharacterController/Scripts/CharacterControllerPrediction.cs b/Assets/FishNet/Example/All/Prediction/CharacterController/Scripts/CharacterControllerPrediction.cs deleted file mode 100644 index 9b4c797..0000000 --- a/Assets/FishNet/Example/All/Prediction/CharacterController/Scripts/CharacterControllerPrediction.cs +++ /dev/null @@ -1,127 +0,0 @@ -using FishNet; -using FishNet.Object; -using FishNet.Object.Prediction; -using FishNet.Transporting; -using UnityEngine; - -/* -* -* See TransformPrediction.cs for more detailed notes. -* -*/ - -namespace FishNet.Example.Prediction.CharacterControllers -{ - - public class CharacterControllerPrediction : NetworkBehaviour - { - #region Types. - public struct MoveData : IReplicateData - { - public float Horizontal; - public float Vertical; - - private uint _tick; - public void Dispose() { } - public uint GetTick() => _tick; - public void SetTick(uint value) => _tick = value; - } - public struct ReconcileData : IReconcileData - { - public Vector3 Position; - public Quaternion Rotation; - public ReconcileData(Vector3 position, Quaternion rotation) - { - Position = position; - Rotation = rotation; - _tick = 0; - } - - private uint _tick; - public void Dispose() { } - public uint GetTick() => _tick; - public void SetTick(uint value) => _tick = value; - } - #endregion - - #region Serialized. - [SerializeField] - private float _moveRate = 5f; - #endregion - - #region Private. - private CharacterController _characterController; - #endregion - - private void Awake() - { - InstanceFinder.TimeManager.OnTick += TimeManager_OnTick; - _characterController = GetComponent(); - } - - public override void OnStartClient() - { - base.OnStartClient(); - _characterController.enabled = (base.IsServer || base.IsOwner); - } - - private void OnDestroy() - { - if (InstanceFinder.TimeManager != null) - { - InstanceFinder.TimeManager.OnTick -= TimeManager_OnTick; - } - } - - private void TimeManager_OnTick() - { - if (base.IsOwner) - { - Reconciliation(default, false); - CheckInput(out MoveData md); - Move(md, false); - } - if (base.IsServer) - { - Move(default, true); - ReconcileData rd = new ReconcileData(transform.position, transform.rotation); - Reconciliation(rd, true); - } - } - - private void CheckInput(out MoveData md) - { - md = default; - - float horizontal = Input.GetAxisRaw("Horizontal"); - float vertical = Input.GetAxisRaw("Vertical"); - - if (horizontal == 0f && vertical == 0f) - return; - - md = new MoveData() - { - Horizontal = horizontal, - Vertical = vertical - }; - } - - [Replicate] - private void Move(MoveData md, bool asServer, Channel channel = Channel.Unreliable, bool replaying = false) - { - Vector3 move = new Vector3(md.Horizontal, 0f, md.Vertical).normalized + new Vector3(0f, Physics.gravity.y, 0f); - _characterController.Move(move * _moveRate * (float)base.TimeManager.TickDelta); - } - - [Reconcile] - private void Reconciliation(ReconcileData rd, bool asServer, Channel channel = Channel.Unreliable) - { - transform.position = rd.Position; - transform.rotation = rd.Rotation; - } - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Example/All/Prediction/CharacterController/Scripts/CharacterControllerPrediction.cs.meta b/Assets/FishNet/Example/All/Prediction/CharacterController/Scripts/CharacterControllerPrediction.cs.meta deleted file mode 100644 index 04a2558..0000000 --- a/Assets/FishNet/Example/All/Prediction/CharacterController/Scripts/CharacterControllerPrediction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6bb7bd88fd11b5d4aa7fca3d42172ab8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Materials.meta b/Assets/FishNet/Example/All/Prediction/Materials.meta deleted file mode 100644 index e174353..0000000 --- a/Assets/FishNet/Example/All/Prediction/Materials.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e3efb1eab37402045a64161aba21ed29 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Materials/BlueMat.mat b/Assets/FishNet/Example/All/Prediction/Materials/BlueMat.mat deleted file mode 100644 index df63253..0000000 --- a/Assets/FishNet/Example/All/Prediction/Materials/BlueMat.mat +++ /dev/null @@ -1,77 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: BlueMat - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MetallicGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 0 - - _GlossMapScale: 0 - - _Glossiness: 0.5 - - _GlossyReflections: 1 - - _Metallic: 0 - - _Mode: 0 - - _OcclusionStrength: 1 - - _Parallax: 0.02 - - _SmoothnessTextureChannel: 1 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 1 - m_Colors: - - _Color: {r: 0.15970986, g: 0.50941056, b: 0.9150943, a: 1} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/FishNet/Example/All/Prediction/Materials/BlueMat.mat.meta b/Assets/FishNet/Example/All/Prediction/Materials/BlueMat.mat.meta deleted file mode 100644 index fde4d4f..0000000 --- a/Assets/FishNet/Example/All/Prediction/Materials/BlueMat.mat.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: ea31fef5ca1bc7344a72c71a5f9a0cd2 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 2100000 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Materials/GroundMat.mat b/Assets/FishNet/Example/All/Prediction/Materials/GroundMat.mat deleted file mode 100644 index 8c769b6..0000000 --- a/Assets/FishNet/Example/All/Prediction/Materials/GroundMat.mat +++ /dev/null @@ -1,77 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: GroundMat - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MetallicGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 0 - - _GlossMapScale: 0 - - _Glossiness: 0.5 - - _GlossyReflections: 1 - - _Metallic: 0 - - _Mode: 0 - - _OcclusionStrength: 1 - - _Parallax: 0.02 - - _SmoothnessTextureChannel: 1 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 1 - m_Colors: - - _Color: {r: 0.3679245, g: 0.36271805, b: 0.36271805, a: 1} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/FishNet/Example/All/Prediction/Materials/GroundMat.mat.meta b/Assets/FishNet/Example/All/Prediction/Materials/GroundMat.mat.meta deleted file mode 100644 index 3a74ead..0000000 --- a/Assets/FishNet/Example/All/Prediction/Materials/GroundMat.mat.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 0bb31cf72dfcef449a1a4a5aab857f63 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 2100000 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Materials/PurpleMat.mat b/Assets/FishNet/Example/All/Prediction/Materials/PurpleMat.mat deleted file mode 100644 index e9f384c..0000000 --- a/Assets/FishNet/Example/All/Prediction/Materials/PurpleMat.mat +++ /dev/null @@ -1,77 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: PurpleMat - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MetallicGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 0 - - _GlossMapScale: 0 - - _Glossiness: 0.5 - - _GlossyReflections: 1 - - _Metallic: 0 - - _Mode: 0 - - _OcclusionStrength: 1 - - _Parallax: 0.02 - - _SmoothnessTextureChannel: 1 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 1 - m_Colors: - - _Color: {r: 0.3364354, g: 0.0990566, b: 0.3962264, a: 1} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/FishNet/Example/All/Prediction/Materials/PurpleMat.mat.meta b/Assets/FishNet/Example/All/Prediction/Materials/PurpleMat.mat.meta deleted file mode 100644 index 8c782d4..0000000 --- a/Assets/FishNet/Example/All/Prediction/Materials/PurpleMat.mat.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 49a3799e31595ea478b5dd6fa163fcbd -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 2100000 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Materials/YellowishMat.mat b/Assets/FishNet/Example/All/Prediction/Materials/YellowishMat.mat deleted file mode 100644 index 0f8028c..0000000 --- a/Assets/FishNet/Example/All/Prediction/Materials/YellowishMat.mat +++ /dev/null @@ -1,77 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: YellowishMat - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MetallicGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 0 - - _GlossMapScale: 0 - - _Glossiness: 0.5 - - _GlossyReflections: 1 - - _Metallic: 0 - - _Mode: 0 - - _OcclusionStrength: 1 - - _Parallax: 0.02 - - _SmoothnessTextureChannel: 1 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 1 - m_Colors: - - _Color: {r: 0.62352943, g: 0.5504006, b: 0.17254901, a: 1} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/FishNet/Example/All/Prediction/Materials/YellowishMat.mat.meta b/Assets/FishNet/Example/All/Prediction/Materials/YellowishMat.mat.meta deleted file mode 100644 index 9f32cc6..0000000 --- a/Assets/FishNet/Example/All/Prediction/Materials/YellowishMat.mat.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 6273444b68d517449aadb36abebaf561 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 2100000 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody.meta b/Assets/FishNet/Example/All/Prediction/Rigidbody.meta deleted file mode 100644 index 06da42f..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: d851e0508fe14f44dae11c460021a6c2 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/New Physic Material.physicMaterial b/Assets/FishNet/Example/All/Prediction/Rigidbody/New Physic Material.physicMaterial deleted file mode 100644 index 32e5794..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/New Physic Material.physicMaterial +++ /dev/null @@ -1,14 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!134 &13400000 -PhysicMaterial: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: New Physic Material - dynamicFriction: 0.1 - staticFriction: 0.1 - bounciness: 0.9 - frictionCombine: 1 - bounceCombine: 0 diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/New Physic Material.physicMaterial.meta b/Assets/FishNet/Example/All/Prediction/Rigidbody/New Physic Material.physicMaterial.meta deleted file mode 100644 index c98b07f..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/New Physic Material.physicMaterial.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 2315b89c915a21c40982b5867ff7d343 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 13400000 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs.meta b/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs.meta deleted file mode 100644 index c67282a..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 185d003306f80ff4cb148c3f06bf3318 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedBullet.prefab b/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedBullet.prefab deleted file mode 100644 index 582bdcd..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedBullet.prefab +++ /dev/null @@ -1,256 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &3624261834906416581 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 3624261834906416580} - - component: {fileID: 3624261834906416603} - - component: {fileID: 3624261834906416600} - - component: {fileID: 3624261834906416601} - - component: {fileID: 3624261834906416602} - - component: {fileID: -6246116784124330627} - - component: {fileID: 7850526870340082268} - m_Layer: 0 - m_Name: PredictedBullet - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &3624261834906416580 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261834906416581} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 15.312408, y: 6.390984, z: 25.2406} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 3624261835462115340} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!135 &3624261834906416603 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261834906416581} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!114 &3624261834906416600 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261834906416581} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 402926ef33e0a894d9fec352693988ac, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 0 - _addedNetworkObject: {fileID: 3624261834906416601} - _networkObjectCache: {fileID: 3624261834906416601} - _implementsPredictionMethods: 0 - _graphicalObject: {fileID: 3624261835462115340} - _enableTeleport: 0 - _teleportThreshold: 200 - _ownerSmoothPosition: 1 - _ownerSmoothRotation: 1 - _ownerInterpolation: 1 - _predictionType: 1 - _rigidbody: {fileID: 3624261834906416602} - _rigidbody2d: {fileID: 0} - _spectatorSmoothPosition: 1 - _spectatorSmoothRotation: 1 - _spectatorSmoothingType: 2 - _customSmoothingData: - InterpolationPercent: 1 - CollisionInterpolationPercent: 0.1 - InterpolationDecreaseStep: 1 - InterpolationIncreaseStep: 3 - _preconfiguredSmoothingDataPreview: - InterpolationPercent: 1.5 - CollisionInterpolationPercent: 0.2 - InterpolationDecreaseStep: 1 - InterpolationIncreaseStep: 5 - _maintainedVelocity: 0 - _resendType: 0 - _resendInterval: 30 - _networkTransform: {fileID: 0} ---- !u!114 &3624261834906416601 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261834906416581} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkObserver: {fileID: 0} - k__BackingField: 5 - k__BackingField: 0 - _scenePathHash: 2281302723 - k__BackingField: 0 - k__BackingField: 12629563467294206692 - _sceneNetworkObjects: - - {fileID: 3624261834906416601} - k__BackingField: 0 - k__BackingField: 0 - k__BackingField: {fileID: 7850526870340082268} - _networkBehaviours: - - {fileID: 3624261834906416600} - - {fileID: -6246116784124330627} - - {fileID: 7850526870340082268} - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 ---- !u!54 &3624261834906416602 -Rigidbody: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261834906416581} - serializedVersion: 2 - m_Mass: 1 - m_Drag: 0 - m_AngularDrag: 0.05 - m_UseGravity: 0 - m_IsKinematic: 0 - m_Interpolate: 0 - m_Constraints: 0 - m_CollisionDetection: 3 ---- !u!114 &-6246116784124330627 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261834906416581} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fc7792d9dc338aa4dbc8a2f0533cf6ec, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 1 - _addedNetworkObject: {fileID: 3624261834906416601} - _networkObjectCache: {fileID: 3624261834906416601} - _startingForce: {x: 0, y: 0, z: 0} ---- !u!114 &7850526870340082268 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261834906416581} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: e2b597e1828355a4d994a69cbb11ef85, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 2 - _addedNetworkObject: {fileID: 3624261834906416601} - _networkObjectCache: {fileID: 3624261834906416601} - _allowSpawning: 1 - _allowDespawning: 1 - _allowSyncTypes: 1 ---- !u!1 &3624261835462115341 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 3624261835462115340} - - component: {fileID: 3624261835462115330} - - component: {fileID: 3624261835462115331} - m_Layer: 0 - m_Name: Graphics - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &3624261835462115340 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261835462115341} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 3624261834906416580} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &3624261835462115330 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261835462115341} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &3624261835462115331 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261835462115341} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedBullet.prefab.meta b/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedBullet.prefab.meta deleted file mode 100644 index c63f512..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedBullet.prefab.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: e3f599c0ac723194a92f51c91ec73267 -PrefabImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedSphereSorta.prefab b/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedSphereSorta.prefab deleted file mode 100644 index 163cb9a..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedSphereSorta.prefab +++ /dev/null @@ -1,246 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &3624261834906416581 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 3624261834906416580} - - component: {fileID: 3624261834906416603} - - component: {fileID: 3624261834906416600} - - component: {fileID: 3624261834906416601} - - component: {fileID: 3624261834906416602} - - component: {fileID: -6246116784124330627} - - component: {fileID: 7850526870340082268} - m_Layer: 0 - m_Name: PredictedSphereSorta - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &3624261834906416580 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261834906416581} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 15.312408, y: 6.390984, z: 25.2406} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 3624261835462115340} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!135 &3624261834906416603 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261834906416581} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!114 &3624261834906416600 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261834906416581} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 402926ef33e0a894d9fec352693988ac, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 0 - _addedNetworkObject: {fileID: 3624261834906416601} - _networkObjectCache: {fileID: 3624261834906416601} - _implementsPredictionMethods: 0 - _graphicalObject: {fileID: 3624261835462115340} - _enableTeleport: 0 - _teleportThreshold: 200 - _ownerSmoothPosition: 1 - _ownerSmoothRotation: 1 - _ownerInterpolation: 1 - _predictionType: 1 - _rigidbody: {fileID: 3624261834906416602} - _rigidbody2d: {fileID: 0} - _spectatorSmoothPosition: 1 - _spectatorSmoothRotation: 1 - _spectatorInterpolation: 4 - _overflowMultiplier: 0.1 - _maintainedVelocity: 0 - _resendType: 0 - _resendInterval: 30 - _networkTransform: {fileID: 0} ---- !u!114 &3624261834906416601 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261834906416581} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkObserver: {fileID: 0} - k__BackingField: 34 - k__BackingField: 0 - _scenePathHash: 2281302723 - k__BackingField: 0 - k__BackingField: 12142845903367415924 - _sceneNetworkObjects: - - {fileID: 3624261834906416601} - k__BackingField: 0 - k__BackingField: 0 - k__BackingField: {fileID: 7850526870340082268} - _networkBehaviours: - - {fileID: 3624261834906416600} - - {fileID: -6246116784124330627} - - {fileID: 7850526870340082268} - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 ---- !u!54 &3624261834906416602 -Rigidbody: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261834906416581} - serializedVersion: 2 - m_Mass: 1 - m_Drag: 0 - m_AngularDrag: 0.05 - m_UseGravity: 0 - m_IsKinematic: 0 - m_Interpolate: 0 - m_Constraints: 0 - m_CollisionDetection: 0 ---- !u!114 &-6246116784124330627 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261834906416581} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fc7792d9dc338aa4dbc8a2f0533cf6ec, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 1 - _addedNetworkObject: {fileID: 3624261834906416601} - _networkObjectCache: {fileID: 3624261834906416601} - Force: 20 ---- !u!114 &7850526870340082268 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261834906416581} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: e2b597e1828355a4d994a69cbb11ef85, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 2 - _addedNetworkObject: {fileID: 3624261834906416601} - _networkObjectCache: {fileID: 3624261834906416601} - _allowSpawning: 1 - _allowDespawning: 1 ---- !u!1 &3624261835462115341 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 3624261835462115340} - - component: {fileID: 3624261835462115330} - - component: {fileID: 3624261835462115331} - m_Layer: 0 - m_Name: Graphics - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &3624261835462115340 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261835462115341} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 3624261834906416580} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &3624261835462115330 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261835462115341} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &3624261835462115331 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3624261835462115341} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedSphereSorta.prefab.meta b/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedSphereSorta.prefab.meta deleted file mode 100644 index b8038ee..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/PredictedSphereSorta.prefab.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 4e1673ccc2acac543871855a0e8bed71 -PrefabImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/RigidbodyPrediction.prefab b/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/RigidbodyPrediction.prefab deleted file mode 100644 index 782c8e4..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/RigidbodyPrediction.prefab +++ /dev/null @@ -1,478 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &303449597948771942 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 303449597948771941} - - component: {fileID: 303449597948771939} - - component: {fileID: 303449597948771940} - m_Layer: 0 - m_Name: Cube (1) - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &303449597948771941 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449597948771942} - m_LocalRotation: {x: 0, y: 0.7071068, z: 0, w: 0.7071068} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1.5, y: 0.25, z: 0.25} - m_Children: [] - m_Father: {fileID: 303449599178274091} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} ---- !u!33 &303449597948771939 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449597948771942} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &303449597948771940 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449597948771942} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!1 &303449598114786579 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 303449598114786577} - - component: {fileID: 303449598114786578} - - component: {fileID: 201277551} - - component: {fileID: 201277550} - - component: {fileID: 201277549} - - component: {fileID: 1565754455094126377} - m_Layer: 0 - m_Name: RigidbodyPrediction - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &303449598114786577 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449598114786579} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -4.80351, y: 0.18147132, z: 5.430528} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 303449599178274091} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!135 &303449598114786578 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449598114786579} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!114 &201277551 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449598114786579} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9e123f937d4b4f94c9cb6cc03944f786, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 0 - _addedNetworkObject: {fileID: 201277550} - _networkObjectCache: {fileID: 201277550} - _jumpForce: 15 - _moveRate: 15 - BulletPrefab: {fileID: 3624261834906416601, guid: 4e1673ccc2acac543871855a0e8bed71, - type: 3} ---- !u!114 &201277550 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449598114786579} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkObserver: {fileID: 0} - k__BackingField: 2 - k__BackingField: 0 - _scenePathHash: 0 - k__BackingField: 0 - k__BackingField: 7596993593060998472 - _sceneNetworkObjects: [] - k__BackingField: 0 - k__BackingField: 0 - k__BackingField: {fileID: 0} - _networkBehaviours: - - {fileID: 201277551} - - {fileID: 1565754455094126377} - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 ---- !u!54 &201277549 -Rigidbody: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449598114786579} - serializedVersion: 2 - m_Mass: 1 - m_Drag: 0 - m_AngularDrag: 0.05 - m_UseGravity: 1 - m_IsKinematic: 0 - m_Interpolate: 0 - m_Constraints: 0 - m_CollisionDetection: 1 ---- !u!114 &1565754455094126377 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449598114786579} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 402926ef33e0a894d9fec352693988ac, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 1 - _addedNetworkObject: {fileID: 0} - _networkObjectCache: {fileID: 201277550} - _implementsPredictionMethods: 1 - _graphicalObject: {fileID: 303449599178274091} - _enableTeleport: 0 - _teleportThreshold: 1 - _ownerSmoothPosition: 1 - _ownerSmoothRotation: 1 - _ownerInterpolation: 1 - _predictionType: 1 - _rigidbody: {fileID: 201277549} - _rigidbody2d: {fileID: 0} - _spectatorSmoothPosition: 1 - _spectatorSmoothRotation: 1 - _spectatorSmoothingType: 1 - _customSmoothingData: - InterpolationPercent: 1 - CollisionInterpolationPercent: 0.1 - InterpolationDecreaseStep: 1 - InterpolationIncreaseStep: 3 - _preconfiguredSmoothingDataPreview: - InterpolationPercent: 1 - CollisionInterpolationPercent: 0.1 - InterpolationDecreaseStep: 1 - InterpolationIncreaseStep: 3 - _maintainedVelocity: 0 - _resendType: 0 - _resendInterval: 30 - _networkTransform: {fileID: 0} ---- !u!1 &303449598207636365 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 303449598207636364} - - component: {fileID: 303449598207636362} - - component: {fileID: 303449598207636363} - m_Layer: 0 - m_Name: Cube (2) - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &303449598207636364 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449598207636365} - m_LocalRotation: {x: 0.5, y: 0.5, z: 0.5, w: 0.5} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1.5, y: 0.25, z: 0.25} - m_Children: [] - m_Father: {fileID: 303449599178274091} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 90, z: 90} ---- !u!33 &303449598207636362 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449598207636365} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &303449598207636363 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449598207636365} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!1 &303449598691742042 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 303449598691742041} - - component: {fileID: 303449598691742039} - - component: {fileID: 303449598691742040} - m_Layer: 0 - m_Name: Cube - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &303449598691742041 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449598691742042} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1.5, y: 0.25, z: 0.25} - m_Children: [] - m_Father: {fileID: 303449599178274091} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &303449598691742039 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449598691742042} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &303449598691742040 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449598691742042} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!1 &303449599178274092 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 303449599178274091} - - component: {fileID: 303449599178274088} - - component: {fileID: 303449599178274089} - m_Layer: 0 - m_Name: Sphere (1) - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &303449599178274091 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449599178274092} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 303449598691742041} - - {fileID: 303449597948771941} - - {fileID: 303449598207636364} - m_Father: {fileID: 303449598114786577} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &303449599178274088 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449599178274092} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &303449599178274089 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 303449599178274092} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/RigidbodyPrediction.prefab.meta b/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/RigidbodyPrediction.prefab.meta deleted file mode 100644 index 1df735c..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/Prefabs/RigidbodyPrediction.prefab.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: d904f93bc171bb144ba33c5155282f6f -PrefabImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/RigidbodyPrediction.unity b/Assets/FishNet/Example/All/Prediction/Rigidbody/RigidbodyPrediction.unity deleted file mode 100644 index 068f732..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/RigidbodyPrediction.unity +++ /dev/null @@ -1,1517 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 256 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 1 - m_PVRDenoiserTypeDirect: 1 - m_PVRDenoiserTypeIndirect: 1 - m_PVRDenoiserTypeAO: 1 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 1 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_UseShadowmask: 1 ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &192429403 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 7443408887813606051, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - m_PrefabInstance: {fileID: 1364334277} - m_PrefabAsset: {fileID: 0} ---- !u!114 &192429404 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 192429403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 3fdaae44044276a49a52229c1597e33b, type: 3} - m_Name: - m_EditorClassIdentifier: - _updateOrder: 0 - _timingType: 0 - _allowTickDropping: 0 - _maximumFrameTicks: 2 - _tickRate: 50 - _pingInterval: 1 - _timingInterval: 3 - _physicsMode: 1 ---- !u!114 &192429405 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 192429403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6f48f002b825cbd45a19bd96d90f9edb, type: 3} - m_Name: - m_EditorClassIdentifier: - _unreliableMTU: 1023 - _ipv4BindAddress: - _ipv6BindAddress: - _port: 7770 - _maximumClients: 5000 - _clientAddress: localhost - _timeout: 15 ---- !u!114 &192429406 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 192429403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: f9b6b565cd9533c4ebc18003f0fc18a2, type: 3} - m_Name: - m_EditorClassIdentifier: - _color: {r: 1, g: 1, b: 1, a: 1} - _placement: 1 - _hideTickRate: 1 ---- !u!114 &192429407 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 192429403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 34e4a322dca349547989b14021da4e23, type: 3} - m_Name: - m_EditorClassIdentifier: - Transport: {fileID: 192429405} - _intermediateLayer: {fileID: 0} - _latencySimulator: - _enabled: 0 - _simulateHost: 1 - _latency: 5 - _outOfOrder: 0 - _packetLoss: 0 ---- !u!114 &192429408 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 192429403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 68828c85278210948b9d50a8db3aab74, type: 3} - m_Name: - m_EditorClassIdentifier: - _authenticator: {fileID: 0} - _syncTypeRate: 0.1 - SpawnPacking: - Position: 0 - Rotation: 2 - Scale: 2 - _changeFrameRate: 1 - _frameRate: 100 - _shareIds: 1 - _startOnHeadless: 1 - _limitClientMTU: 1 ---- !u!114 &192429409 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 192429403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: e08bb003fce297d4086cf8cba5aa459a, type: 3} - m_Name: - m_EditorClassIdentifier: - _dropExcessiveReplicates: 1 - _maximumServerReplicates: 15 - _maximumConsumeCount: 4 - _redundancyCount: 3 - _allowPredictedSpawning: 1 - _reservedObjectIds: 15 ---- !u!114 &192429410 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 192429403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: aca43cf6f20e77c4f8fcc078fd85081f, type: 3} - m_Name: - m_EditorClassIdentifier: - _changeFrameRate: 1 - _frameRate: 100 ---- !u!1 &212039606 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 212039607} - - component: {fileID: 212039608} - m_Layer: 0 - m_Name: View - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &212039607 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 212039606} - m_LocalRotation: {x: 0.37959778, y: -0.5981522, z: 0.3830318, w: 0.5927952} - m_LocalPosition: {x: 10.585218, y: 24.346329, z: 20.032343} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 4 - m_LocalEulerAnglesHint: {x: 40, y: -90, z: 0} ---- !u!114 &212039608 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 212039606} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkObserver: {fileID: 0} - k__BackingField: 0 - k__BackingField: 0 - _scenePathHash: 2281302723 - k__BackingField: 9798120588264221620 - k__BackingField: 0 - _sceneNetworkObjects: - - {fileID: 212039608} - k__BackingField: 0 - k__BackingField: 0 - k__BackingField: {fileID: 0} - _networkBehaviours: [] - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 ---- !u!1 &555580081 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 555580085} - - component: {fileID: 555580084} - - component: {fileID: 555580083} - - component: {fileID: 555580082} - m_Layer: 0 - m_Name: Sphere - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &555580082 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 555580081} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &555580083 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 555580081} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 6273444b68d517449aadb36abebaf561, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &555580084 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 555580081} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &555580085 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 555580081} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -9.16, y: -3.4, z: 13.1} - m_LocalScale: {x: 15, y: 15, z: 15} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &587483120 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 587483126} - - component: {fileID: 587483125} - - component: {fileID: 587483124} - - component: {fileID: 587483123} - - component: {fileID: 587483122} - - component: {fileID: 587483121} - m_Layer: 0 - m_Name: OfflineCapsule - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!54 &587483121 -Rigidbody: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 587483120} - serializedVersion: 2 - m_Mass: 1 - m_Drag: 0 - m_AngularDrag: 0.05 - m_UseGravity: 1 - m_IsKinematic: 0 - m_Interpolate: 0 - m_Constraints: 0 - m_CollisionDetection: 0 ---- !u!114 &587483122 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 587483120} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: b749f90d4c9961c4991179db1130fa4d, type: 3} - m_Name: - m_EditorClassIdentifier: - _rigidbodyType: 0 - _getInChildren: 0 ---- !u!136 &587483123 -CapsuleCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 587483120} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - m_Radius: 0.5 - m_Height: 2 - m_Direction: 1 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &587483124 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 587483120} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &587483125 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 587483120} - m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &587483126 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 587483120} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 6.0329375, y: 0.01036527, z: 8.858636} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 3 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &872683029 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 872683031} - - component: {fileID: 872683030} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!108 &872683030 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 872683029} - m_Enabled: 1 - serializedVersion: 10 - m_Type: 1 - m_Shape: 0 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 4 - m_LightShadowCasterMode: 0 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 0 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_ShadowRadius: 0 - m_ShadowAngle: 0 ---- !u!4 &872683031 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 872683029} - m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: 0, y: 3, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 4 - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!1 &967467089 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 967467090} - - component: {fileID: 967467093} - - component: {fileID: 967467092} - - component: {fileID: 967467091} - m_Layer: 0 - m_Name: Wall - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &967467090 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 967467089} - m_LocalRotation: {x: 0, y: 0.82565534, z: 0, w: 0.56417483} - m_LocalPosition: {x: 8.24, y: -0.08, z: 15.86} - m_LocalScale: {x: 1, y: 5, z: 5} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 5 - m_LocalEulerAnglesHint: {x: 0, y: 111.31, z: 0} ---- !u!65 &967467091 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 967467089} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &967467092 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 967467089} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 6273444b68d517449aadb36abebaf561, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &967467093 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 967467089} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!1 &1112005912 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1112005916} - - component: {fileID: 1112005915} - - component: {fileID: 1112005914} - - component: {fileID: 1112005913} - m_Layer: 0 - m_Name: Cube - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!65 &1112005913 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1112005912} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1112005914 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1112005912} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 0bb31cf72dfcef449a1a4a5aab857f63, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1112005915 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1112005912} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &1112005916 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1112005912} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -2, z: 0} - m_LocalScale: {x: 100, y: 1, z: 100} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1256183191 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1256183192} - - component: {fileID: 1256183195} - - component: {fileID: 1256183194} - m_Layer: 0 - m_Name: Sphere - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1256183192 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1256183191} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 1560902884} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!23 &1256183194 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1256183191} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1256183195 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1256183191} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!1001 &1364334277 -PrefabInstance: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Modification: - m_TransformParent: {fileID: 0} - m_Modifications: - - target: {fileID: 4393252310584637056, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: AutoStart - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 4393252310584637056, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: _autoStartType - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_RootOrder - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalPosition.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalRotation.w - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalRotation.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalRotation.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalRotation.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalEulerAnglesHint.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalEulerAnglesHint.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalEulerAnglesHint.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606050, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: _spawnablePrefabs - value: - objectReference: {fileID: 11400000, guid: 3a54436bdb916194f99da0d17231e617, - type: 2} - - target: {fileID: 7443408887813606050, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: _refreshDefaultPrefabs - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606051, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_Name - value: NetworkManager - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606060, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: _playerPrefab - value: - objectReference: {fileID: 201277550, guid: d904f93bc171bb144ba33c5155282f6f, - type: 3} - m_RemovedComponents: [] - m_SourcePrefab: {fileID: 100100000, guid: 0b650fca685f2eb41a86538aa883e4c1, type: 3} ---- !u!1 &1377211188 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1377211192} - - component: {fileID: 1377211191} - - component: {fileID: 1377211190} - - component: {fileID: 1377211189} - m_Layer: 0 - m_Name: Sphere - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &1377211189 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1377211188} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 0 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1377211190 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1377211188} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1377211191 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1377211188} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &1377211192 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1377211188} - m_LocalRotation: {x: 0, y: 0, z: 0.9122505, w: -0.40963268} - m_LocalPosition: {x: 10.983304, y: -0.99999994, z: 5.430528} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 5 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1470934487 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1470934491} - - component: {fileID: 1470934490} - - component: {fileID: 1470934489} - - component: {fileID: 1470934488} - m_Layer: 0 - m_Name: Wall - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!65 &1470934488 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1470934487} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1470934489 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1470934487} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 6273444b68d517449aadb36abebaf561, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1470934490 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1470934487} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &1470934491 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1470934487} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 12.11, y: -0.08, z: 0} - m_LocalScale: {x: 1, y: 5, z: 20} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1560902877 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1560902884} - - component: {fileID: 1560902881} - - component: {fileID: 1560902878} - - component: {fileID: 1560902880} - - component: {fileID: 1560902879} - m_Layer: 0 - m_Name: OnlineSphere - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!54 &1560902878 -Rigidbody: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1560902877} - serializedVersion: 2 - m_Mass: 1 - m_Drag: 0 - m_AngularDrag: 0.05 - m_UseGravity: 1 - m_IsKinematic: 0 - m_Interpolate: 0 - m_Constraints: 0 - m_CollisionDetection: 1 ---- !u!114 &1560902879 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1560902877} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 402926ef33e0a894d9fec352693988ac, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 0 - _addedNetworkObject: {fileID: 1560902880} - _networkObjectCache: {fileID: 1560902880} - _implementsPredictionMethods: 1 - _graphicalObject: {fileID: 1256183192} - _enableTeleport: 0 - _teleportThreshold: 1 - _ownerSmoothPosition: 1 - _ownerSmoothRotation: 1 - _ownerInterpolation: 1 - _predictionType: 1 - _rigidbody: {fileID: 1560902878} - _rigidbody2d: {fileID: 0} - _spectatorSmoothPosition: 1 - _spectatorSmoothRotation: 1 - _spectatorSmoothingType: 1 - _maintainedVelocity: 0 - _resendType: 0 - _resendInterval: 30 - _networkTransform: {fileID: 0} ---- !u!114 &1560902880 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1560902877} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkObserver: {fileID: 0} - k__BackingField: 65535 - k__BackingField: 0 - _scenePathHash: 2281302723 - k__BackingField: 9798120589401593003 - k__BackingField: 0 - _sceneNetworkObjects: - - {fileID: 212039608} - k__BackingField: 0 - k__BackingField: 0 - k__BackingField: {fileID: 0} - _networkBehaviours: - - {fileID: 1560902879} - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 ---- !u!135 &1560902881 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1560902877} - m_Material: {fileID: 13400000, guid: 2315b89c915a21c40982b5867ff7d343, type: 2} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!4 &1560902884 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1560902877} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 1.1, y: 0, z: 5.430528} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 1256183192} - m_Father: {fileID: 0} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1784594014 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1784594015} - m_Layer: 0 - m_Name: Level - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1784594015 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1784594014} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 1112005916} - - {fileID: 1470934491} - - {fileID: 555580085} - - {fileID: 1852016427} - - {fileID: 872683031} - - {fileID: 967467090} - - {fileID: 1883869627} - m_Father: {fileID: 0} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1852016424 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1852016427} - - component: {fileID: 1852016426} - - component: {fileID: 1852016425} - m_Layer: 0 - m_Name: Main Camera - m_TagString: MainCamera - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!81 &1852016425 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1852016424} - m_Enabled: 1 ---- !u!20 &1852016426 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1852016424} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_FocalLength: 50 - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: -1 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!4 &1852016427 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1852016424} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 1, z: -10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 3 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1883869626 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1883869627} - - component: {fileID: 1883869630} - - component: {fileID: 1883869629} - - component: {fileID: 1883869628} - m_Layer: 0 - m_Name: Cube (3) - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1883869627 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1883869626} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -48.62, y: -0.08, z: 0} - m_LocalScale: {x: 1, y: 5, z: 20} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 6 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!65 &1883869628 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1883869626} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1883869629 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1883869626} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 6273444b68d517449aadb36abebaf561, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1883869630 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1883869626} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/RigidbodyPrediction.unity.meta b/Assets/FishNet/Example/All/Prediction/Rigidbody/RigidbodyPrediction.unity.meta deleted file mode 100644 index 2edff22..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/RigidbodyPrediction.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 005289ca292137448ba5edc0e1163f4a -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts.meta b/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts.meta deleted file mode 100644 index f4324aa..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 789e9c92c35f6aa4bb179f6ee73a3061 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/BulletTest.cs b/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/BulletTest.cs deleted file mode 100644 index 824ea81..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/BulletTest.cs +++ /dev/null @@ -1,59 +0,0 @@ -using FishNet; -using FishNet.Object; -using FishNet.Object.Synchronizing; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -public class BulletTest : NetworkBehaviour -{ - [SyncObject] - public readonly SyncList SyncListNumbers = new SyncList(); - - [SyncVar] - public Vector3 SyncVarScale = Vector3.one; - - public float Force; - - public void SendSpeed() - { - //Debug.Log("Local tick " + InstanceFinder.TimeManager.LocalTick); - Rigidbody rb = GetComponent(); - rb.AddForce((transform.forward * Force), ForceMode.Impulse); - } - - public override void OnStartNetwork() - { - base.OnStartNetwork(); - transform.localScale = SyncVarScale; - - Debug.Log("Reading numbers"); - foreach (var item in SyncListNumbers) - Debug.Log(item); - - } - - public override void OnStartServer() - { - base.OnStartServer(); - SendSpeed(); - StartCoroutine(__DelayDestroy(3f)); - } - - private void Update() - { - if (base.TimeManager == null) - return; - if (base.TimeManager.FrameTicked) - { -// Debug.Log(_scale); - //Rigidbody rb = GetComponent(); - //Debug.Log(rb.velocity.z); - } - } - private IEnumerator __DelayDestroy(float time) - { - yield return new WaitForSeconds(time); - base.Despawn(); - } -} diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/BulletTest.cs.meta b/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/BulletTest.cs.meta deleted file mode 100644 index 338a0b6..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/BulletTest.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fc7792d9dc338aa4dbc8a2f0533cf6ec -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/PredictedBullet.cs b/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/PredictedBullet.cs deleted file mode 100644 index 207da52..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/PredictedBullet.cs +++ /dev/null @@ -1,106 +0,0 @@ -using FishNet.Component.Prediction; -using FishNet.Object; -using FishNet.Object.Synchronizing; -using System.Collections; -using UnityEngine; - -public class PredictedBullet : NetworkBehaviour -{ - //SyncVar to set spawn force. This is set by predicted spawner and sent to the server. - [SyncVar(OnChange = nameof(_startingForce_OnChange))] - private Vector3 _startingForce; - //Tick to set rb to kinematic. - private uint _stopTick = uint.MaxValue; - - public void SetStartingForce(Vector3 value) - { - /* If the object is not yet initialized then - * this is being set prior to network spawning. - * Such a scenario occurs because the client which is - * predicted spawning sets the synctype value before network - * spawning to ensure the server receives the value. - * Just as when the server sets synctypes, if they are set - * before the object is spawned it's gauranteed clients will - * get the value in the spawn packet; same practice is used here. */ - if (!base.IsSpawned) - SetVelocity(value); - - _startingForce = value; - } - - //Simple delay destroy so object does not exist forever. - public override void OnStartServer() - { - base.OnStartServer(); - StartCoroutine(__DelayDestroy(3f)); - } - - public override void OnStartNetwork() - { - base.OnStartNetwork(); - uint timeToTicks = base.TimeManager.TimeToTicks(0.65f); - /* If server or predicted spawner then add the kinematic - * tick onto local. Predicted spawner and server should behave - * as though no time has elapsed since this spawned. */ - if (base.IsServer || base.Owner.IsLocalClient) - { - _stopTick = base.TimeManager.LocalTick + timeToTicks; - } - /* If not server or a client that did not predicted spawn this - * then calculate time passed and set kinematic tick to the same - * amount in the future while subtracting already passed ticks. */ - else - { - uint passed = (uint)Mathf.Max(1, base.TimeManager.Tick - base.TimeManager.LastPacketTick); - long stopTick = (base.TimeManager.Tick + timeToTicks - passed - 1); - if (stopTick > 0) - _stopTick = (uint)stopTick; - else - _stopTick = 0; - } - - base.TimeManager.OnTick += TimeManager_OnTick; - } - - public override void OnStopNetwork() - { - base.OnStopNetwork(); - base.TimeManager.OnTick -= TimeManager_OnTick; - } - private void TimeManager_OnTick() - { - if (base.TimeManager.LocalTick >= _stopTick) - { - Rigidbody rb = GetComponent(); - rb.isKinematic = true; - } - } - - /// - /// When starting force changes set that velocity to the rigidbody. - /// This is an example as how a predicted spawn can modify sync types for server and other clients. - /// - private void _startingForce_OnChange(Vector3 prev, Vector3 next, bool asServer) - { - SetVelocity(next); - } - - /// - /// Sets velocity of the rigidbody. - /// - public void SetVelocity(Vector3 value) - { - Rigidbody rb = GetComponent(); - rb.velocity = value; - } - - /// - /// Destroy object after time. - /// - private IEnumerator __DelayDestroy(float time) - { - yield return new WaitForSeconds(time); - base.Despawn(); - } - -} diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/PredictedBullet.cs.meta b/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/PredictedBullet.cs.meta deleted file mode 100644 index bd4077f..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/PredictedBullet.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2878f245b0c06ce49b3e98d5984e8d41 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/RigidbodyPrediction.cs b/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/RigidbodyPrediction.cs deleted file mode 100644 index ee3fe6e..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/RigidbodyPrediction.cs +++ /dev/null @@ -1,285 +0,0 @@ -using FishNet; -using FishNet.Object; -using FishNet.Object.Prediction; -using FishNet.Transporting; -using UnityEngine; - -/* -* -* See TransformPrediction.cs for more detailed notes. -* -*/ - -namespace FishNet.Example.Prediction.Rigidbodies -{ - - public class RigidbodyPrediction : NetworkBehaviour - { - #region Types. - public struct MoveData : IReplicateData - { - public bool Jump; - public float Horizontal; - public float Vertical; - public MoveData(bool jump, float horizontal, float vertical) - { - Jump = jump; - Horizontal = horizontal; - Vertical = vertical; - _tick = 0; - } - - private uint _tick; - public void Dispose() { } - public uint GetTick() => _tick; - public void SetTick(uint value) => _tick = value; - } - public struct ReconcileData : IReconcileData - { - public Vector3 Position; - public Quaternion Rotation; - public Vector3 Velocity; - public Vector3 AngularVelocity; - public ReconcileData(Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 angularVelocity) - { - Position = position; - Rotation = rotation; - Velocity = velocity; - AngularVelocity = angularVelocity; - _tick = 0; - } - - private uint _tick; - public void Dispose() { } - public uint GetTick() => _tick; - public void SetTick(uint value) => _tick = value; - } - #endregion - - #region Serialized. - [SerializeField] - private float _jumpForce = 15f; - [SerializeField] - private float _moveRate = 15f; - #endregion - - #region Private. - /// - /// Rigidbody on this object. - /// - private Rigidbody _rigidbody; - /// - /// Next time a jump is allowed. - /// - private float _nextJumpTime; - /// - /// True to jump next frame. - /// - private bool _jump; - #endregion - - #region Predicted spawning. - /// - /// Prefab to spawn for predicted spawning. - /// - public NetworkObject BulletPrefab; - /// - /// True if a spawn is queued from input. - /// - private bool _spawnBullet; - /// - /// True if a despawn is queued from input. - /// - private bool _despawnBullet; - /// - /// Last spawned bullet. Used to test predicted despawn. - /// - private NetworkObject _lastSpawnedBullet; - #endregion - - private void Awake() - { - - _rigidbody = GetComponent(); - InstanceFinder.TimeManager.OnTick += TimeManager_OnTick; - InstanceFinder.TimeManager.OnPostTick += TimeManager_OnPostTick; - } - - private void OnDestroy() - { - if (InstanceFinder.TimeManager != null) - { - InstanceFinder.TimeManager.OnTick -= TimeManager_OnTick; - InstanceFinder.TimeManager.OnPostTick -= TimeManager_OnPostTick; - } - } - - public override void OnStartClient() - { - base.OnStartClient(); - base.PredictionManager.OnPreReplicateReplay += PredictionManager_OnPreReplicateReplay; - } - public override void OnStopClient() - { - base.OnStopClient(); - base.PredictionManager.OnPreReplicateReplay -= PredictionManager_OnPreReplicateReplay; - } - - private void Update() - { - if (base.IsOwner) - { - if (Input.GetKeyDown(KeyCode.RightAlt)) - { - _rigidbody.velocity = Vector3.zero; - _rigidbody.angularVelocity = Vector3.zero; - } - if (Input.GetKeyDown(KeyCode.Space) && Time.time > _nextJumpTime) - { - _nextJumpTime = Time.time + 1f; - _jump = true; - } - else if (Input.GetKeyDown(KeyCode.LeftShift)) - { - _spawnBullet = true; - } - //else if (Input.GetKeyDown(KeyCode.LeftAlt)) - //{ - // _despawnBullet = true; - //} - } - } - - /// - /// Called every time any predicted object is replaying. Replays only occur for owner. - /// Currently owners may only predict one object at a time. - /// - private void PredictionManager_OnPreReplicateReplay(uint arg1, PhysicsScene arg2, PhysicsScene2D arg3) - { - /* Server does not replay so it does - * not need to add gravity. */ - if (!base.IsServer) - AddGravity(); - } - - - private void TimeManager_OnTick() - { - if (base.IsOwner) - { - Reconciliation(default, false); - BuildMoveData(out MoveData md); - Move(md, false); - //Predicted spawning example. - TryDespawnBullet(); - TrySpawnBullet(); - } - if (base.IsServer) - { - Move(default, true); - } - - /* Server and all clients must add the additional gravity. - * Adding gravity is not necessarily required in general but - * to make jumps more snappy extra gravity is added per tick. - * All clients and server need to simulate the gravity to keep - * prediction equal across the network. */ - AddGravity(); - } - - private void TimeManager_OnPostTick() - { - /* Reconcile is sent during PostTick because we - * want to send the rb data AFTER the simulation. */ - if (base.IsServer) - { - ReconcileData rd = new ReconcileData(transform.position, transform.rotation, _rigidbody.velocity, _rigidbody.angularVelocity); - Reconciliation(rd, true); - } - } - - - /// - /// Builds a MoveData to use within replicate. - /// - /// - private void BuildMoveData(out MoveData md) - { - md = default; - - float horizontal = Input.GetAxisRaw("Horizontal"); - float vertical = Input.GetAxisRaw("Vertical"); - - if (horizontal == 0f && vertical == 0f && !_jump) - return; - - md = new MoveData(_jump, horizontal, vertical); - _jump = false; - } - - - /// - /// PredictedObject example (unpolished) - /// - private void TrySpawnBullet() - { - if (_spawnBullet) - { - _spawnBullet = false; - - NetworkObject nob = Instantiate(BulletPrefab, transform.position + (transform.forward * 1f), transform.rotation); - //Set last spawned to test destroy with ALT key. - _lastSpawnedBullet = nob; - - //Set force to 100f at current forward. - PredictedBullet bt = nob.GetComponent(); - bt.SetStartingForce(transform.forward * 20f); - //Spawn client side, which will send the predicted spawn to server. - base.Spawn(nob, base.Owner); - } - } - - /// - /// PredictedObject example (unpolished) - /// - private void TryDespawnBullet() - { - if (_despawnBullet) - { - _despawnBullet = false; - _lastSpawnedBullet?.Despawn(); - } - } - - /// - /// Adds gravity to the rigidbody. - /// - private void AddGravity() - { - _rigidbody.AddForce(Physics.gravity * 2f); - } - - [Replicate] - private void Move(MoveData md, bool asServer, Channel channel = Channel.Unreliable, bool replaying = false) - { - Vector3 forces = new Vector3(md.Horizontal, 0f, md.Vertical) * _moveRate; - _rigidbody.AddForce(forces); - - if (md.Jump) - _rigidbody.AddForce(new Vector3(0f, _jumpForce, 0f), ForceMode.Impulse); - } - - [Reconcile] - private void Reconciliation(ReconcileData rd, bool asServer, Channel channel = Channel.Unreliable) - { - transform.position = rd.Position; - transform.rotation = rd.Rotation; - _rigidbody.velocity = rd.Velocity; - _rigidbody.angularVelocity = rd.AngularVelocity; - } - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/RigidbodyPrediction.cs.meta b/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/RigidbodyPrediction.cs.meta deleted file mode 100644 index b80d6e4..0000000 --- a/Assets/FishNet/Example/All/Prediction/Rigidbody/Scripts/RigidbodyPrediction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9e123f937d4b4f94c9cb6cc03944f786 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Transform.meta b/Assets/FishNet/Example/All/Prediction/Transform.meta deleted file mode 100644 index af337f4..0000000 --- a/Assets/FishNet/Example/All/Prediction/Transform.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 49d8c9756de86004c802a5ce8448fdad -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Transform/Prefabs.meta b/Assets/FishNet/Example/All/Prediction/Transform/Prefabs.meta deleted file mode 100644 index abbd684..0000000 --- a/Assets/FishNet/Example/All/Prediction/Transform/Prefabs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 52874c2b0ae3cc74d9b6be4650f3a24a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Transform/Prefabs/TransformPrediction.prefab b/Assets/FishNet/Example/All/Prediction/Transform/Prefabs/TransformPrediction.prefab deleted file mode 100644 index 26c013c..0000000 --- a/Assets/FishNet/Example/All/Prediction/Transform/Prefabs/TransformPrediction.prefab +++ /dev/null @@ -1,250 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &27039729695437544 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 27039729695437538} - - component: {fileID: 27039729695437541} - - component: {fileID: 27039729695437542} - - component: {fileID: 27039729695437543} - - component: {fileID: 8399567158492483659} - - component: {fileID: -4118712540632748398} - m_Layer: 0 - m_Name: TransformPrediction - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &27039729695437538 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 27039729695437544} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 1, z: -10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 7846666075604890595} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!136 &27039729695437541 -CapsuleCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 27039729695437544} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - m_Radius: 0.5 - m_Height: 2 - m_Direction: 1 - m_Center: {x: 0, y: 0, z: 0} ---- !u!114 &27039729695437542 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 27039729695437544} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 13cad243fdfd7294e8a6a393735726eb, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 255 - _addedNetworkObject: {fileID: 27039729695437543} - _networkObjectCache: {fileID: 0} - _moveRate: 5 ---- !u!114 &27039729695437543 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 27039729695437544} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkObserver: {fileID: 0} - k__BackingField: 0 - k__BackingField: 0 - _scenePathHash: 0 - k__BackingField: 0 - k__BackingField: 139770397801111289 - _sceneNetworkObjects: [] - k__BackingField: 0 - k__BackingField: 0 - k__BackingField: {fileID: 0} - _networkBehaviours: [] - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 ---- !u!114 &8399567158492483659 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 27039729695437544} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 402926ef33e0a894d9fec352693988ac, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 255 - _addedNetworkObject: {fileID: 0} - _networkObjectCache: {fileID: 0} - _implementsPredictionMethods: 1 - _graphicalObject: {fileID: 0} - _enableTeleport: 0 - _teleportThreshold: 1 - _ownerSmoothPosition: 1 - _ownerSmoothRotation: 1 - _ownerInterpolation: 1 - _predictionType: 0 - _rigidbody: {fileID: 0} - _rigidbody2d: {fileID: 0} - _spectatorSmoothPosition: 1 - _spectatorSmoothRotation: 1 - _spectatorInterpolation: 4 - _overflowMultiplier: 0.1 - _maintainedVelocity: 0 - _resendType: 0 - _resendInterval: 30 - _networkTransform: {fileID: 0} ---- !u!114 &-4118712540632748398 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 27039729695437544} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a2836e36774ca1c4bbbee976e17b649c, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 255 - _addedNetworkObject: {fileID: 27039729695437543} - _networkObjectCache: {fileID: 0} - _synchronizeParent: 0 - _packing: - Position: 1 - Rotation: 1 - Scale: 0 - _interpolation: 2 - _extrapolation: 2 - _enableTeleport: 0 - _teleportThreshold: 1 - _clientAuthoritative: 1 - _sendToOwner: 1 - _synchronizePosition: 1 - _positionSnapping: - X: 0 - Y: 0 - Z: 0 - _synchronizeRotation: 1 - _rotationSnapping: - X: 0 - Y: 0 - Z: 0 - _synchronizeScale: 1 - _scaleSnapping: - X: 0 - Y: 0 - Z: 0 ---- !u!1 &907868826061293566 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7846666075604890595} - - component: {fileID: 3240451035359699034} - - component: {fileID: 85305618895715439} - m_Layer: 0 - m_Name: Capsule - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &7846666075604890595 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 907868826061293566} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 27039729695437538} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &3240451035359699034 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 907868826061293566} - m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &85305618895715439 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 907868826061293566} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 diff --git a/Assets/FishNet/Example/All/Prediction/Transform/Prefabs/TransformPrediction.prefab.meta b/Assets/FishNet/Example/All/Prediction/Transform/Prefabs/TransformPrediction.prefab.meta deleted file mode 100644 index 6ef3a43..0000000 --- a/Assets/FishNet/Example/All/Prediction/Transform/Prefabs/TransformPrediction.prefab.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: f820efff6a2871447b961fc755212ba3 -PrefabImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Transform/Scripts.meta b/Assets/FishNet/Example/All/Prediction/Transform/Scripts.meta deleted file mode 100644 index a24d6b2..0000000 --- a/Assets/FishNet/Example/All/Prediction/Transform/Scripts.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 99b192b05caa072458c66dbd47086403 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Transform/Scripts/TransformPrediction.cs b/Assets/FishNet/Example/All/Prediction/Transform/Scripts/TransformPrediction.cs deleted file mode 100644 index e56d456..0000000 --- a/Assets/FishNet/Example/All/Prediction/Transform/Scripts/TransformPrediction.cs +++ /dev/null @@ -1,222 +0,0 @@ -using FishNet.Object; -using FishNet.Object.Prediction; -using FishNet.Transporting; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.Example.Prediction.Transforms -{ - public class TransformPrediction : NetworkBehaviour - { - /// - /// Data on how to move. - /// This is processed locally as well sent to the server for processing. - /// Any inputs or values which may affect your move should be placed in your own MoveData. - /// The structure type may be named anything. Classes can also be used but will generate garbage, so structures - /// are recommended. - /// - public struct TestStruct - { - public int Two; - } - public class TestClass - { - public int One; - } - public struct MoveData : IReplicateData - { - public Vector2 Movement; - //public TestStruct _testStruct; - //public TestClass _testClass; - public float Horizontal; - public float Vertical; - private uint _tick; - - public MoveData(float horizontal, float vertical) - { - Movement = new Vector2(horizontal, vertical); - Horizontal = horizontal; - Vertical = vertical; - _tick = 0; - //_testStruct = default; - //_testClass = null; - } - - public void Dispose() { } - public uint GetTick() => _tick; - public void SetTick(uint value) => _tick = value; - } - - /// - /// Data on how to reconcile. - /// Server sends this back to the client. Once the client receives this they - /// will reset their object using this information. Like with MoveData anything that may - /// affect your movement should be reset. Since this is just a transform only position and - /// rotation would be reset. But a rigidbody would include velocities as well. If you are using - /// an asset it's important to know what systems in that asset affect movement and need - /// to be reset as well. - /// - public struct ReconcileData : IReconcileData - { - public Vector3 Position; - public Quaternion Rotation; - private uint _tick; - - public ReconcileData(Vector3 position, Quaternion rotation) - { - Position = position; - Rotation = rotation; - _tick = 0; - } - - public void Dispose() { } - public uint GetTick() => _tick; - public void SetTick(uint value) => _tick = value; - } - - #region Serialized. - /// - /// How many units to move per second. - /// - [Tooltip("How many units to move per second.")] - [SerializeField] - private float _moveRate = 5f; - #endregion - - private void Awake() - { - /* Prediction is tick based so you must - * send datas during ticks. You can use whichever - * tick best fits your need, such as PreTick, Tick, or PostTick. - * In most cases you will send/move using Tick. For rigidbodies - * you will send using PostTick. I subscribe to ticks using - * the InstanceFinder class, which finds the first NetworkManager - * loaded. If you are using several NetworkManagers you would want - * to subscrube in OnStartServer/Client using base.TimeManager. */ - InstanceFinder.TimeManager.OnTick += TimeManager_OnTick; - } - - private void OnDestroy() - { - //Unsubscribe as well. - if (InstanceFinder.TimeManager != null) - { - InstanceFinder.TimeManager.OnTick -= TimeManager_OnTick; - } - } - - private void TimeManager_OnTick() - { - if (base.IsOwner) - { - /* Call reconcile using default, and false for - * asServer. This will reset the client to the latest - * values from server and replay cached inputs. */ - Reconciliation(default, false); - /* CheckInput builds MoveData from user input. When there - * is no input CheckInput returns default. You can handle this - * however you like but Move should be called when default if - * there is no input which needs to be sent to the server. */ - CheckInput(out MoveData md); - /* Move using the input, and false for asServer. - * Inputs are automatically sent with redundancy. How many past - * inputs will be configurable at a later time. - * When a default value is used the most recent past inputs - * are sent a predetermined amount of times. It's important you - * call Move whether your data is default or not. FishNet will - * automatically determine how to send the data, and run the logic. */ - Move(md, false); - } - if (base.IsServer) - { - /* Move using default data with true for asServer. - * The server will use stored data from the client automatically. - * You may also run any sanity checks on the input as demonstrated - * in the method. */ - Move(default, true); - /* After the server has processed input you will want to send - * the result back to clients. You are welcome to skip - * a few sends if you like, eg only send every few ticks. - * Generate data required on how the client will reset and send it by calling your Reconcile - * method with the data, again using true for asServer. Like the - * Replicate method (Move) this will send with redundancy a certain - * amount of times. If there is no input to process from the client this - * will not continue to send data. */ - ReconcileData rd = new ReconcileData(transform.position, transform.rotation); - Reconciliation(rd, true); - } - } - - - /// - /// A simple method to get input. This doesn't have any relation to the prediction. - /// - private void CheckInput(out MoveData md) - { - md = default; - - float horizontal = Input.GetAxisRaw("Horizontal"); - float vertical = Input.GetAxisRaw("Vertical"); - - //No input to send. - if (horizontal == 0f && vertical == 0f) - return; - - //Make movedata with input. - md = new MoveData(horizontal, vertical); - } - - /// - /// Replicate attribute indicates the data is being sent from the client to the server. - /// When Replicate is present data is automatically sent with redundancy. - /// The replay parameter becomes true automatically when client inputs are - /// being replayed after a reconcile. This is useful for a variety of things, - /// such as if you only want to show effects the first time input is run you will - /// do so when replaying is false. - /// - [Replicate] - private void Move(MoveData md, bool asServer, Channel channel = Channel.Unreliable, bool replaying = false) - { - /* You can check if being run as server to - * add security checks such as normalizing - * the inputs. */ - if (asServer) - { - //Sanity check! - } - /* You may also use replaying to know - * if a client is replaying inputs rather - * than running them for the first time. This can - * be useful because you may only want to run - * VFX during the first input and not during - * replayed inputs. */ - if (!replaying) - { - //VFX! - } - - Vector3 move = new Vector3(md.Horizontal, 0f, md.Vertical); - transform.position += (move * _moveRate * (float)base.TimeManager.TickDelta); - } - - /// - /// A Reconcile attribute indicates the client will reconcile - /// using the data and logic within the method. When asServer - /// is true the data is sent to the client with redundancy, - /// and the server will not run the logic. - /// When asServer is false the client will reset using the logic - /// you supply then replay their inputs. - /// - [Reconcile] - private void Reconciliation(ReconcileData rd, bool asServer, Channel channel = Channel.Unreliable) - { - transform.position = rd.Position; - transform.rotation = rd.Rotation; - } - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Example/All/Prediction/Transform/Scripts/TransformPrediction.cs.meta b/Assets/FishNet/Example/All/Prediction/Transform/Scripts/TransformPrediction.cs.meta deleted file mode 100644 index 01cb9f1..0000000 --- a/Assets/FishNet/Example/All/Prediction/Transform/Scripts/TransformPrediction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 13cad243fdfd7294e8a6a393735726eb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/Prediction/Transform/TransformPrediction.unity b/Assets/FishNet/Example/All/Prediction/Transform/TransformPrediction.unity deleted file mode 100644 index d57c7ad..0000000 --- a/Assets/FishNet/Example/All/Prediction/Transform/TransformPrediction.unity +++ /dev/null @@ -1,890 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 256 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 1 - m_PVRDenoiserTypeDirect: 1 - m_PVRDenoiserTypeIndirect: 1 - m_PVRDenoiserTypeAO: 1 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 1 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_UseShadowmask: 1 ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &192429403 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 7443408887813606051, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - m_PrefabInstance: {fileID: 1364334277} - m_PrefabAsset: {fileID: 0} ---- !u!114 &192429404 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 192429403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 3fdaae44044276a49a52229c1597e33b, type: 3} - m_Name: - m_EditorClassIdentifier: - _updateOrder: 0 - _timingType: 0 - _allowTickDropping: 0 - _maximumFrameTicks: 2 - _tickRate: 20 - _pingInterval: 15 - _timingInterval: 15 - _physicsMode: 1 ---- !u!114 &192429405 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 192429403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6f48f002b825cbd45a19bd96d90f9edb, type: 3} - m_Name: - m_EditorClassIdentifier: - _unreliableMTU: 1023 - _ipv4BindAddress: - _ipv6BindAddress: - _port: 7770 - _maximumClients: 4095 - _clientAddress: localhost - _timeout: 15 ---- !u!114 &192429406 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 192429403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 756c28cd3141c4140ae776188ee26729, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkTraffic: - _updateInteval: 1 - _updateClient: 1 - _updateServer: 1 ---- !u!114 &192429407 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 192429403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 8bc8f0363ddc75946a958043c5e49a83, type: 3} - m_Name: - m_EditorClassIdentifier: - _color: {r: 0, g: 0, b: 0, a: 1} - _placement: 2 - _showOutgoing: 1 - _showIncoming: 1 ---- !u!114 &192429408 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 192429403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 34e4a322dca349547989b14021da4e23, type: 3} - m_Name: - m_EditorClassIdentifier: - Transport: {fileID: 192429405} - _latencySimulator: - _enabled: 1 - _simulateHost: 1 - _latency: 100 - _outOfOrder: 0 - _packetLoss: 0 ---- !u!114 &192429409 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 192429403} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: e08bb003fce297d4086cf8cba5aa459a, type: 3} - m_Name: - m_EditorClassIdentifier: - _dropExcessiveReplicates: 1 - _maximumServerReplicates: 15 - _maximumConsumeCount: 4 - _redundancyCount: 3 - _allowPredictedSpawning: 0 - _reservedObjectIds: 15 ---- !u!1 &439822901 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 439822904} - - component: {fileID: 439822903} - - component: {fileID: 439822902} - m_Layer: 0 - m_Name: GameObject - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &439822902 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 439822901} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkObserver: {fileID: 0} - k__BackingField: 0 - k__BackingField: 0 - _scenePathHash: 3820541331 - k__BackingField: 16409100072611719970 - k__BackingField: 0 - _sceneNetworkObjects: - - {fileID: 439822902} - k__BackingField: 0 - k__BackingField: 0 - k__BackingField: {fileID: 0} - _networkBehaviours: - - {fileID: 439822903} - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 ---- !u!114 &439822903 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 439822901} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fc498684834f8864896da013f42864d9, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 0 - _addedNetworkObject: {fileID: 439822902} - _networkObjectCache: {fileID: 439822902} ---- !u!4 &439822904 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 439822901} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -54.301113, y: 11.982289, z: 55.36256} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &555580081 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 555580085} - - component: {fileID: 555580084} - - component: {fileID: 555580083} - - component: {fileID: 555580082} - m_Layer: 0 - m_Name: Sphere - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &555580082 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 555580081} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &555580083 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 555580081} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: ea31fef5ca1bc7344a72c71a5f9a0cd2, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &555580084 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 555580081} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &555580085 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 555580081} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -9.16, y: -3.4, z: 13.1} - m_LocalScale: {x: 15, y: 15, z: 15} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &872683029 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 872683031} - - component: {fileID: 872683030} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!108 &872683030 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 872683029} - m_Enabled: 1 - serializedVersion: 10 - m_Type: 1 - m_Shape: 0 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 4 - m_LightShadowCasterMode: 0 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 0 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_ShadowRadius: 0 - m_ShadowAngle: 0 ---- !u!4 &872683031 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 872683029} - m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: 0, y: 3, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 4 - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!1 &1112005912 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1112005916} - - component: {fileID: 1112005915} - - component: {fileID: 1112005914} - - component: {fileID: 1112005913} - m_Layer: 0 - m_Name: Cube - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!65 &1112005913 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1112005912} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1112005914 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1112005912} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 0bb31cf72dfcef449a1a4a5aab857f63, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1112005915 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1112005912} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &1112005916 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1112005912} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -2, z: 0} - m_LocalScale: {x: 100, y: 1, z: 100} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1001 &1364334277 -PrefabInstance: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Modification: - m_TransformParent: {fileID: 0} - m_Modifications: - - target: {fileID: 4393252310584637056, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: _autoStartType - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_RootOrder - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalPosition.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalRotation.w - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalRotation.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalRotation.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalRotation.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalEulerAnglesHint.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalEulerAnglesHint.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606049, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_LocalEulerAnglesHint.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606050, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: _spawnablePrefabs - value: - objectReference: {fileID: 11400000, guid: 3a54436bdb916194f99da0d17231e617, - type: 2} - - target: {fileID: 7443408887813606051, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: m_Name - value: NetworkManager - objectReference: {fileID: 0} - - target: {fileID: 7443408887813606060, guid: 0b650fca685f2eb41a86538aa883e4c1, - type: 3} - propertyPath: _playerPrefab - value: - objectReference: {fileID: 27039729695437543, guid: f820efff6a2871447b961fc755212ba3, - type: 3} - m_RemovedComponents: [] - m_SourcePrefab: {fileID: 100100000, guid: 0b650fca685f2eb41a86538aa883e4c1, type: 3} ---- !u!1 &1470934487 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1470934491} - - component: {fileID: 1470934490} - - component: {fileID: 1470934489} - - component: {fileID: 1470934488} - m_Layer: 0 - m_Name: Cube (1) - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!65 &1470934488 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1470934487} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1470934489 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1470934487} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: ea31fef5ca1bc7344a72c71a5f9a0cd2, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1470934490 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1470934487} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &1470934491 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1470934487} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 12.11, y: -0.08, z: 0} - m_LocalScale: {x: 1, y: 5, z: 20} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1784594014 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1784594015} - m_Layer: 0 - m_Name: Level - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1784594015 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1784594014} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 1112005916} - - {fileID: 1470934491} - - {fileID: 555580085} - - {fileID: 1852016427} - - {fileID: 872683031} - m_Father: {fileID: 0} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1852016424 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1852016427} - - component: {fileID: 1852016426} - - component: {fileID: 1852016425} - m_Layer: 0 - m_Name: Main Camera - m_TagString: MainCamera - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!81 &1852016425 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1852016424} - m_Enabled: 1 ---- !u!20 &1852016426 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1852016424} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_FocalLength: 50 - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: -1 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!4 &1852016427 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1852016424} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 1, z: -10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 1784594015} - m_RootOrder: 3 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/FishNet/Example/All/Prediction/Transform/TransformPrediction.unity.meta b/Assets/FishNet/Example/All/Prediction/Transform/TransformPrediction.unity.meta deleted file mode 100644 index f444295..0000000 --- a/Assets/FishNet/Example/All/Prediction/Transform/TransformPrediction.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 23d8c720c2338a54c9787668c81290f6 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager.meta b/Assets/FishNet/Example/All/SceneManager.meta deleted file mode 100644 index 5a149c0..0000000 --- a/Assets/FishNet/Example/All/SceneManager.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 3ce919ae77eaee5459c4c0b47a7c13f9 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Materials.meta b/Assets/FishNet/Example/All/SceneManager/Materials.meta deleted file mode 100644 index dd18bf4..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Materials.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e72a8e512b2ca5142857eaab157e8f03 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Materials/Black.mat b/Assets/FishNet/Example/All/SceneManager/Materials/Black.mat deleted file mode 100644 index 99f4278..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Materials/Black.mat +++ /dev/null @@ -1,78 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: Black - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _ALPHAPREMULTIPLY_ON - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: 3000 - stringTagMap: - RenderType: Transparent - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MetallicGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 10 - - _GlossMapScale: 1 - - _Glossiness: 0 - - _GlossyReflections: 1 - - _Metallic: 0.177 - - _Mode: 3 - - _OcclusionStrength: 1 - - _Parallax: 0.02 - - _SmoothnessTextureChannel: 0 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 0 - m_Colors: - - _Color: {r: 0, g: 0, b: 0, a: 0.39215687} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/FishNet/Example/All/SceneManager/Materials/Black.mat.meta b/Assets/FishNet/Example/All/SceneManager/Materials/Black.mat.meta deleted file mode 100644 index b7dfa60..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Materials/Black.mat.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 2e7517d1496ae784f94a2307a88e2bb5 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Materials/Blue.mat b/Assets/FishNet/Example/All/SceneManager/Materials/Blue.mat deleted file mode 100644 index cd9821d..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Materials/Blue.mat +++ /dev/null @@ -1,78 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: Blue - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _ALPHAPREMULTIPLY_ON - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: 3000 - stringTagMap: - RenderType: Transparent - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MetallicGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 10 - - _GlossMapScale: 1 - - _Glossiness: 0 - - _GlossyReflections: 1 - - _Metallic: 0 - - _Mode: 3 - - _OcclusionStrength: 1 - - _Parallax: 0.02 - - _SmoothnessTextureChannel: 0 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 0 - m_Colors: - - _Color: {r: 0, g: 0.6867471, b: 1, a: 0.39215687} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/FishNet/Example/All/SceneManager/Materials/Blue.mat.meta b/Assets/FishNet/Example/All/SceneManager/Materials/Blue.mat.meta deleted file mode 100644 index abdab7d..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Materials/Blue.mat.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: d0a99caade0a68842b2274726d1bc7c3 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Materials/Green.mat b/Assets/FishNet/Example/All/SceneManager/Materials/Green.mat deleted file mode 100644 index 04c1cf8..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Materials/Green.mat +++ /dev/null @@ -1,78 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: Green - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _ALPHAPREMULTIPLY_ON - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: 3000 - stringTagMap: - RenderType: Transparent - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MetallicGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 10 - - _GlossMapScale: 1 - - _Glossiness: 0 - - _GlossyReflections: 1 - - _Metallic: 0 - - _Mode: 3 - - _OcclusionStrength: 1 - - _Parallax: 0.02 - - _SmoothnessTextureChannel: 0 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 0 - m_Colors: - - _Color: {r: 0, g: 1, b: 0.030314445, a: 0.39215687} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/FishNet/Example/All/SceneManager/Materials/Green.mat.meta b/Assets/FishNet/Example/All/SceneManager/Materials/Green.mat.meta deleted file mode 100644 index 92fd8a6..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Materials/Green.mat.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e0dd7b8c357813f4ba3ae9b60783a6cd -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Materials/Red.mat b/Assets/FishNet/Example/All/SceneManager/Materials/Red.mat deleted file mode 100644 index 19a839c..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Materials/Red.mat +++ /dev/null @@ -1,78 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: Red - m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _ALPHAPREMULTIPLY_ON - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: 3000 - stringTagMap: - RenderType: Transparent - disabledShaderPasses: [] - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MetallicGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 10 - - _GlossMapScale: 1 - - _Glossiness: 0 - - _GlossyReflections: 1 - - _Metallic: 0 - - _Mode: 3 - - _OcclusionStrength: 1 - - _Parallax: 0.02 - - _SmoothnessTextureChannel: 0 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 0 - m_Colors: - - _Color: {r: 1, g: 0.018451946, b: 0, a: 0.39215687} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/FishNet/Example/All/SceneManager/Materials/Red.mat.meta b/Assets/FishNet/Example/All/SceneManager/Materials/Red.mat.meta deleted file mode 100644 index 7dd93d4..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Materials/Red.mat.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: a35bce0c956282a42a90a04b25492fb6 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Prefabs.meta b/Assets/FishNet/Example/All/SceneManager/Prefabs.meta deleted file mode 100644 index 6dcfebb..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Prefabs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: ff677f3c29d59764f917114e0ddf4323 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Prefabs/Player.prefab b/Assets/FishNet/Example/All/SceneManager/Prefabs/Player.prefab deleted file mode 100644 index bab21db..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Prefabs/Player.prefab +++ /dev/null @@ -1,337 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &1659630665519808908 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2767813079423793104} - - component: {fileID: 2155251397865338026} - - component: {fileID: 6670251115109007609} - m_Layer: 2 - m_Name: Capsule - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &2767813079423793104 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1659630665519808908} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0.893, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 5090726670223187106} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &2155251397865338026 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1659630665519808908} - m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &6670251115109007609 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1659630665519808908} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!1 &5090726669533971462 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 5090726669533971481} - - component: {fileID: 5090726669533971480} - - component: {fileID: 5090726669533971463} - m_Layer: 0 - m_Name: Main Camera - m_TagString: MainCamera - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!4 &5090726669533971481 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5090726669533971462} - m_LocalRotation: {x: 0.04100376, y: 0, z: 0, w: 0.99915904} - m_LocalPosition: {x: 0, y: 1.56, z: -4.5} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 5090726670223187106} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 4.7, y: 0, z: 0} ---- !u!20 &5090726669533971480 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5090726669533971462} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_FocalLength: 50 - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: -1 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!81 &5090726669533971463 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5090726669533971462} - m_Enabled: 1 ---- !u!1 &5090726670223187118 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 5090726670223187106} - - component: {fileID: 5090726670223187108} - - component: {fileID: 3514369712614123748} - - component: {fileID: 474764807019926078} - - component: {fileID: 611616139817875448} - - component: {fileID: 6420552185407096997} - - component: {fileID: 6654616088585099699} - m_Layer: 0 - m_Name: Player - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &5090726670223187106 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5090726670223187118} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 5, y: 0, z: -10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 5090726669533971481} - - {fileID: 2767813079423793104} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &5090726670223187108 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5090726670223187118} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26e4f626a9ca9704f9befe7673a8dd15, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 0 - _addedNetworkObject: {fileID: 611616139817875448} - _networkObjectCache: {fileID: 611616139817875448} - _camera: {fileID: 5090726669533971462} - _moveRate: 8 - _clientAuth: 1 ---- !u!54 &3514369712614123748 -Rigidbody: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5090726670223187118} - serializedVersion: 2 - m_Mass: 1 - m_Drag: 0 - m_AngularDrag: 0.05 - m_UseGravity: 0 - m_IsKinematic: 1 - m_Interpolate: 0 - m_Constraints: 0 - m_CollisionDetection: 0 ---- !u!136 &474764807019926078 -CapsuleCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5090726670223187118} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - m_Radius: 0.5 - m_Height: 1 - m_Direction: 1 - m_Center: {x: 0, y: 0, z: 0} ---- !u!114 &611616139817875448 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5090726670223187118} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkObserver: {fileID: 0} - k__BackingField: 6 - k__BackingField: 0 - _scenePathHash: 0 - k__BackingField: 0 - k__BackingField: 15644345540858261432 - _sceneNetworkObjects: [] - k__BackingField: 0 - k__BackingField: 0 - k__BackingField: {fileID: 0} - _networkBehaviours: - - {fileID: 5090726670223187108} - - {fileID: 6654616088585099699} - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 ---- !u!114 &6420552185407096997 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5090726670223187118} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c71fd7f855ec523429999fc4e14a1928, type: 3} - m_Name: - m_EditorClassIdentifier: - _overrideType: 3 - _updateHostVisibility: 1 - _observerConditions: [] ---- !u!114 &6654616088585099699 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5090726670223187118} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a2836e36774ca1c4bbbee976e17b649c, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 1 - _addedNetworkObject: {fileID: 611616139817875448} - _networkObjectCache: {fileID: 611616139817875448} - _synchronizeParent: 0 - _packing: - Position: 1 - Rotation: 1 - Scale: 0 - _interpolation: 2 - _extrapolation: 2 - _enableTeleport: 0 - _teleportThreshold: 1 - _clientAuthoritative: 1 - _sendToOwner: 1 - _synchronizePosition: 1 - _positionSnapping: - X: 0 - Y: 0 - Z: 0 - _synchronizeRotation: 1 - _rotationSnapping: - X: 0 - Y: 0 - Z: 0 - _synchronizeScale: 1 - _scaleSnapping: - X: 0 - Y: 0 - Z: 0 diff --git a/Assets/FishNet/Example/All/SceneManager/Prefabs/Player.prefab.meta b/Assets/FishNet/Example/All/SceneManager/Prefabs/Player.prefab.meta deleted file mode 100644 index a7f29b6..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Prefabs/Player.prefab.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: bf5f023b4017a5e41a9815ec5745df3d -PrefabImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/SceneManager Event Diagram.png b/Assets/FishNet/Example/All/SceneManager/SceneManager Event Diagram.png deleted file mode 100644 index de8858be547b80ed95625e647ad78ba294db93f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45367 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

mHVGPGm}y`7lOc`|kw$C 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 UDXC%0bHu70Tg|snjO@<+53I9EC;$Ke diff --git a/Assets/FishNet/Example/All/SceneManager/SceneManager Event Diagram.png.meta b/Assets/FishNet/Example/All/SceneManager/SceneManager Event Diagram.png.meta deleted file mode 100644 index 33e28f3..0000000 --- a/Assets/FishNet/Example/All/SceneManager/SceneManager Event Diagram.png.meta +++ /dev/null @@ -1,92 +0,0 @@ -fileFormatVersion: 2 -guid: f2231de60d345664cb1831a2e2ebe776 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 11 - mipmaps: - mipMapMode: 0 - enableMipMap: 1 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 0 - wrapV: 0 - wrapW: 0 - nPOTScale: 1 - lightmap: 0 - compressionQuality: 50 - spriteMode: 0 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 0 - spriteTessellationDetail: -1 - textureType: 0 - textureShape: 1 - singleChannelComponent: 0 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - applyGammaDecoding: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - spritePackingTag: - pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes.meta b/Assets/FishNet/Example/All/SceneManager/Scenes.meta deleted file mode 100644 index 6d8db28..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: cf1de1b0d2f857d41ab48f999ffc7e2c -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes/Additive.meta b/Assets/FishNet/Example/All/SceneManager/Scenes/Additive.meta deleted file mode 100644 index 2690e79..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes/Additive.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 3d3192e4db2057b46bdf0b1c61bed424 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveConnection.unity b/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveConnection.unity deleted file mode 100644 index 4e63925..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveConnection.unity +++ /dev/null @@ -1,264 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.37311953, g: 0.38074014, b: 0.3587274, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 256 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 1 - m_PVRDenoiserTypeDirect: 1 - m_PVRDenoiserTypeIndirect: 1 - m_PVRDenoiserTypeAO: 1 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 1 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_UseShadowmask: 1 ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &76845508 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 76845512} - - component: {fileID: 76845511} - - component: {fileID: 76845510} - - component: {fileID: 76845509} - - component: {fileID: 76845514} - - component: {fileID: 76845513} - m_Layer: 0 - m_Name: Cube - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!65 &76845509 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 76845508} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &76845510 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 76845508} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &76845511 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 76845508} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &76845512 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 76845508} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -5, y: 0, z: 10} - m_LocalScale: {x: 4, y: 4, z: 4} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &76845513 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 76845508} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkObserver: {fileID: 0} - k__BackingField: -1 - _scenePathHash: 3284346746 - k__BackingField: 14106161864781660253 - _sceneNetworkObjects: - - {fileID: 76845513} - k__BackingField: 0 - k__BackingField: 0 - _networkBehaviours: - - {fileID: 76845514} - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _disableOnDespawn: 0 ---- !u!114 &76845514 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 76845508} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c71fd7f855ec523429999fc4e14a1928, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 0 - _addedNetworkObject: {fileID: 76845513} - _networkObjectCache: {fileID: 76845513} - _overrideType: 3 - _setHostVisibility: 1 - _observerConditions: - - {fileID: 11400000, guid: 2033f54fd2794464bae08fa5a55c8996, type: 2} diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveConnection.unity.meta b/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveConnection.unity.meta deleted file mode 100644 index 807c4f4..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveConnection.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: cc489be8bb6ae444283f394c5e5fa8e2 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveGlobal.unity b/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveGlobal.unity deleted file mode 100644 index 85d0f6f..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveGlobal.unity +++ /dev/null @@ -1,264 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.37311953, g: 0.38074014, b: 0.3587274, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 256 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 1 - m_PVRDenoiserTypeDirect: 1 - m_PVRDenoiserTypeIndirect: 1 - m_PVRDenoiserTypeAO: 1 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 1 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_UseShadowmask: 1 ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &1950515027 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1950515031} - - component: {fileID: 1950515030} - - component: {fileID: 1950515029} - - component: {fileID: 1950515028} - - component: {fileID: 1950515033} - - component: {fileID: 1950515032} - m_Layer: 0 - m_Name: Sphere - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &1950515028 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1950515027} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1950515029 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1950515027} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1950515030 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1950515027} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &1950515031 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1950515027} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 5, y: 0, z: 10} - m_LocalScale: {x: 4, y: 4, z: 4} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &1950515032 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1950515027} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkObserver: {fileID: 0} - k__BackingField: -1 - _scenePathHash: 2384367787 - k__BackingField: 10240781668764572782 - _sceneNetworkObjects: - - {fileID: 1950515032} - k__BackingField: 0 - k__BackingField: 0 - _networkBehaviours: - - {fileID: 1950515033} - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _disableOnDespawn: 0 ---- !u!114 &1950515033 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1950515027} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c71fd7f855ec523429999fc4e14a1928, type: 3} - m_Name: - m_EditorClassIdentifier: - _componentIndexCache: 0 - _addedNetworkObject: {fileID: 1950515032} - _networkObjectCache: {fileID: 1950515032} - _overrideType: 3 - _setHostVisibility: 1 - _observerConditions: - - {fileID: 11400000, guid: 2033f54fd2794464bae08fa5a55c8996, type: 2} diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveGlobal.unity.meta b/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveGlobal.unity.meta deleted file mode 100644 index 36036b2..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveGlobal.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: c43835f124dc68747a2091c4b8c42f80 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveMain.unity b/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveMain.unity deleted file mode 100644 index dc78e62..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveMain.unity +++ /dev/null @@ -1,1265 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 705507994} - m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 500 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 500 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 2 - m_PVRDenoiserTypeDirect: 0 - m_PVRDenoiserTypeIndirect: 0 - m_PVRDenoiserTypeAO: 0 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 0 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_UseShadowmask: 1 ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &705507993 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 705507995} - - component: {fileID: 705507994} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!108 &705507994 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 705507993} - m_Enabled: 1 - serializedVersion: 10 - m_Type: 1 - m_Shape: 0 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 1 - m_LightShadowCasterMode: 0 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 0 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_ShadowRadius: 0 - m_ShadowAngle: 0 ---- !u!4 &705507995 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 705507993} - m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: -2.2843354, y: 60.72741, z: -2.9938574} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 1155569020} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!1 &825925881 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 825925885} - - component: {fileID: 825925886} - - component: {fileID: 825925887} - - component: {fileID: 825925884} - - component: {fileID: 825925883} - - component: {fileID: 825925882} - m_Layer: 0 - m_Name: Connection - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &825925882 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 825925881} - m_Material: {fileID: 0} - m_IsTrigger: 1 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &825925883 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 825925881} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: d0a99caade0a68842b2274726d1bc7c3, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &825925884 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 825925881} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &825925885 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 825925881} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -4.7799997, y: -3, z: 10} - m_LocalScale: {x: 15, y: 15, z: 15} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &825925886 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 825925881} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fa23b6e6f9b08d74885e3707aa0d9bc7, type: 3} - m_Name: - m_EditorClassIdentifier: - _moveObject: 0 - _moveAllObjects: 0 - _replaceOption: 2 - _scenes: - - AdditiveConnection - _connectionOnly: 1 - _automaticallyUnload: 1 - _onTriggerEnter: 1 ---- !u!114 &825925887 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 825925881} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 84ae572fef1171b41ab287d1c9b5da63, type: 3} - m_Name: - m_EditorClassIdentifier: - _scenes: - - AdditiveConnection - _connectionOnly: 1 - _unloadUnused: 1 - _onTriggerEnter: 0 ---- !u!1 &1155569019 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1155569020} - m_Layer: 0 - m_Name: Scene - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1155569020 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1155569019} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 705507995} - - {fileID: 2114768053} - m_Father: {fileID: 0} - m_RootOrder: 3 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1406093434 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1406093440} - - component: {fileID: 1406093439} - - component: {fileID: 1406093438} - - component: {fileID: 1406093437} - - component: {fileID: 1406093436} - - component: {fileID: 1406093435} - m_Layer: 0 - m_Name: Global - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &1406093435 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1406093434} - m_Material: {fileID: 0} - m_IsTrigger: 1 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1406093436 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1406093434} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: a35bce0c956282a42a90a04b25492fb6, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1406093437 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1406093434} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!114 &1406093438 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1406093434} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 84ae572fef1171b41ab287d1c9b5da63, type: 3} - m_Name: - m_EditorClassIdentifier: - _scenes: - - AdditiveGlobal - _connectionOnly: 0 - _unloadUnused: 1 - _onTriggerEnter: 0 ---- !u!114 &1406093439 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1406093434} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fa23b6e6f9b08d74885e3707aa0d9bc7, type: 3} - m_Name: - m_EditorClassIdentifier: - _moveObject: 0 - _moveAllObjects: 0 - _replaceOption: 2 - _scenes: - - AdditiveGlobal - _connectionOnly: 0 - _automaticallyUnload: 1 - _onTriggerEnter: 1 ---- !u!4 &1406093440 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1406093434} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 4.89, y: -3, z: 10} - m_LocalScale: {x: 15, y: 15, z: 15} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &2114768049 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2114768053} - - component: {fileID: 2114768052} - - component: {fileID: 2114768051} - - component: {fileID: 2114768050} - m_Layer: 0 - m_Name: Plane - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!64 &2114768050 -MeshCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2114768049} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 4 - m_Convex: 0 - m_CookingOptions: 30 - m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &2114768051 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2114768049} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &2114768052 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2114768049} - m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &2114768053 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2114768049} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -5, z: 0} - m_LocalScale: {x: 10, y: 10, z: 10} - m_Children: [] - m_Father: {fileID: 1155569020} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &174578014943721374 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 6832184529280211084} - - component: {fileID: 9050426448999039876} - - component: {fileID: 3730311944083398519} - m_Layer: 5 - m_Name: Indicator - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &1661284633666962301 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7114397409874979456} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2b3dca501a9d8c8479dc71dd068aa8b8, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!114 &2085292595826649312 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2085292595826649325} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2d50394614f8feb4eb0567fb7618d84d, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!222 &2085292595826649313 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2085292595826649325} - m_CullTransparentMesh: 0 ---- !u!1 &2085292595826649325 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2085292595826649326} - - component: {fileID: 2085292595826649313} - - component: {fileID: 2085292595826649312} - - component: {fileID: 2085292595826649327} - m_Layer: 5 - m_Name: Client - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &2085292595826649326 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2085292595826649325} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 6832184529280211084} - m_Father: {fileID: 2085292596359202251} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 16, y: -96} - m_SizeDelta: {x: 256, y: 64} - m_Pivot: {x: 0, y: 1} ---- !u!114 &2085292595826649327 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2085292595826649325} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 3 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Selected - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 2085292595826649312} - m_OnClick: - m_PersistentCalls: - m_Calls: - - m_Target: {fileID: 2085292596359202263} - m_MethodName: OnClick_Client - m_Mode: 1 - m_Arguments: - m_ObjectArgument: {fileID: 0} - m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine - m_IntArgument: 0 - m_FloatArgument: 0 - m_StringArgument: - m_BoolArgument: 0 - m_CallState: 2 ---- !u!114 &2085292596010868064 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2085292596010868077} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 1b187e63031bf7849b249c8212440c3b, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!222 &2085292596010868065 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2085292596010868077} - m_CullTransparentMesh: 0 ---- !u!1 &2085292596010868077 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2085292596010868078} - - component: {fileID: 2085292596010868065} - - component: {fileID: 2085292596010868064} - - component: {fileID: 2085292596010868079} - m_Layer: 5 - m_Name: Server - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &2085292596010868078 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2085292596010868077} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 4928688179816641390} - m_Father: {fileID: 2085292596359202251} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 16, y: -16} - m_SizeDelta: {x: 256, y: 64} - m_Pivot: {x: 0, y: 1} ---- !u!114 &2085292596010868079 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2085292596010868077} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 3 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Selected - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 2085292596010868064} - m_OnClick: - m_PersistentCalls: - m_Calls: - - m_Target: {fileID: 2085292596359202263} - m_MethodName: OnClick_Server - m_Mode: 1 - m_Arguments: - m_ObjectArgument: {fileID: 0} - m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine - m_IntArgument: 0 - m_FloatArgument: 0 - m_StringArgument: - m_BoolArgument: 0 - m_CallState: 2 ---- !u!114 &2085292596359202248 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2085292596359202262} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} - m_Name: - m_EditorClassIdentifier: - m_IgnoreReversedGraphics: 1 - m_BlockingObjects: 0 - m_BlockingMask: - serializedVersion: 2 - m_Bits: 4294967295 ---- !u!114 &2085292596359202249 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2085292596359202262} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} - m_Name: - m_EditorClassIdentifier: - m_UiScaleMode: 1 - m_ReferencePixelsPerUnit: 100 - m_ScaleFactor: 1 - m_ReferenceResolution: {x: 1920, y: 1080} - m_ScreenMatchMode: 0 - m_MatchWidthOrHeight: 0.5 - m_PhysicalUnit: 3 - m_FallbackScreenDPI: 96 - m_DefaultSpriteDPI: 96 - m_DynamicPixelsPerUnit: 1 ---- !u!223 &2085292596359202250 -Canvas: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2085292596359202262} - m_Enabled: 1 - serializedVersion: 3 - m_RenderMode: 0 - m_Camera: {fileID: 0} - m_PlaneDistance: 100 - m_PixelPerfect: 0 - m_ReceivesEvents: 1 - m_OverrideSorting: 0 - m_OverridePixelPerfect: 0 - m_SortingBucketNormalizedSize: 0 - m_AdditionalShaderChannelsFlag: 0 - m_SortingLayerID: 0 - m_SortingOrder: 0 - m_TargetDisplay: 0 ---- !u!224 &2085292596359202251 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2085292596359202262} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0, y: 0, z: 0} - m_Children: - - {fileID: 2085292596010868078} - - {fileID: 2085292595826649326} - m_Father: {fileID: 7443408887680269496} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0, y: 0} ---- !u!1 &2085292596359202262 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2085292596359202251} - - component: {fileID: 2085292596359202250} - - component: {fileID: 2085292596359202249} - - component: {fileID: 2085292596359202248} - - component: {fileID: 2085292596359202263} - m_Layer: 5 - m_Name: NetworkHudCanvas - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &2085292596359202263 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2085292596359202262} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6d3606bfdac5a4743890fc1a5ecd8f24, type: 3} - m_Name: - m_EditorClassIdentifier: - _autoStartType: 0 - _stoppedColor: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - _changingColor: {r: 0.78431374, g: 0.6862745, b: 0, a: 1} - _startedColor: {r: 0, g: 0.5882353, b: 0.64705884, a: 1} - _serverIndicator: {fileID: 1661284633666962301} - _clientIndicator: {fileID: 3730311944083398519} ---- !u!114 &3730311944083398519 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 174578014943721374} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2b3dca501a9d8c8479dc71dd068aa8b8, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!224 &4928688179816641390 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7114397409874979456} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -1} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 2085292596010868078} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!224 &6832184529280211084 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 174578014943721374} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -1} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 2085292595826649326} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!1 &7114397409874979456 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4928688179816641390} - - component: {fileID: 7408958669887450887} - - component: {fileID: 1661284633666962301} - m_Layer: 5 - m_Name: Indicator - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!222 &7408958669887450887 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7114397409874979456} - m_CullTransparentMesh: 0 ---- !u!4 &7443408887680269496 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887680269498} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -2.2843354, y: 57.72741, z: -2.9938574} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 2085292596359202251} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &7443408887680269498 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7443408887680269496} - - component: {fileID: 7443408887680269499} - - component: {fileID: 7443408887680269500} - - component: {fileID: 7443408887680269501} - - component: {fileID: 7443408887680269502} - - component: {fileID: 7443408887680269503} - m_Layer: 0 - m_Name: 'NetworkManager ' - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &7443408887680269499 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887680269498} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d2c95dfde7d73b54dbbdc23155d35d36, type: 3} - m_Name: - m_EditorClassIdentifier: - _logging: {fileID: 0} - _spawnablePrefabs: {fileID: 11400000, guid: 3a54436bdb916194f99da0d17231e617, type: 2} - _refreshDefaultPrefabs: 1 - _runInBackground: 1 - _dontDestroyOnLoad: 1 - _objectPool: {fileID: 0} - _persistence: 0 ---- !u!114 &7443408887680269500 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887680269498} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 3fdaae44044276a49a52229c1597e33b, type: 3} - m_Name: - m_EditorClassIdentifier: - _updateOrder: 0 - _timingType: 0 - _allowTickDropping: 0 - _maximumFrameTicks: 2 - _tickRate: 30 - _pingInterval: 1 - _timingInterval: 2 - _physicsMode: 0 ---- !u!114 &7443408887680269501 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887680269498} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6f48f002b825cbd45a19bd96d90f9edb, type: 3} - m_Name: - m_EditorClassIdentifier: - _unreliableMTU: 1023 - _ipv4BindAddress: - _ipv6BindAddress: - _port: 7770 - _maximumClients: 4095 - _clientAddress: localhost - _timeout: 15 ---- !u!114 &7443408887680269502 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887680269498} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 68828c85278210948b9d50a8db3aab74, type: 3} - m_Name: - m_EditorClassIdentifier: - _authenticator: {fileID: 0} - _syncTypeRate: 0.1 - SpawnPacking: - Position: 0 - Rotation: 2 - Scale: 2 - _changeFrameRate: 1 - _frameRate: 9999 - _shareIds: 1 - _startOnHeadless: 1 - _limitClientMTU: 1 ---- !u!114 &7443408887680269503 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887680269498} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 211a9f6ec51ddc14f908f5acc0cd0423, type: 3} - m_Name: - m_EditorClassIdentifier: - _playerPrefab: {fileID: 611616139817875448, guid: bf5f023b4017a5e41a9815ec5745df3d, - type: 3} - _addToDefaultScene: 1 - Spawns: [] ---- !u!222 &9050426448999039876 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 174578014943721374} - m_CullTransparentMesh: 0 diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveMain.unity.meta b/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveMain.unity.meta deleted file mode 100644 index 86dfccb..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes/Additive/AdditiveMain.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: e7d3ac2d556912042aca9aa1947aea07 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes/Replace.meta b/Assets/FishNet/Example/All/SceneManager/Scenes/Replace.meta deleted file mode 100644 index 7b51256..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes/Replace.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 2ad819293f3cbbf44b9e2790853833c5 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceConnection.unity b/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceConnection.unity deleted file mode 100644 index 836be96..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceConnection.unity +++ /dev/null @@ -1,624 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 256 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 1 - m_PVRDenoiserTypeDirect: 1 - m_PVRDenoiserTypeIndirect: 1 - m_PVRDenoiserTypeAO: 1 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 1 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_UseShadowmask: 1 ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &76845508 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 76845512} - - component: {fileID: 76845511} - - component: {fileID: 76845510} - - component: {fileID: 76845509} - - component: {fileID: 76845514} - - component: {fileID: 76845513} - m_Layer: 0 - m_Name: Cube - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!65 &76845509 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 76845508} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &76845510 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 76845508} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &76845511 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 76845508} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &76845512 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 76845508} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -19.2, y: 3.8, z: -0.43} - m_LocalScale: {x: 4, y: 4, z: 4} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &76845513 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 76845508} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkObserver: {fileID: 0} - k__BackingField: -1 - _scenePathHash: 3254454948 - k__BackingField: 13977777569408466860 - k__BackingField: 0 - _sceneNetworkObjects: - - {fileID: 76845513} - k__BackingField: 0 - k__BackingField: 0 - _networkBehaviours: [] - k__BackingField: {fileID: 0} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _defaultDespawnType: 0 ---- !u!114 &76845514 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 76845508} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c71fd7f855ec523429999fc4e14a1928, type: 3} - m_Name: - m_EditorClassIdentifier: - _overrideType: 3 - _updateHostVisibility: 1 - _observerConditions: - - {fileID: 11400000, guid: 2033f54fd2794464bae08fa5a55c8996, type: 2} ---- !u!1 &603255273 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 603255274} - m_Layer: 0 - m_Name: Triggers - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &603255274 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 603255273} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -22.68, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 979031081727779170} - m_Father: {fileID: 0} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!4 &748707377276284900 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 748707377276284902} - m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: -2.2843354, y: 60.72741, z: -2.9938574} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 748707378658658307} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!108 &748707377276284901 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 748707377276284902} - m_Enabled: 1 - serializedVersion: 10 - m_Type: 1 - m_Shape: 0 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 1 - m_LightShadowCasterMode: 0 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 0 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_ShadowRadius: 0 - m_ShadowAngle: 0 ---- !u!1 &748707377276284902 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 748707377276284900} - - component: {fileID: 748707377276284901} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &748707378551427530 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 748707378551427534} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -5, z: 0} - m_LocalScale: {x: 10, y: 10, z: 10} - m_Children: [] - m_Father: {fileID: 748707378658658307} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &748707378551427531 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 748707378551427534} - m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &748707378551427532 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 748707378551427534} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!64 &748707378551427533 -MeshCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 748707378551427534} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 4 - m_Convex: 0 - m_CookingOptions: 30 - m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} ---- !u!1 &748707378551427534 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 748707378551427530} - - component: {fileID: 748707378551427531} - - component: {fileID: 748707378551427532} - - component: {fileID: 748707378551427533} - m_Layer: 0 - m_Name: Plane - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &748707378658658307 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 748707378658658308} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 748707377276284900} - - {fileID: 748707378551427530} - m_Father: {fileID: 0} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &748707378658658308 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 748707378658658307} - m_Layer: 0 - m_Name: Scene - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &979031081727779169 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 979031081727779174} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fa23b6e6f9b08d74885e3707aa0d9bc7, type: 3} - m_Name: - m_EditorClassIdentifier: - _moveObject: 1 - _moveAllObjects: 0 - _replaceOption: 0 - _scenes: - - ReplaceMain - _connectionOnly: 1 - _automaticallyUnload: 1 - _onTriggerEnter: 1 ---- !u!4 &979031081727779170 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 979031081727779174} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 2.87, y: -3, z: 0} - m_LocalScale: {x: 15, y: 15, z: 15} - m_Children: [] - m_Father: {fileID: 603255274} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &979031081727779171 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 979031081727779174} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &979031081727779172 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 979031081727779174} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 2e7517d1496ae784f94a2307a88e2bb5, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!135 &979031081727779173 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 979031081727779174} - m_Material: {fileID: 0} - m_IsTrigger: 1 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!1 &979031081727779174 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 979031081727779170} - - component: {fileID: 979031081727779169} - - component: {fileID: 979031081727779171} - - component: {fileID: 979031081727779172} - - component: {fileID: 979031081727779173} - m_Layer: 0 - m_Name: Connection - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceConnection.unity.meta b/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceConnection.unity.meta deleted file mode 100644 index 0eb3735..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceConnection.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 58053e81b62de3a499afaf0f73d01b01 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceGlobal.unity b/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceGlobal.unity deleted file mode 100644 index 4181a2f..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceGlobal.unity +++ /dev/null @@ -1,724 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 256 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 1 - m_PVRDenoiserTypeDirect: 1 - m_PVRDenoiserTypeIndirect: 1 - m_PVRDenoiserTypeAO: 1 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 1 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_UseShadowmask: 1 ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &1808099118 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1808099119} - - component: {fileID: 1808099124} - - component: {fileID: 1808099123} - - component: {fileID: 1808099122} - - component: {fileID: 1808099120} - m_Layer: 0 - m_Name: SphereChild - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1808099119 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1808099118} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -0.637, z: 0} - m_LocalScale: {x: 0.5, y: 0.5, z: 0.5} - m_Children: [] - m_Father: {fileID: 1950515031} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &1808099120 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1808099118} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkObserver: {fileID: 0} - k__BackingField: 65535 - k__BackingField: 0 - _scenePathHash: 3074121493 - k__BackingField: 13203251279664725889 - k__BackingField: 0 - _sceneNetworkObjects: - - {fileID: 1808099120} - - {fileID: 1950515032} - k__BackingField: 1 - k__BackingField: 1 - k__BackingField: {fileID: 0} - _networkBehaviours: [] - k__BackingField: {fileID: 1950515032} - k__BackingField: [] - _isNetworked: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 ---- !u!135 &1808099122 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1808099118} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1808099123 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1808099118} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1808099124 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1808099118} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!1 &1950515027 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1950515031} - - component: {fileID: 1950515030} - - component: {fileID: 1950515029} - - component: {fileID: 1950515028} - - component: {fileID: 1950515033} - - component: {fileID: 1950515032} - m_Layer: 0 - m_Name: Sphere - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &1950515028 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1950515027} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1950515029 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1950515027} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1950515030 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1950515027} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &1950515031 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1950515027} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 24.31, y: 3, z: -5.47} - m_LocalScale: {x: 4, y: 4, z: 4} - m_Children: - - {fileID: 1808099119} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &1950515032 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1950515027} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 26b716c41e9b56b4baafaf13a523ba2e, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkObserver: {fileID: 0} - k__BackingField: 65535 - k__BackingField: 0 - _scenePathHash: 3074121493 - k__BackingField: 13203251279314293806 - k__BackingField: 0 - _sceneNetworkObjects: - - {fileID: 1808099120} - - {fileID: 1950515032} - k__BackingField: 0 - k__BackingField: 0 - k__BackingField: {fileID: 0} - _networkBehaviours: [] - k__BackingField: {fileID: 0} - k__BackingField: - - {fileID: 1808099120} - _isNetworked: 1 - _isGlobal: 0 - _initializeOrder: 0 - _defaultDespawnType: 0 ---- !u!114 &1950515033 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1950515027} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c71fd7f855ec523429999fc4e14a1928, type: 3} - m_Name: - m_EditorClassIdentifier: - _overrideType: 3 - _updateHostVisibility: 1 - _observerConditions: - - {fileID: 11400000, guid: 2033f54fd2794464bae08fa5a55c8996, type: 2} ---- !u!1 &1722183419489630397 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1722183419489630399} - - component: {fileID: 1722183419489630398} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!108 &1722183419489630398 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1722183419489630397} - m_Enabled: 1 - serializedVersion: 10 - m_Type: 1 - m_Shape: 0 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 1 - m_LightShadowCasterMode: 0 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 0 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_ShadowRadius: 0 - m_ShadowAngle: 0 ---- !u!4 &1722183419489630399 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1722183419489630397} - m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: -2.2843354, y: 60.72741, z: -2.9938574} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 1722183420925353816} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!33 &1722183420764669584 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1722183420764669589} - m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &1722183420764669585 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1722183420764669589} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -5, z: 0} - m_LocalScale: {x: 10, y: 10, z: 10} - m_Children: [] - m_Father: {fileID: 1722183420925353816} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1722183420764669589 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1722183420764669585} - - component: {fileID: 1722183420764669584} - - component: {fileID: 1722183420764669591} - - component: {fileID: 1722183420764669590} - m_Layer: 0 - m_Name: Plane - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!64 &1722183420764669590 -MeshCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1722183420764669589} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 4 - m_Convex: 0 - m_CookingOptions: 30 - m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &1722183420764669591 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1722183420764669589} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!4 &1722183420925353816 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1722183420925353823} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 1722183419489630399} - - {fileID: 1722183420764669585} - m_Father: {fileID: 0} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1722183420925353823 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1722183420925353816} - m_Layer: 0 - m_Name: Scene - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!1 &5581392219061976576 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 5581392219061976826} - - component: {fileID: 5581392219061976581} - - component: {fileID: 5581392219061976583} - - component: {fileID: 5581392219061976582} - - component: {fileID: 5581392219061976577} - m_Layer: 0 - m_Name: Global - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &5581392219061976577 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5581392219061976576} - m_Material: {fileID: 0} - m_IsTrigger: 1 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!114 &5581392219061976581 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5581392219061976576} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fa23b6e6f9b08d74885e3707aa0d9bc7, type: 3} - m_Name: - m_EditorClassIdentifier: - _moveObject: 0 - _moveAllObjects: 1 - _replaceOption: 0 - _scenes: - - ReplaceMain - _connectionOnly: 0 - _automaticallyUnload: 1 - _onTriggerEnter: 1 ---- !u!23 &5581392219061976582 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5581392219061976576} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 2e7517d1496ae784f94a2307a88e2bb5, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &5581392219061976583 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5581392219061976576} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &5581392219061976826 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5581392219061976576} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 30.66, y: -3, z: -1.24} - m_LocalScale: {x: 15, y: 15, z: 15} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceGlobal.unity.meta b/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceGlobal.unity.meta deleted file mode 100644 index 58f62b6..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceGlobal.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: fddd81e62368fe9448b0eb0a80da6bb4 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceMain.unity b/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceMain.unity deleted file mode 100644 index 08ea094..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceMain.unity +++ /dev/null @@ -1,1271 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 705507994} - m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 500 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 500 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 2 - m_PVRDenoiserTypeDirect: 0 - m_PVRDenoiserTypeIndirect: 0 - m_PVRDenoiserTypeAO: 0 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 0 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_UseShadowmask: 1 ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &40691391 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 40691392} - m_Layer: 0 - m_Name: Triggers - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &40691392 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 40691391} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 825925885} - - {fileID: 1406093440} - m_Father: {fileID: 0} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &705507993 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 705507995} - - component: {fileID: 705507994} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!108 &705507994 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 705507993} - m_Enabled: 1 - serializedVersion: 10 - m_Type: 1 - m_Shape: 0 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 1 - m_LightShadowCasterMode: 0 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 0 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_ShadowRadius: 0 - m_ShadowAngle: 0 ---- !u!4 &705507995 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 705507993} - m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: -2.2843354, y: 60.72741, z: -2.9938574} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 1155569020} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!1 &825925881 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 825925885} - - component: {fileID: 825925886} - - component: {fileID: 825925884} - - component: {fileID: 825925883} - - component: {fileID: 825925882} - m_Layer: 0 - m_Name: Connection - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &825925882 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 825925881} - m_Material: {fileID: 0} - m_IsTrigger: 1 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &825925883 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 825925881} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: d0a99caade0a68842b2274726d1bc7c3, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &825925884 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 825925881} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &825925885 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 825925881} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -2.4611313, y: -3, z: 2.2759757} - m_LocalScale: {x: 15, y: 15, z: 15} - m_Children: [] - m_Father: {fileID: 40691392} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &825925886 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 825925881} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fa23b6e6f9b08d74885e3707aa0d9bc7, type: 3} - m_Name: - m_EditorClassIdentifier: - _moveObject: 1 - _moveAllObjects: 0 - _replaceOption: 0 - _scenes: - - ReplaceConnection - _connectionOnly: 1 - _automaticallyUnload: 1 - _onTriggerEnter: 1 ---- !u!1 &1155569019 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1155569020} - m_Layer: 0 - m_Name: Scene - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1155569020 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1155569019} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 705507995} - - {fileID: 2114768053} - m_Father: {fileID: 0} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1406093434 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1406093440} - - component: {fileID: 1406093439} - - component: {fileID: 1406093437} - - component: {fileID: 1406093436} - - component: {fileID: 1406093435} - m_Layer: 0 - m_Name: Global - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!135 &1406093435 -SphereCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1406093434} - m_Material: {fileID: 0} - m_IsTrigger: 1 - m_Enabled: 1 - serializedVersion: 2 - m_Radius: 0.5 - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &1406093436 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1406093434} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: a35bce0c956282a42a90a04b25492fb6, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &1406093437 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1406093434} - m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} ---- !u!114 &1406093439 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1406093434} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fa23b6e6f9b08d74885e3707aa0d9bc7, type: 3} - m_Name: - m_EditorClassIdentifier: - _moveObject: 0 - _moveAllObjects: 1 - _replaceOption: 1 - _scenes: - - ReplaceGlobal - _connectionOnly: 0 - _automaticallyUnload: 1 - _onTriggerEnter: 1 ---- !u!4 &1406093440 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1406093434} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 13.88, y: -3, z: 2.2759757} - m_LocalScale: {x: 15, y: 15, z: 15} - m_Children: [] - m_Father: {fileID: 40691392} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &2114768049 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2114768053} - - component: {fileID: 2114768052} - - component: {fileID: 2114768051} - - component: {fileID: 2114768050} - m_Layer: 0 - m_Name: Plane - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!64 &2114768050 -MeshCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2114768049} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 4 - m_Convex: 0 - m_CookingOptions: 30 - m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &2114768051 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2114768049} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 ---- !u!33 &2114768052 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2114768049} - m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &2114768053 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2114768049} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -5, z: 0} - m_LocalScale: {x: 10, y: 10, z: 10} - m_Children: [] - m_Father: {fileID: 1155569020} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &1357903939251608625 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2553749094314996952} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2b3dca501a9d8c8479dc71dd068aa8b8, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!1 &2553749094314996952 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 9208822351047973834} - - component: {fileID: 6666759449596494018} - - component: {fileID: 1357903939251608625} - m_Layer: 5 - m_Name: Indicator - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &3896340524768297019 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4875127092859136454} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2b3dca501a9d8c8479dc71dd068aa8b8, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!114 &4462211894441225126 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4462211894441225131} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2d50394614f8feb4eb0567fb7618d84d, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!222 &4462211894441225127 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4462211894441225131} - m_CullTransparentMesh: 0 ---- !u!224 &4462211894441225128 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4462211894441225131} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 9208822351047973834} - m_Father: {fileID: 4462211894982264461} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 16, y: -96} - m_SizeDelta: {x: 256, y: 64} - m_Pivot: {x: 0, y: 1} ---- !u!114 &4462211894441225129 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4462211894441225131} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 3 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Selected - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 4462211894441225126} - m_OnClick: - m_PersistentCalls: - m_Calls: - - m_Target: {fileID: 4462211894982264465} - m_MethodName: OnClick_Client - m_Mode: 1 - m_Arguments: - m_ObjectArgument: {fileID: 0} - m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine - m_IntArgument: 0 - m_FloatArgument: 0 - m_StringArgument: - m_BoolArgument: 0 - m_CallState: 2 ---- !u!1 &4462211894441225131 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4462211894441225128} - - component: {fileID: 4462211894441225127} - - component: {fileID: 4462211894441225126} - - component: {fileID: 4462211894441225129} - m_Layer: 5 - m_Name: Client - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &4462211894961511974 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4462211894961511979} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 1b187e63031bf7849b249c8212440c3b, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!222 &4462211894961511975 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4462211894961511979} - m_CullTransparentMesh: 0 ---- !u!224 &4462211894961511976 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4462211894961511979} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 7312354082057744424} - m_Father: {fileID: 4462211894982264461} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 16, y: -16} - m_SizeDelta: {x: 256, y: 64} - m_Pivot: {x: 0, y: 1} ---- !u!114 &4462211894961511977 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4462211894961511979} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 3 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Selected - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 4462211894961511974} - m_OnClick: - m_PersistentCalls: - m_Calls: - - m_Target: {fileID: 4462211894982264465} - m_MethodName: OnClick_Server - m_Mode: 1 - m_Arguments: - m_ObjectArgument: {fileID: 0} - m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine - m_IntArgument: 0 - m_FloatArgument: 0 - m_StringArgument: - m_BoolArgument: 0 - m_CallState: 2 ---- !u!1 &4462211894961511979 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4462211894961511976} - - component: {fileID: 4462211894961511975} - - component: {fileID: 4462211894961511974} - - component: {fileID: 4462211894961511977} - m_Layer: 5 - m_Name: Server - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!223 &4462211894982264460 -Canvas: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4462211894982264464} - m_Enabled: 1 - serializedVersion: 3 - m_RenderMode: 0 - m_Camera: {fileID: 0} - m_PlaneDistance: 100 - m_PixelPerfect: 0 - m_ReceivesEvents: 1 - m_OverrideSorting: 0 - m_OverridePixelPerfect: 0 - m_SortingBucketNormalizedSize: 0 - m_AdditionalShaderChannelsFlag: 0 - m_SortingLayerID: 0 - m_SortingOrder: 0 - m_TargetDisplay: 0 ---- !u!224 &4462211894982264461 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4462211894982264464} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0, y: 0, z: 0} - m_Children: - - {fileID: 4462211894961511976} - - {fileID: 4462211894441225128} - m_Father: {fileID: 7443408887680269496} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0, y: 0} ---- !u!114 &4462211894982264462 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4462211894982264464} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} - m_Name: - m_EditorClassIdentifier: - m_IgnoreReversedGraphics: 1 - m_BlockingObjects: 0 - m_BlockingMask: - serializedVersion: 2 - m_Bits: 4294967295 ---- !u!114 &4462211894982264463 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4462211894982264464} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} - m_Name: - m_EditorClassIdentifier: - m_UiScaleMode: 1 - m_ReferencePixelsPerUnit: 100 - m_ScaleFactor: 1 - m_ReferenceResolution: {x: 1920, y: 1080} - m_ScreenMatchMode: 0 - m_MatchWidthOrHeight: 0.5 - m_PhysicalUnit: 3 - m_FallbackScreenDPI: 96 - m_DefaultSpriteDPI: 96 - m_DynamicPixelsPerUnit: 1 ---- !u!1 &4462211894982264464 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4462211894982264461} - - component: {fileID: 4462211894982264460} - - component: {fileID: 4462211894982264465} - - component: {fileID: 4462211894982264463} - - component: {fileID: 4462211894982264462} - m_Layer: 5 - m_Name: NetworkHudCanvas - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &4462211894982264465 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4462211894982264464} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6d3606bfdac5a4743890fc1a5ecd8f24, type: 3} - m_Name: - m_EditorClassIdentifier: - _autoStartType: 2 - _stoppedColor: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - _changingColor: {r: 0.78431374, g: 0.6862745, b: 0, a: 1} - _startedColor: {r: 0, g: 0.5882353, b: 0.64705884, a: 1} - _serverIndicator: {fileID: 3896340524768297019} - _clientIndicator: {fileID: 1357903939251608625} ---- !u!1 &4875127092859136454 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7312354082057744424} - - component: {fileID: 5173910453633412161} - - component: {fileID: 3896340524768297019} - m_Layer: 5 - m_Name: Indicator - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!222 &5173910453633412161 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4875127092859136454} - m_CullTransparentMesh: 0 ---- !u!222 &6666759449596494018 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2553749094314996952} - m_CullTransparentMesh: 0 ---- !u!224 &7312354082057744424 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4875127092859136454} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -1} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 4462211894961511976} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &7443408887680269493 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887680269498} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 211a9f6ec51ddc14f908f5acc0cd0423, type: 3} - m_Name: - m_EditorClassIdentifier: - _playerPrefab: {fileID: 611616139817875448, guid: bf5f023b4017a5e41a9815ec5745df3d, - type: 3} - _addToDefaultScene: 0 - Spawns: [] ---- !u!4 &7443408887680269496 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887680269498} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 4462211894982264461} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &7443408887680269498 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7443408887680269496} - - component: {fileID: 7443408887680269499} - - component: {fileID: 7443408887680269493} - - component: {fileID: 7443408887680269500} - - component: {fileID: 7443408887680269501} - - component: {fileID: 7443408887680269502} - - component: {fileID: 7443408887680269503} - m_Layer: 0 - m_Name: 'NetworkManager ' - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &7443408887680269499 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887680269498} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d2c95dfde7d73b54dbbdc23155d35d36, type: 3} - m_Name: - m_EditorClassIdentifier: - _logging: {fileID: 0} - _spawnablePrefabs: {fileID: 11400000, guid: 3a54436bdb916194f99da0d17231e617, type: 2} - _refreshDefaultPrefabs: 1 - _runInBackground: 1 - _dontDestroyOnLoad: 1 - _objectPool: {fileID: 0} - _persistence: 0 ---- !u!114 &7443408887680269500 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887680269498} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 3fdaae44044276a49a52229c1597e33b, type: 3} - m_Name: - m_EditorClassIdentifier: - _updateOrder: 0 - _timingType: 0 - _allowTickDropping: 0 - _maximumFrameTicks: 2 - _tickRate: 30 - _pingInterval: 1 - _timingInterval: 2 - _physicsMode: 0 ---- !u!114 &7443408887680269501 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887680269498} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6f48f002b825cbd45a19bd96d90f9edb, type: 3} - m_Name: - m_EditorClassIdentifier: - _unreliableMTU: 1023 - _ipv4BindAddress: - _ipv6BindAddress: - _port: 7770 - _maximumClients: 4095 - _clientAddress: localhost - _timeout: 15 ---- !u!114 &7443408887680269502 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887680269498} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 15895a51081447d46bda466e7e830c08, type: 3} - m_Name: - m_EditorClassIdentifier: - _sceneProcessor: {fileID: 0} - _lightProbeUpdating: 0 - _moveClientHostObjects: 1 - _setActiveScene: 1 ---- !u!114 &7443408887680269503 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887680269498} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 7d331f979d46e8e4a9fc90070c596d44, type: 3} - m_Name: - m_EditorClassIdentifier: - _useNetworkLod: 0 - _levelOfDetailDistances: [] - _updateHostVisibility: 1 - _defaultConditions: [] ---- !u!224 &9208822351047973834 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2553749094314996952} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -1} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 4462211894441225128} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0.5, y: 0.5} diff --git a/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceMain.unity.meta b/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceMain.unity.meta deleted file mode 100644 index 5276e6e..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scenes/Replace/ReplaceMain.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 099398b014b86004abd99a7d21cf417a -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Scripts.meta b/Assets/FishNet/Example/All/SceneManager/Scripts.meta deleted file mode 100644 index 83ffc63..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scripts.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 237bdcd1cdb63df4089e95bd92e1c69e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Scripts/PlayerController.cs b/Assets/FishNet/Example/All/SceneManager/Scripts/PlayerController.cs deleted file mode 100644 index 81d8594..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scripts/PlayerController.cs +++ /dev/null @@ -1,75 +0,0 @@ -using FishNet.Connection; -using FishNet.Object; -using UnityEngine; - -namespace FishNet.Example.Scened -{ - - - public class PlayerController : NetworkBehaviour - { - [SerializeField] - private GameObject _camera; - [SerializeField] - private float _moveRate = 4f; - [SerializeField] - private bool _clientAuth = true; - - public override void OnStartClient() - { - base.OnStartClient(); - if (base.IsOwner) - _camera.SetActive(true); - } - - private void Update() - { - if (!base.IsOwner) - return; - - float hor = Input.GetAxisRaw("Horizontal"); - float ver = Input.GetAxisRaw("Vertical"); - - /* If ground cannot be found for 20 units then bump up 3 units. - * This is just to keep player on ground if they fall through - * when changing scenes. */ - if (_clientAuth || (!_clientAuth && base.IsServer)) - { - if (!Physics.Linecast(transform.position + new Vector3(0f, 0.3f, 0f), transform.position - (Vector3.one * 20f))) - transform.position += new Vector3(0f, 3f, 0f); - } - - if (_clientAuth) - Move(hor, ver); - else - ServerMove(hor, ver); - } - - [ServerRpc] - private void ServerMove(float hor, float ver) - { - Move(hor, ver); - } - - private void Move(float hor, float ver) - { - float gravity = -10f * Time.deltaTime; - //If ray hits floor then cancel gravity. - Ray ray = new Ray(transform.position + new Vector3(0f, 0.05f, 0f), -Vector3.up); - if (Physics.Raycast(ray, 0.1f + -gravity)) - gravity = 0f; - - /* Moving. */ - Vector3 direction = new Vector3( - 0f, - gravity, - ver * _moveRate * Time.deltaTime); - - transform.position += transform.TransformDirection(direction); - transform.Rotate(new Vector3(0f, hor * 100f * Time.deltaTime, 0f)); - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Example/All/SceneManager/Scripts/PlayerController.cs.meta b/Assets/FishNet/Example/All/SceneManager/Scripts/PlayerController.cs.meta deleted file mode 100644 index cbdc08d..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scripts/PlayerController.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 26e4f626a9ca9704f9befe7673a8dd15 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Scripts/SceneLoaderExample.cs b/Assets/FishNet/Example/All/SceneManager/Scripts/SceneLoaderExample.cs deleted file mode 100644 index 9569eef..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scripts/SceneLoaderExample.cs +++ /dev/null @@ -1,148 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing.Logging; -using FishNet.Managing.Scened; -using FishNet.Object; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.Example.Scened -{ - - ///

- /// Loads a single scene, additive scenes, or both when a client - /// enters or exits this trigger. - /// - public class SceneLoaderExample : MonoBehaviour - { - /// - /// True to move the triggering object. - /// - [Tooltip("True to move the triggering object.")] - [SerializeField] - private bool _moveObject = true; - /// - /// True to move all connection objects (clients). - /// - [Tooltip("True to move all connection objects (clients).")] - [SerializeField] - private bool _moveAllObjects; - /// - /// True to replace current scenes with new scenes. First scene loaded will become active scene. - /// - [Tooltip("True to replace current scenes with new scenes. First scene loaded will become active scene.")] - [SerializeField] - private ReplaceOption _replaceOption = ReplaceOption.None; - /// - /// Scenes to load. - /// - [Tooltip("Scenes to load.")] - [SerializeField] - private string[] _scenes = new string[0]; - /// - /// True to only unload for the connectioning causing the trigger. - /// - [Tooltip("True to only unload for the connectioning causing the trigger.")] - [SerializeField] - private bool _connectionOnly; - /// - /// True to automatically unload the loaded scenes when no more connections are using them. - /// - [Tooltip("True to automatically unload the loaded scenes when no more connections are using them.")] - [SerializeField] - private bool _automaticallyUnload = true; - /// - /// True to fire when entering the trigger. False to fire when exiting the trigger. - /// - [Tooltip("True to fire when entering the trigger. False to fire when exiting the trigger.")] - [SerializeField] - private bool _onTriggerEnter = true; - - /// - /// Used to prevent excessive triggering when two clients are loaded and server is separate. - /// Client may enter trigger intentionally then when moved to a new scene will re-enter trigger - /// since original scene will still be loaded on server due to another client being in it. - /// This scenario is extremely unlikely in production but keep it in mind. - /// - private Dictionary _triggeredTimes = new Dictionary(); - - - [Server(Logging = LoggingType.Off)] - private void OnTriggerEnter(Collider other) - { - if (!_onTriggerEnter) - return; - - LoadScene(other.GetComponent()); - } - - [Server(Logging = LoggingType.Off)] - private void OnTriggerExit(Collider other) - { - if (_onTriggerEnter) - return; - - LoadScene(other.GetComponent()); - } - - private void LoadScene(NetworkObject triggeringIdentity) - { - if (!InstanceFinder.NetworkManager.IsServer) - return; - - //NetworkObject isn't necessarily needed but to ensure its the player only run if found. - if (triggeringIdentity == null) - return; - - /* Dont let trigger hit twice by same connection too frequently - * See _triggeredTimes field for more info. */ - if (_triggeredTimes.TryGetValue(triggeringIdentity.Owner, out float time)) - { - if (Time.time - time < 0.5f) - return; - } - _triggeredTimes[triggeringIdentity.Owner] = Time.time; - - //Which objects to move. - List movedObjects = new List(); - if (_moveAllObjects) - { - foreach (NetworkConnection item in InstanceFinder.ServerManager.Clients.Values) - { - foreach (NetworkObject nob in item.Objects) - movedObjects.Add(nob); - } - } - else if (_moveObject) - { - movedObjects.Add(triggeringIdentity); - } - //Load options. - LoadOptions loadOptions = new LoadOptions - { - AutomaticallyUnload = _automaticallyUnload, - }; - - //Make scene data. - SceneLoadData sld = new SceneLoadData(_scenes); - sld.PreferredActiveScene = sld.SceneLookupDatas[0]; - sld.ReplaceScenes = _replaceOption; - sld.Options = loadOptions; - sld.MovedNetworkObjects = movedObjects.ToArray(); - - //Load for connection only. - if (_connectionOnly) - InstanceFinder.SceneManager.LoadConnectionScenes(triggeringIdentity.Owner, sld); - //Load for all clients. - else - InstanceFinder.SceneManager.LoadGlobalScenes(sld); - - - } - - - } - - - - -} \ No newline at end of file diff --git a/Assets/FishNet/Example/All/SceneManager/Scripts/SceneLoaderExample.cs.meta b/Assets/FishNet/Example/All/SceneManager/Scripts/SceneLoaderExample.cs.meta deleted file mode 100644 index ee3fa3f..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scripts/SceneLoaderExample.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fa23b6e6f9b08d74885e3707aa0d9bc7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/All/SceneManager/Scripts/SceneUnloaderExample.cs b/Assets/FishNet/Example/All/SceneManager/Scripts/SceneUnloaderExample.cs deleted file mode 100644 index 67c5af8..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scripts/SceneUnloaderExample.cs +++ /dev/null @@ -1,91 +0,0 @@ -using FishNet.Managing.Logging; -using FishNet.Managing.Scened; -using FishNet.Object; -using UnityEngine; - -namespace FishNet.Example.Scened -{ - - /// - /// Unloads specified scenes when entering or exiting this trigger. - /// - public class SceneUnloaderExample : MonoBehaviour - { - /// - /// Scenes to unload. - /// - [Tooltip("Scenes to unload.")] - [SerializeField] - private string[] _scenes = new string[0]; - /// - /// True to only unload for the connectioning causing the trigger. - /// - [Tooltip("True to only unload for the connectioning causing the trigger.")] - [SerializeField] - private bool _connectionOnly; - /// - /// True to unload unused scenes. - /// - [Tooltip("True to unload unused scenes.")] - [SerializeField] - private bool _unloadUnused = true; - /// - /// True to fire when entering the trigger. False to fire when exiting the trigger. - /// - [Tooltip("True to fire when entering the trigger. False to fire when exiting the trigger.")] - [SerializeField] - private bool _onTriggerEnter = true; - - - [Server(Logging = LoggingType.Off)] - private void OnTriggerEnter(Collider other) - { - if (!_onTriggerEnter) - return; - - UnloadScenes(other.gameObject.GetComponent()); - } - - [Server(Logging = LoggingType.Off)] - private void OnTriggerExit(Collider other) - { - if (_onTriggerEnter) - return; - - UnloadScenes(other.gameObject.GetComponent()); - } - - /// - /// Unload scenes. - /// - /// - private void UnloadScenes(NetworkObject triggeringIdentity) - { - if (!InstanceFinder.NetworkManager.IsServer) - return; - - //NetworkObject isn't necessarily needed but to ensure its the player only run if nob is found. - if (triggeringIdentity == null) - return; - - UnloadOptions unloadOptions = new UnloadOptions() - { - Mode = (_unloadUnused) ? UnloadOptions.ServerUnloadMode.UnloadUnused : UnloadOptions.ServerUnloadMode.KeepUnused - }; - - SceneUnloadData sud = new SceneUnloadData(_scenes); - sud.Options = unloadOptions; - - //Unload only for the triggering connection. - if (_connectionOnly) - InstanceFinder.SceneManager.UnloadConnectionScenes(triggeringIdentity.Owner, sud); - //Unload for all players. - else - InstanceFinder.SceneManager.UnloadGlobalScenes(sud); - } - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Example/All/SceneManager/Scripts/SceneUnloaderExample.cs.meta b/Assets/FishNet/Example/All/SceneManager/Scripts/SceneUnloaderExample.cs.meta deleted file mode 100644 index ba09def..0000000 --- a/Assets/FishNet/Example/All/SceneManager/Scripts/SceneUnloaderExample.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 84ae572fef1171b41ab287d1c9b5da63 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/FishNet.Example.asmdef b/Assets/FishNet/Example/FishNet.Example.asmdef deleted file mode 100644 index dd0e8cf..0000000 --- a/Assets/FishNet/Example/FishNet.Example.asmdef +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "FishNet.Example", - "references": [ - "GUID:7c88a4a7926ee5145ad2dfa06f454c67" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} \ No newline at end of file diff --git a/Assets/FishNet/Example/FishNet.Example.asmdef.meta b/Assets/FishNet/Example/FishNet.Example.asmdef.meta deleted file mode 100644 index 8b6f01d..0000000 --- a/Assets/FishNet/Example/FishNet.Example.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: a5e44165775d9294ba486f89d4c07300 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/Prefabs.meta b/Assets/FishNet/Example/Prefabs.meta deleted file mode 100644 index b4d5992..0000000 --- a/Assets/FishNet/Example/Prefabs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 9d9b597402966d8498f81aa39427f47a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/Prefabs/NetworkHudCanvas.prefab b/Assets/FishNet/Example/Prefabs/NetworkHudCanvas.prefab deleted file mode 100644 index a0288e4..0000000 --- a/Assets/FishNet/Example/Prefabs/NetworkHudCanvas.prefab +++ /dev/null @@ -1,529 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &2480283714602906875 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 9139860296052841449} - - component: {fileID: 6745855428185604321} - - component: {fileID: 1424052073409502226} - m_Layer: 5 - m_Name: Indicator - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &9139860296052841449 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2480283714602906875} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -1} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 4393252311501663115} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!222 &6745855428185604321 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2480283714602906875} - m_CullTransparentMesh: 0 ---- !u!114 &1424052073409502226 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2480283714602906875} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2b3dca501a9d8c8479dc71dd068aa8b8, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!1 &4393252310969058995 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4393252310969058990} - - component: {fileID: 4393252310969058994} - - component: {fileID: 4393252310969058991} - - component: {fileID: 4393252310969058988} - - component: {fileID: 4393252310969058989} - m_Layer: 5 - m_Name: NetworkHudCanvas - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &4393252310969058990 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252310969058995} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0, y: 0, z: 0} - m_Children: - - {fileID: 4393252311652982283} - - {fileID: 4393252311501663115} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0, y: 0} ---- !u!114 &4393252310969058994 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252310969058995} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6d3606bfdac5a4743890fc1a5ecd8f24, type: 3} - m_Name: - m_EditorClassIdentifier: - AutoStart: 0 - _stoppedColor: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - _changingColor: {r: 0.78431374, g: 0.6862745, b: 0, a: 1} - _startedColor: {r: 0, g: 0.5882353, b: 0.64705884, a: 1} - _serverIndicator: {fileID: 3965864433427628056} - _clientIndicator: {fileID: 1424052073409502226} ---- !u!223 &4393252310969058991 -Canvas: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252310969058995} - m_Enabled: 1 - serializedVersion: 3 - m_RenderMode: 0 - m_Camera: {fileID: 0} - m_PlaneDistance: 100 - m_PixelPerfect: 0 - m_ReceivesEvents: 1 - m_OverrideSorting: 0 - m_OverridePixelPerfect: 0 - m_SortingBucketNormalizedSize: 0 - m_AdditionalShaderChannelsFlag: 0 - m_SortingLayerID: 0 - m_SortingOrder: 0 - m_TargetDisplay: 0 ---- !u!114 &4393252310969058988 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252310969058995} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} - m_Name: - m_EditorClassIdentifier: - m_UiScaleMode: 1 - m_ReferencePixelsPerUnit: 100 - m_ScaleFactor: 1 - m_ReferenceResolution: {x: 1920, y: 1080} - m_ScreenMatchMode: 0 - m_MatchWidthOrHeight: 0.5 - m_PhysicalUnit: 3 - m_FallbackScreenDPI: 96 - m_DefaultSpriteDPI: 96 - m_DynamicPixelsPerUnit: 1 ---- !u!114 &4393252310969058989 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252310969058995} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} - m_Name: - m_EditorClassIdentifier: - m_IgnoreReversedGraphics: 1 - m_BlockingObjects: 0 - m_BlockingMask: - serializedVersion: 2 - m_Bits: 4294967295 ---- !u!1 &4393252311501663112 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4393252311501663115} - - component: {fileID: 4393252311501663108} - - component: {fileID: 4393252311501663109} - - component: {fileID: 4393252311501663114} - m_Layer: 5 - m_Name: Client - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &4393252311501663115 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311501663112} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 9139860296052841449} - m_Father: {fileID: 4393252310969058990} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 16, y: -96} - m_SizeDelta: {x: 256, y: 64} - m_Pivot: {x: 0, y: 1} ---- !u!222 &4393252311501663108 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311501663112} - m_CullTransparentMesh: 0 ---- !u!114 &4393252311501663109 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311501663112} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2d50394614f8feb4eb0567fb7618d84d, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!114 &4393252311501663114 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311501663112} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 3 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Selected - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 4393252311501663109} - m_OnClick: - m_PersistentCalls: - m_Calls: - - m_Target: {fileID: 4393252310969058994} - m_MethodName: OnClick_Client - m_Mode: 1 - m_Arguments: - m_ObjectArgument: {fileID: 0} - m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine - m_IntArgument: 0 - m_FloatArgument: 0 - m_StringArgument: - m_BoolArgument: 0 - m_CallState: 2 ---- !u!1 &4393252311652982280 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4393252311652982283} - - component: {fileID: 4393252311652982276} - - component: {fileID: 4393252311652982277} - - component: {fileID: 4393252311652982282} - m_Layer: 5 - m_Name: Server - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &4393252311652982283 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311652982280} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 7233259200663826443} - m_Father: {fileID: 4393252310969058990} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 16, y: -16} - m_SizeDelta: {x: 256, y: 64} - m_Pivot: {x: 0, y: 1} ---- !u!222 &4393252311652982276 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311652982280} - m_CullTransparentMesh: 0 ---- !u!114 &4393252311652982277 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311652982280} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 1b187e63031bf7849b249c8212440c3b, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!114 &4393252311652982282 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4393252311652982280} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Navigation: - m_Mode: 3 - m_SelectOnUp: {fileID: 0} - m_SelectOnDown: {fileID: 0} - m_SelectOnLeft: {fileID: 0} - m_SelectOnRight: {fileID: 0} - m_Transition: 1 - m_Colors: - m_NormalColor: {r: 1, g: 1, b: 1, a: 1} - m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} - m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} - m_ColorMultiplier: 1 - m_FadeDuration: 0.1 - m_SpriteState: - m_HighlightedSprite: {fileID: 0} - m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} - m_DisabledSprite: {fileID: 0} - m_AnimationTriggers: - m_NormalTrigger: Normal - m_HighlightedTrigger: Highlighted - m_PressedTrigger: Pressed - m_SelectedTrigger: Selected - m_DisabledTrigger: Disabled - m_Interactable: 1 - m_TargetGraphic: {fileID: 4393252311652982277} - m_OnClick: - m_PersistentCalls: - m_Calls: - - m_Target: {fileID: 4393252310969058994} - m_MethodName: OnClick_Server - m_Mode: 1 - m_Arguments: - m_ObjectArgument: {fileID: 0} - m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine - m_IntArgument: 0 - m_FloatArgument: 0 - m_StringArgument: - m_BoolArgument: 0 - m_CallState: 2 ---- !u!1 &4808982256197118437 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7233259200663826443} - - component: {fileID: 5104387649082666082} - - component: {fileID: 3965864433427628056} - m_Layer: 5 - m_Name: Indicator - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &7233259200663826443 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4808982256197118437} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -1} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 4393252311652982283} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!222 &5104387649082666082 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4808982256197118437} - m_CullTransparentMesh: 0 ---- !u!114 &3965864433427628056 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4808982256197118437} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.25490198, g: 0.25490198, b: 0.25490198, a: 1} - m_RaycastTarget: 1 - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 21300000, guid: 2b3dca501a9d8c8479dc71dd068aa8b8, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 - m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 diff --git a/Assets/FishNet/Example/Prefabs/NetworkHudCanvas.prefab.meta b/Assets/FishNet/Example/Prefabs/NetworkHudCanvas.prefab.meta deleted file mode 100644 index c4281bb..0000000 --- a/Assets/FishNet/Example/Prefabs/NetworkHudCanvas.prefab.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 0570b6f7f713dc44a90463654bbcd8d0 -PrefabImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/Prefabs/NetworkManager.prefab b/Assets/FishNet/Example/Prefabs/NetworkManager.prefab deleted file mode 100644 index 42b9e4e..0000000 --- a/Assets/FishNet/Example/Prefabs/NetworkManager.prefab +++ /dev/null @@ -1,190 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1 &7443408887813606051 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7443408887813606049} - - component: {fileID: 7443408887813606050} - - component: {fileID: 934570884} - - component: {fileID: 7443408887813606060} - m_Layer: 0 - m_Name: NetworkManager - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &7443408887813606049 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887813606051} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 4393252310584637084} - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &7443408887813606050 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887813606051} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d2c95dfde7d73b54dbbdc23155d35d36, type: 3} - m_Name: - m_EditorClassIdentifier: - _refreshDefaultPrefabs: 0 - _runInBackground: 1 - _dontDestroyOnLoad: 1 - _objectPool: {fileID: 0} - _persistence: 0 - _logging: {fileID: 0} - _spawnablePrefabs: {fileID: 11400000, guid: ec64eb18c93ab344892891f33edbf82a, type: 2} ---- !u!114 &934570884 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887813606051} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 7d331f979d46e8e4a9fc90070c596d44, type: 3} - m_Name: - m_EditorClassIdentifier: - _useNetworkLod: 0 - _levelOfDetailDistances: [] - _updateHostVisibility: 1 - _defaultConditions: - - {fileID: 11400000, guid: 2033f54fd2794464bae08fa5a55c8996, type: 2} ---- !u!114 &7443408887813606060 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7443408887813606051} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 211a9f6ec51ddc14f908f5acc0cd0423, type: 3} - m_Name: - m_EditorClassIdentifier: - _playerPrefab: {fileID: 0} - _addToDefaultScene: 1 - Spawns: [] ---- !u!1001 &2130063410 -PrefabInstance: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Modification: - m_TransformParent: {fileID: 7443408887813606049} - m_Modifications: - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_Pivot.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_Pivot.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_RootOrder - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_AnchorMax.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_AnchorMax.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_AnchorMin.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_AnchorMin.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_SizeDelta.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_SizeDelta.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalPosition.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalRotation.w - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalRotation.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalRotation.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalRotation.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_AnchoredPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_AnchoredPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalEulerAnglesHint.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalEulerAnglesHint.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_LocalEulerAnglesHint.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 4393252310969058995, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - propertyPath: m_Name - value: NetworkHudCanvas - objectReference: {fileID: 0} - m_RemovedComponents: [] - m_SourcePrefab: {fileID: 100100000, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} ---- !u!224 &4393252310584637084 stripped -RectTransform: - m_CorrespondingSourceObject: {fileID: 4393252310969058990, guid: 0570b6f7f713dc44a90463654bbcd8d0, type: 3} - m_PrefabInstance: {fileID: 2130063410} - m_PrefabAsset: {fileID: 0} diff --git a/Assets/FishNet/Example/Prefabs/NetworkManager.prefab.meta b/Assets/FishNet/Example/Prefabs/NetworkManager.prefab.meta deleted file mode 100644 index ae648e6..0000000 --- a/Assets/FishNet/Example/Prefabs/NetworkManager.prefab.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 0b650fca685f2eb41a86538aa883e4c1 -PrefabImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/Scripts.meta b/Assets/FishNet/Example/Scripts.meta deleted file mode 100644 index 4feee45..0000000 --- a/Assets/FishNet/Example/Scripts.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 7a4f0be731a103e4888691005f67a0e1 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Example/Scripts/NetworkHudCanvases.cs b/Assets/FishNet/Example/Scripts/NetworkHudCanvases.cs deleted file mode 100644 index bd11edf..0000000 --- a/Assets/FishNet/Example/Scripts/NetworkHudCanvases.cs +++ /dev/null @@ -1,248 +0,0 @@ -using FishNet.Managing; -using FishNet.Transporting; -using UnityEngine; -using UnityEngine.EventSystems; -using UnityEngine.UI; - -public class NetworkHudCanvases : MonoBehaviour -{ - #region Types. - /// - /// Ways the HUD will automatically start a connection. - /// - private enum AutoStartType - { - Disabled, - Host, - Server, - Client - } - #endregion - - #region Serialized. - /// - /// What connections to automatically start on play. - /// - [Tooltip("What connections to automatically start on play.")] - [SerializeField] - private AutoStartType _autoStartType = AutoStartType.Disabled; - /// - /// Color when socket is stopped. - /// - [Tooltip("Color when socket is stopped.")] - [SerializeField] - private Color _stoppedColor; - /// - /// Color when socket is changing. - /// - [Tooltip("Color when socket is changing.")] - [SerializeField] - private Color _changingColor; - /// - /// Color when socket is started. - /// - [Tooltip("Color when socket is started.")] - [SerializeField] - private Color _startedColor; - [Header("Indicators")] - /// - /// Indicator for server state. - /// - [Tooltip("Indicator for server state.")] - [SerializeField] - private Image _serverIndicator; - /// - /// Indicator for client state. - /// - [Tooltip("Indicator for client state.")] - [SerializeField] - private Image _clientIndicator; - #endregion - - #region Private. - /// - /// Found NetworkManager. - /// - private NetworkManager _networkManager; - /// - /// Current state of client socket. - /// - private LocalConnectionState _clientState = LocalConnectionState.Stopped; - /// - /// Current state of server socket. - /// - private LocalConnectionState _serverState = LocalConnectionState.Stopped; -#if !ENABLE_INPUT_SYSTEM - /// - /// EventSystem for the project. - /// - private EventSystem _eventSystem; -#endif - #endregion - - void OnGUI() - { -#if ENABLE_INPUT_SYSTEM - string GetNextStateText(LocalConnectionState state) - { - if (state == LocalConnectionState.Stopped) - return "Start"; - else if (state == LocalConnectionState.Starting) - return "Starting"; - else if (state == LocalConnectionState.Stopping) - return "Stopping"; - else if (state == LocalConnectionState.Started) - return "Stop"; - else - return "Invalid"; - } - - GUILayout.BeginArea(new Rect(16, 16, 256, 9000)); - Vector2 defaultResolution = new Vector2(1920f, 1080f); - GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(Screen.width / defaultResolution.x, Screen.height / defaultResolution.y, 1)); - - GUIStyle style = GUI.skin.GetStyle("button"); - int originalFontSize = style.fontSize; - - Vector2 buttonSize = new Vector2(256f, 64f); - style.fontSize = 28; - //Server button. - if (Application.platform != RuntimePlatform.WebGLPlayer) - { - if (GUILayout.Button($"{GetNextStateText(_serverState)} Server", GUILayout.Width(buttonSize.x), GUILayout.Height(buttonSize.y))) - OnClick_Server(); - GUILayout.Space(10f); - } - - //Client button. - if (GUILayout.Button($"{GetNextStateText(_clientState)} Client", GUILayout.Width(buttonSize.x), GUILayout.Height(buttonSize.y))) - OnClick_Client(); - - style.fontSize = originalFontSize; - - GUILayout.EndArea(); -#endif - } - - private void Start() - { -#if !ENABLE_INPUT_SYSTEM - SetEventSystem(); - BaseInputModule inputModule = FindObjectOfType(); - if (inputModule == null) - gameObject.AddComponent(); -#else - _serverIndicator.transform.parent.gameObject.SetActive(false); - _clientIndicator.transform.parent.gameObject.SetActive(false); -#endif - - _networkManager = FindObjectOfType(); - if (_networkManager == null) - { - Debug.LogError("NetworkManager not found, HUD will not function."); - return; - } - else - { - UpdateColor(LocalConnectionState.Stopped, ref _serverIndicator); - UpdateColor(LocalConnectionState.Stopped, ref _clientIndicator); - _networkManager.ServerManager.OnServerConnectionState += ServerManager_OnServerConnectionState; - _networkManager.ClientManager.OnClientConnectionState += ClientManager_OnClientConnectionState; - } - - if (_autoStartType == AutoStartType.Host || _autoStartType == AutoStartType.Server) - OnClick_Server(); - if (!Application.isBatchMode && (_autoStartType == AutoStartType.Host || _autoStartType == AutoStartType.Client)) - OnClick_Client(); - } - - - private void OnDestroy() - { - if (_networkManager == null) - return; - - _networkManager.ServerManager.OnServerConnectionState -= ServerManager_OnServerConnectionState; - _networkManager.ClientManager.OnClientConnectionState -= ClientManager_OnClientConnectionState; - } - - /// - /// Updates img color baased on state. - /// - /// - /// - private void UpdateColor(LocalConnectionState state, ref Image img) - { - Color c; - if (state == LocalConnectionState.Started) - c = _startedColor; - else if (state == LocalConnectionState.Stopped) - c = _stoppedColor; - else - c = _changingColor; - - img.color = c; - } - - - private void ClientManager_OnClientConnectionState(ClientConnectionStateArgs obj) - { - _clientState = obj.ConnectionState; - UpdateColor(obj.ConnectionState, ref _clientIndicator); - } - - - private void ServerManager_OnServerConnectionState(ServerConnectionStateArgs obj) - { - _serverState = obj.ConnectionState; - UpdateColor(obj.ConnectionState, ref _serverIndicator); - } - - - public void OnClick_Server() - { - if (_networkManager == null) - return; - - if (_serverState != LocalConnectionState.Stopped) - _networkManager.ServerManager.StopConnection(true); - else - _networkManager.ServerManager.StartConnection(); - - DeselectButtons(); - } - - - public void OnClick_Client() - { - if (_networkManager == null) - return; - - if (_clientState != LocalConnectionState.Stopped) - _networkManager.ClientManager.StopConnection(); - else - _networkManager.ClientManager.StartConnection(); - - DeselectButtons(); - } - - - private void SetEventSystem() - { -#if !ENABLE_INPUT_SYSTEM - if (_eventSystem != null) - return; - _eventSystem = FindObjectOfType(); - if (_eventSystem == null) - _eventSystem = gameObject.AddComponent(); -#endif - } - - private void DeselectButtons() - { -#if !ENABLE_INPUT_SYSTEM - SetEventSystem(); - _eventSystem?.SetSelectedGameObject(null); -#endif - } -} \ No newline at end of file diff --git a/Assets/FishNet/Example/Scripts/NetworkHudCanvases.cs.meta b/Assets/FishNet/Example/Scripts/NetworkHudCanvases.cs.meta deleted file mode 100644 index e2e25fb..0000000 --- a/Assets/FishNet/Example/Scripts/NetworkHudCanvases.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6d3606bfdac5a4743890fc1a5ecd8f24 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/LICENSE.txt b/Assets/FishNet/LICENSE.txt deleted file mode 100644 index a76aaf2..0000000 --- a/Assets/FishNet/LICENSE.txt +++ /dev/null @@ -1,35 +0,0 @@ -0. Definitions. - -"Fish-Net" means FishNet, FishNetworking, Fish-Networking, networking for Unity Engine. - -"Repository Service" means the respository service through which Fish-Net is made available. - -“Software” means the software (including code in source or object format as applicable) of Fish-Net that accompanies this License. - -"FirstGearGames" means Benjamin Berwick of FirstGearGames LLC, registered 2018, North Carolina. - -1. License Grant to the Software. FirstGearGames grants to you a worldwide, non-exclusive, no-charge, and royalty-free license to reproduce, modify, and use the Software for developed game, or other content with Software. - -1.1 Exclusions. Other products of like Software (eg: networking solutions) may not use, reverse engineer, or implement Software in part or full. Exclusions do not apply to parts of Software which are governed by a third-party license, nor to content or works created specifically to be used with Software, such as tools, add-ons, games, or improvements for Software. - -2. Trademarks. You are not granted any right or license under this License to use any trademarks, service marks, trade names, products names, or branding of FirstGearGames or its affiliates (“Trademarks”). - -3. Notice & Third-Party Terms. This License, including notices of copyright associated with the Software, must be provided in all substantial portions of the Software (or, if that is impracticable, in any other location where such notices are customarily placed). If the Software is accompanied by a “third-party notices” or similar file, you acknowledge and agree that software identified in that file is governed exclusively by those separate license terms. - -4. DISCLAIMER, LIMITATION OF LIABILITY. THE SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND IS PROVIDED WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR NONINFRINGEMENT. IN NO EVENT SHALL ANY COPYRIGHT HOLDER OR AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES (WHETHER DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL, INCLUDING PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF USE, DATA, OR PROFITS, AND BUSINESS INTERRUPTION), OR OTHER LIABILITY WHATSOEVER, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM OR OUT OF, OR IN CONNECTION WITH, THE SOFTWARE OR THE USE OF OR OTHER DEALINGS IN IT, EVEN WHERE ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -5. USE IS ACCEPTANCE and License Versions. Your access to and use of the Software, and/or any other indications of acceptance where required, constitutes your acceptance of this License and its terms and conditions. This License may be modified or updated; upon any such modification or update, you will comply with the terms of the updated License for any use of any of the Software under the updated License. - -6. Use in Compliance with Law and Termination. - -6.1 Compliance. Your exercise of the license granted herein will at all times be in compliance with applicable law and will not infringe any proprietary rights (including intellectual property rights). - -6.2 Termination. This License will terminate immediately (i) on any breach by you of this License; and (ii) if you commence any form of patent litigation, including a cross-claim or counterclaim, against anyone wherein you allege that the Software constitutes direct or secondary/indirect patent infringement. - -7. Severability. If any provision of this License is held to be unenforceable or invalid, that provision will be enforced to the maximum extent possible and the other provisions will remain in full force and effect. - -8. Governing Law and Venue. This License is governed by and construed in accordance with the laws of North Carolina, United States. You and FirstGearGames agree to submit to the personal and exclusive jurisdiction of and venue in the state and federal courts located in Onslow County, North Carolina concerning any dispute arising out of this License (“Dispute”). - -9. You agree by submitting ideas, modifications, or changes (content) of any kind to Software within Repository Service does not grant you ownership to Software nor additional rights to Software. - -9.1 By submitting to Repository Service you are granting FirstGearGames with a no-charge, and royalty-free license to reproduce, modify, and use submitted content. \ No newline at end of file diff --git a/Assets/FishNet/LICENSE.txt.meta b/Assets/FishNet/LICENSE.txt.meta deleted file mode 100644 index 5ba5b4f..0000000 --- a/Assets/FishNet/LICENSE.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 83c5a6d0014103d48a0028f0ab7fec8d -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Plugins/CodeAnalysis.meta b/Assets/FishNet/Plugins/CodeAnalysis.meta deleted file mode 100644 index a7fb576..0000000 --- a/Assets/FishNet/Plugins/CodeAnalysis.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 90f5de37ae0e3184fb0d662879ba060b -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Plugins/CodeAnalysis/FishNet.CodeAnalysis.Analyzers.dll b/Assets/FishNet/Plugins/CodeAnalysis/FishNet.CodeAnalysis.Analyzers.dll deleted file mode 100644 index c01e33044b2dd2d0ab48c0ca5717a60e789f6dc3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21504 zcmeHv3wRvWmFB6ces`;-ZdsDwv@ILjdLdbsZ4qOvm$8Cv*_L@@TY9U zoV0mNW|ELKiAh2}SPbO(C4`VnGCXGtW+%%>NbomdCJ)H+2pgCgNM?cWgJeIm|2b9F zU3%EOX7}6qc1!M4_ndp~x#ymH?zyLKb$ioghe;zM4?gd{OLRZ(e616BdQe1l^o$3i z^w+_s7TvFGd}`75J?UIx+%!hb)L3FTmCYLY#4bHy7P5(SHqkpUm>4rg^p=W>&=Onp zmOi45ibl^>effyf+w-(I5ms7J0gBI}er7N334Dt95LHQ8we)5J>o3Dg(A_jY>27XQKATF^T9WNYTfDZ1W~|M9{|3=g}3DO{dwR=F91ND zjMdf~m|O{>oh@e090n%36;a@UZpO!Tt;2M+n0m$lBkM{>@nKop@Nr%1h`L><6f z0Or8cuvpa&O2H9_3JhEry!IWA;b|~S;<#G%9OPQndr&H?TUF}75YTZf2D&{7mEt(>`Mb(1x{VoXnx%TdE$!YV)A4dFTs8 zjt4O{S%W$Q0LGo~GvX*rGpnaA{M%Ze5kp<`v%d}bntVP3HVi!rlR%z=vWk_STtOj- zg?x=Zj(ZUDJ+rn>>SB@AMOgEfdoi#mLQQ^;e`{T&)XzUn?uVV<>Zg*L*I4~jqaQ48 zMq(;fz{whTq2f!f1c^On74B#T+gg0#DSWGKzE0*_Z@b|+K$7BySmU$VU=L~r0#Hbs zW56jx+N_g4tW94It1wh|6NjdywTTDeH@6#Dl#S@Hy46n?Vh$1eVwIFU4~%)tp%MbJ z4u~&~RmiFalU+coJ#mldTEO%wVSlsI;7?Yf3$qRjBZ-*`H7O0gS#<^$YU9#o&zZ9t zy+$v{kpOrDMjs3D#eK>3T<|vb#l6Y%x#+h$jQI`3(-22OpLrDvtwpJ6K_z_>U3h#( zKi6WpH6{`ML&=Q*4G^*k_vRn?3^-=U7yzga#)HW%TnIFd#{w^HKD6*U~!a^{ymVVq-jd+~rm% zklYT&=1(KaN=s2biPhJ5kS9t_UW96~e}qz)cfQQ9LgVHf1`jfrtJ3(Kx>>X890kt= z;jY}pXjx=!%=N&{?ImzJezqNN5sUdg-Ah28;w9e$$@Y@!Ru5ed{VK{nGQ$Lie3)RL zOfUxmp5Jg|KU|xqx5A#?;Ea=75A!CVnC*bZC1^2iiWO^$zlZHnn3D)UjR$!=jxnoS zBhb2sT?w{of6U)` z4~AG<9bEl6+_7SYm|hXDhy{~7Q7o*22GyZhs3{GPg?ohxyr!$ev2fGH&N>Sx;fOw2 z$JLQoq-kv|V(bEIpnXMMwJ+vvYK{eK+pxGli3sC?kGnlTFwNs*!MaPTgR!7Xo8&OW zowwuNci(MX?=wb#R7YdcrgLIZLoex68LMns>gZJI(y1y|)f9K09E~YYk90{0-X}$Ln=q zv{y}Bu^i2x9Oc$Fbylsh2dI$-h^&4SJqL_Wpj;6wAdV=VFN!WACn&~e$Lstls4>se z2v;uGOwMAz%KE1(j{_r&~l z79*Uc=`wh%aBYnReO8{;&5gP-%gbSjpu~bXPQ3M4@z!I__R>15$z4ll$NaNJs4E6T zGX#UsIhVoz0+J7$qoDZPP@u^duu=j{NEdQg720y#@WHOD@Cl*J7Xl6IUT~}Hg=3y3 zKZug-+2MvmsTNt~w=x z!N6a;l{;Rr%J5M(k>#W8STp%(mk;haPy(lmZ!D}~x0=kt;CPV4BLgHFKn||s8Xwd_ z3{wfAo#HU8dVpCZ&8}-{s%=nftTyU_F3=D505mqM>H#hsgx7l1I$@}DadMq8&V6vn z;%$CXoh4{3uNZFFFgJG3!OAqXHg#FUiJgqxQI66mHRef$o1;FuR%7^UXda>yfsTq0 zWi*!g&ETg4A-XZdlnH^O{v>!F4l$$%)0f4#d9DWU9!{181UmibPcWqMTB;VRK# z3@}PdDp_)6HPhb}O`aCJt&8$}J%Vzac8jzhNbP-?FCVQB9Ti8}Ep8%f0S~di_jXit z!lOV0b_HgKG4|dn`bT(BC(0gDfZgqjL_2Xl;}vX{U>^8r5p_o@@)dpX(THIGU}Ken zy=-GOf<0tovjzLEjm;HoBr*_XDf6WFpN9sb-$veTVdsV!n@;kP-^Q0HVEtl zY@;93m4FMCE79Xa>M+{Q@vwy31QrC&EYoVcwa7e9+nG7H7T*r!Su*L~i?0!HN`wEL2c9j^RK)ZJ0yWDozQUDxA@Dk|M; zW0!jw`x_hkMUb(-E48~RtkScLDPN+WRUQd@DY3}H9s%a33}f^qdZhC9aFCv`>om_d z!V&T;w(73;e>Yq~8%x*^!fEM1!D_GM)$&GfKfmXu~%#%YW_ zqGnoQVIrl4@`71X&Zg&i)3yDqmEIQ2lF~{YO=T&qbgqSols3u;W=UC2H?)+cw9{>Z zSyI~RSEV{HwbL7dy`VhkRS<>Vwz1mSB4DEkSwt@chpPUltRTa}l#WW~+-KMQxT+0U z(XJZ{pB3q#<2Ls9;XcVH6za#Bf_I)RX<(hbOO+-2^yOer88 zQRq71XQ|?BZWVZ`z?8r=paMy6glp(gDgO#^9`@6x;0-~Ay&yu*R5hWz9kU)(p22L-qL;&K zD5kuO*`1@XgnqyakTG)kW_m0-gnjX`fC2dBV2% zpT~~Jy{w?8;!X69@>cvUP`LL8=q~S{DX6{}Rg?$l2LV6epR}m*j`EvmT;Lo~PDWak zUXim=f;I=zDm}}TJ0lA`N1)Xjx=pltNBNl6<+(~YU$8Wk*?&TvukQ7{ zN}t87olw~yqI`k?IG?`giBf`&0xqF@0F(3}U=#fWu$6uRxPo2)TrHey=yjCW(dWHU zWJIq4ZjiPc>1~v^2;4685&DKNN_*&Czzm)sqBJft^Ymqu_Y1sMIB$^J&q?ox=}pug zp{0Q+eMM?-6Mc@-Hc-AscL07%==Y0O57V2V9HVpb0QI=gpB9~eK}SIOrNC!}{t9gi zMd@GZ>wtfxlcA+}ZoN9(LSecf(t?${1#li+3RqA30UPNMU_0Fp_%Zq!U=RHU@B(@T zaFE^ryd1Cx&%hS|h5-9SW=bf-He~uR?WJOcF10zp%IG1fz21h*b3J&zS#hKA92NSV z0`CU>XBA%qy{_WxQu}S1ONEMKQv0aD*Ry)yce&|i{~{!Zk) zDz&7r=9J;Ku?Ji`Ku0!tRnQ0^AW-9ourIZidvV?sG5wa2A=TxyR??eju^N$4*L{UxE3%GzqG=&y?YDogXI zInWbQTQ9ZsQd=*z>xAB;^4NDud05IL;Hiujg>qCqKnp64O8J<;$5pn;^HL^_`&Bfi zC>qO22xXndnyi!ZPN6@JH++>*@-R=Ahxxmte1nvaO8IwEUgu?=UN7_9X+x%bP0G(p zt;ff;DI0Qa(f1JG4L%eo`k?fewMJv&u!NUWv4|Cu!JswDS?Wd ze$Jw8bS*thXDEHjMrDU`t8%yUkn&4qk=m_|YQNV0MO*JNJUI`Z^{@k~cr)ZhO!47V z+mDlv0AfrKD=UOZbEFan?R36p1>lgE;V**>2O_Ia17EJ}M(ygV^RfSXkpXZo8u|$U zQz6?Ai05d)dGKx(ajXJxDf(COlota$8~v-aifRBmsSemDupd_=BGm(C!CQ^EbQYjV z%K-D#2)K`$QPY9wH9>dNz4R*1gV!q8EB7k@Q@KsOSA9!8sXnQ-c{)9Z_Y$5OJw?tp z+}A*qvy}3+-*YxH7Wv*niFnAV?K{+@{ScqI^kZ!{aA`a=G?-82)5Be+nVRU&rt{k; z#`VGUHTt=2t+b{uTNu;LR9_6+KIkOuYf6iXf%oXF-=`!}X@Of4~rJ|Og_Q=?fU2Mzm2 z+Gu+^pV2|obHiqO9J1SJlb*|^M)mcEIhM+|Q4d6p8smp zHJgl)LPlRpYqpr_ebBIfY&@fn=@>Yht5?sb(wW>^YVBLOdVO0@dvDu{j`r?VtJ->7 zS9SIEwyx;tTHV&w)ziLmWqar9_Rg-Z)vH%`ujuRQXm4*{zH)inidDTmovq!po$~m~ zSXUm0kh=1+26 z4Rxo6_u^=DeOk|eZ<9W@OE+h(gCIyYvZ+jecDKwckm(`@3*)T5K2jb)ZaPLEDXTd0QcyPmf_tu;>P8g|;?Hma9cMUza7l-ZaK+9$7@9E1RFdFnQ91I+@gK zWb;@IdDEB}$Zj-JBbGgclig%8w=?Usdq!u#3UvF(W<7tkVeakL_oVivje=QfJtNz| zu1~;=Pr);&o0zd}9o2~8z(56qv!a?6eiDbMWovUWL6i{(RbH>}dUjz!uwGz51=u@8$4 zZah*_mwJq`@pMKvB@}?gRkg*`_d&Z0Ijr_)bLkPi+^kfR+7gCHxvMZb%I;gH@$#5V z>B{9`h0KI_V41N$&wGqv%DUW?8s3x6y2Loki5D<0WVTVctu;&Q@da6(y{KGaX{4JQ zWc`-uef#q|24!T+BuB0FFvvx^Idi2e6s0n!DBUBfn+Qc=wS?(QM zVi~cfMOtsuGpYSja@9MkZZWZ=4Cl)Yv5L!xV|n%)d@r_Ku?1W1m~5?Onj@0CPGu*` z6?QBUdOp1?ok{0iwcQi&D|UEsRocgUDRBaUEdl8R*#kwG94zc&j~&=e5`DX}!-yn? zIbaUz8PGDRQOB9BtpslF5Ns7%Yu@s`>Fm_x$ zLvS}2wmzNPgJ^@T5H8L0kW1%UoC(RbjASy@Z)FOWC`lSPKKAOvnUu+?3a1g&Z$&=` z<2C7&c}dHzXA{<}Z66xqJ=w(sfi8?IZDv&1CAKS8#h7geWE(IVRug;Gc4M!e6$ShD zkDJJTKw~908pBdARWoj(l$vQ{MHVoMNHE6*$rH4%;XY8IbN!A8x z2e$4)Iy0i1u4KiTLz=cvm1<@PYW7N`83T+{xlJE4@;a8=us%{SC6g%0oVs&isMsR0 zEDf{7<81PvIrf|(6KiqUV6Zi(ut9&>Y1Sfx%R9OG%z|A4r!cp$e$+B7w{l=A=emxb z<+>c5LMJ!ND15f$1@4M+xql?*2zOStvk&psokn1=cM`00Ucrp!hIJ%d*ewO0y#2CC zc**6aq#C6lW>vCk%$g&2u+6dWl{jBh_P{Kx3?CX!^$kM`%tzRsymTh`Y&l4hZA(JOIJzNNZ0WK`c zobG`H8&)0i2v z58E@Z;nRq9_wHt0vv&E=ki7wk`FjjJHI*iUj~xVY97+hAjD7lM9X}{?ZHaci0Q<^M zjfU;}%(0-wT3jtwd+Ns%WS$?0<$>2GI=Q}$A}celF7N1A9fcgy3O*Yld`W0{uTzG1 zl-X=ze|Dd}`%kN~9znW>5nFT9Dp?0BnXytFS?I2g*n6kfxWqV5(smoiiY^gsP#5ZO zxX3Ac$@XVQ^!?@4CTXfGqqK0I+iqiILME-ONQs1F9juX=POVBuHe`$s^J#)kTkq@jg8{0(4bxTc7BG=!5>{Zm2x4@5z{z1L_3s5QO=T1 zE%;5`E}S;%IHAu2>xGmoO1+@ua5sTZfG3MLVg{s-;4pNmZscK+Zn2F{l6<^?ww3?!KsEJ#=W5zc!-c9T!3^9_A>HT;F?O2`H2WX9}Om zO1nE@E^|h%=|fA1VX`>5%}a}nOw!db!3fNx41IY04q%W6A(IV%O8H@ypTg*MqBAx_ z?>t@(@fdfb-KZEpg~`uwy~}jVVY+)Pb6JWHLkO$>{*1U=d}d6P%gO|dpo6I;dS-`mu)AILBaEmYjfG$8NkXbKt{DZQcY<9+@+ma-B1&PCIbBMz(@z zQ@1V0ExX*`F3~)X^~EFLN#-%JCJa;f=ro28uW!h{@YFpgz~_wO14?yijBmU4mtBw- z&Ti1hY&<>oo<2fycwz4_ZC}daeby-?e?V=wW7bUx0QpnP zbj=vPzgv7{x|6;4!r+N?n|T|CGbT%jU2z;r7%&ybJr4OybDW%IC-I`XJbY{LO`xC3 zFkCl%Xv^45h{8{ew2yxEu??Sn^P<0fdBgJw(h{V25{eS=0>o;#7?t9=4C86ktG=4} zgc2`!5_o+Dd_M52fCm!971iWTP`r4fFQF>Y1<{CKtBGw=Vq0Td7ZS4w;udv0yA zHCDVeR=hn*8eqJ5bG D6ma@hf{f{RNgtMvVhSlu|u&yP5e-e5-a}5iD+M|1W&EicC6TlTM%*FNjy%BJk$2 ziiZ|JN)%l!gbfZY#Z6VwQ~b~(;e0g22CxJNoI+4&Pq2AFlFnuFmI-Y0!Jg1p3n}v} z@Wt*!o$=y5@k4D3=JPm#3fH-1!6zKSQV_+3WkIA$fdLL;Vk~jdiYf*3zX=5XV>OHS zR3?H7dq(U~KRjeX6kZI|IC?oM!zf{vW;bs0$Ku6j#EOqZ0E-Fx&GAEih;`)f4H_S;c%mg)q25G%cSi%b>ns_M5XxKD76hZHrs z1fuQX@vurgz;FJ|8PUJty>&qID*=yRiEj-2^g#8yPc=WcHPH5Vt1r4|<>rpS_s<*p zRP341IT3fB>Oz*23u$*FE8Iwj8(HZ_R#EXk^FHb17XSApy;pvC_1xS2sdC;>IZG&h z_dik&d&$%^ACInM}}$3 z|MaW$REhC)!5>i9=~?x3k(zITSM}kas`{cH9} z<-Bi!my4<|p>b*vK-RI4kZn2zB%?@Aci`K3YJ5i&Uzo#f0pH{O!11LyD?3FwL`Yyb zH;)&DyTCiT8ZSuNSQRgX(8k{1xmd8adJ&(NEDKp~@gB*Wiud^lX=3q5*tZo;a`+KbK9_+}$pdb@~M#m3b+1$?UT ztyE}E%jUlAcy%CO&uOw>8K1jvc}puKL}!)0BVZr$^U*ogC{%TE8b`V&PXF_X^W|L< zMHKSm^}CMKQT#d(NE?3ni9h^GQ6aA&`01uX3s3RN#CpY#AAw?iFq(@M+BPF+`Q=NC z>+N2d+IZS8;IT3?cyw{5LO0;+hbl}}(Ur*t8-9v32snoBrVCKq{U{hWG{bkx)t-8po~eL;3+ujiLV4%9hRX>Dn|ycv ze=UnT)MJ>v_-YqktI=3)*f4cn-r{rZyGtRX>N|^%Eq-+IV~dY3o-F783yN3-#~ zKe<2g3LGv@r!(IMd@d=X()xxblTgOV6kUWz_#wbPoHGnkKOWsT1Mdf1k1}76c>Zvb zC(imXh08?vwX|FwK=BzH=UXp63Z(KW21i6bs_aKjup5~HUrUHvZAWcNG6g<0%!7~f z2J8C1=XnTKpp$h*!zYN-B|R)W*2yu$6*!TB4RBf=Lt8#H9m638_c4JHrQ{5Y>A}p2rxyY_5+oBCETT35;UiIK-Yg+nSy_84yQS@nn=6r6-7s4s}*$90` zWgI-Nag2s7Fp3ktJa`iLWJR9=o6b)#JZi^ojPc1K3B~=k;e*)8t=E+@FI&(b+u1q= zE|31B^#e6wYwRxgt%+Oy)LALd3BErr^Vfx0=CeRPA>}zw!28*|_?gb~>T(;N&ku0z Tw0?X4IsT#k|G)m9v%voXXpu@cn0I_F|h* z^(7B*ocYdwJOBC5fBrdpCNodIKspg6@Z7yibQ3+doWgs-sqv^SI&ukb~({bFus7S+WIfmsJrMU&8;nrkkczEbY)|tjyc&Q%vJC*8T5A+HIMocIrHto$Rd6b{ z90*=$8c$ElA^MCbZ5M`|GFrmJzTSt!d;sosp z^T^}4jQQd1W}irsitHeIj8ihiu4G~E-_*iBMaQ)zJw-1nd`isd@1k`?o1$06ue20B zr=5a!r@~(grvIk!yplYl=wZPgzN_7V{az zfBwNKL?-BRhZ_gi>~N2Q`%H&p-SZ(g@RoiC+}9#*Um^$Y8y(9OV*GZbdxa*zy%KSM zRNSi(m(*GJlg_wlaGZ}@yj=PvXpR0sBO^K;)CXxw7qkPIqP@T&dOvW4#uc7cm{&Nh z@SMU=C^Ug7Y6EwZrRX#~5%RE&E(3Rx34Dmwfur3 zo%7qPc_vSr)tb1l=hmMvK;x0`a-Y{X?e@=)rfAy)aV3H6Ie#ACTsZs$5N#gNGiIGre#ZSN;=X* zI6bO)Pp%=j3%*&G(~fV|WOrDHQrZqjC0S|J>t@C7v7JSf{gS-zBPP3Dwt`;6xi#r| zn1)ltsp6D%U6)M{shGr7KwfdZ)vhA;Hi>myl%9|DZ&vo~jcNZ!tD@^HTlE$a(dQ&g zk`kVmws}=i{^m*MJrq_o=qlo+!!Q3pcNKBW?AdhMUB&s96IczYrAfc^rusJOxwq_<{Or61J@g2ZbGHqH?*$lo$$ z>$}VS%h}R4ljmDvxIxrOYgjwJTJ^nNMDp>n-P0gCL%w=r?)unke<^(D&v%Bdw@-hI z5{3{1x7@-~!LJokz(U>6>Cj|$qGnVl%(Y*EL@ z2cnwz$lCEt79P^OI&V20LC>x7QC!xB^S13?nQ7U9)wCr9gVWB6^emh@Y<70n ze>cNqIXLB1Z19#;7YtxH=PeMM=M=qj_Wxe=-{aZKKXFHoTbl2+M$B#KqdRXXT`am@ z3CFx?In?m0t|z5>?^t{HVff(d+y6*IQDLPI60RYAO>GsSj5f*HjK3W&=ZLcS1&>=+ zKMC?8?kS7F2|5pI8edwo;HQC;;a3;EmiYUf@Fo!NZrFb`a+E+Hz9_M0q7p~}uO@l$ zW8oez;nSgIa+T2$b(=0jYeMQnZ&Cm|7hKqGBwm11ftUhVS&-uZ-sH(vHd(AY{5we% z&H+B6c3^A~{uN(5N6aQXx1nVVZdn{XU7r`#{H%@FJ&y6&&O?Y{FYGyUVXUFY z?n>V7+!;h< : IEnumerable - { - private Dictionary t1ToT2Dict = new Dictionary(); - private Dictionary t2ToT1Dict = new Dictionary(); - - public IEnumerable FirstTypes => t1ToT2Dict.Keys; - public IEnumerable SecondTypes => t2ToT1Dict.Keys; - - public IEnumerator GetEnumerator() => t1ToT2Dict.GetEnumerator(); - - public int Count => t1ToT2Dict.Count; - - public Dictionary First => t1ToT2Dict; - public Dictionary Second => t2ToT1Dict; - - public void Add(T1 key, T2 value) - { - if (t1ToT2Dict.ContainsKey(key)) - { - Remove(key); - } - - t1ToT2Dict[key] = value; - t2ToT1Dict[value] = key; - } - - public void Add(T2 key, T1 value) - { - if (t2ToT1Dict.ContainsKey(key)) - { - Remove(key); - } - - t2ToT1Dict[key] = value; - t1ToT2Dict[value] = key; - } - - public T2 Get(T1 key) => t1ToT2Dict[key]; - - public T1 Get(T2 key) => t2ToT1Dict[key]; - - public bool TryGetValue(T1 key, out T2 value) => t1ToT2Dict.TryGetValue(key, out value); - - public bool TryGetValue(T2 key, out T1 value) => t2ToT1Dict.TryGetValue(key, out value); - - public bool Contains(T1 key) => t1ToT2Dict.ContainsKey(key); - - public bool Contains(T2 key) => t2ToT1Dict.ContainsKey(key); - - public void Remove(T1 key) - { - if (Contains(key)) - { - T2 val = t1ToT2Dict[key]; - t1ToT2Dict.Remove(key); - t2ToT1Dict.Remove(val); - } - } - public void Remove(T2 key) - { - if (Contains(key)) - { - T1 val = t2ToT1Dict[key]; - t1ToT2Dict.Remove(val); - t2ToT1Dict.Remove(key); - } - } - - public T1 this[T2 key] - { - get => t2ToT1Dict[key]; - set - { - Add(key, value); - } - } - - public T2 this[T1 key] - { - get => t1ToT2Dict[key]; - set - { - Add(key, value); - } - } - } -} \ No newline at end of file diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/BidirectionalDictionary.cs.meta b/Assets/FishNet/Plugins/FishyFacepunch/Core/BidirectionalDictionary.cs.meta deleted file mode 100644 index 3bd09e8..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/BidirectionalDictionary.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 336587b490f535a4aa3b1618c9ebac55 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/ClientHostSocket.cs b/Assets/FishNet/Plugins/FishyFacepunch/Core/ClientHostSocket.cs deleted file mode 100644 index 2727871..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/ClientHostSocket.cs +++ /dev/null @@ -1,126 +0,0 @@ -#if !FishyFacepunch -using FishNet.Transporting; -using FishyFacepunch.Server; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; - -namespace FishyFacepunch.Client -{ - /// - /// Creates a fake client connection to interact with the ServerSocket when acting as host. - /// - public class ClientHostSocket : CommonSocket - { - #region Private. - /// - /// Socket for the server. - /// - private ServerSocket _server; - /// - /// Incomimg data. - /// - private Queue _incoming = new Queue(); - #endregion - - /// - /// Checks to set localCLient started. - /// - internal void CheckSetStarted() - { - //Check to set as started. - if (_server != null && base.GetLocalConnectionState() == LocalConnectionState.Starting) - { - if (_server.GetLocalConnectionState() == LocalConnectionState.Started) - SetLocalConnectionState(LocalConnectionState.Started, false); - } - } - - /// - /// Starts the client connection. - /// - /// - /// - /// - /// - internal bool StartConnection(ServerSocket serverSocket) - { - _server = serverSocket; - _server.SetClientHostSocket(this); - if (_server.GetLocalConnectionState() != LocalConnectionState.Started) - return false; - - SetLocalConnectionState(LocalConnectionState.Starting, false); - return true; - } - - /// - /// Sets a new connection state. - /// - protected override void SetLocalConnectionState(LocalConnectionState connectionState, bool server) - { - base.SetLocalConnectionState(connectionState, server); - if (connectionState == LocalConnectionState.Started) - _server.OnClientHostState(true); - else - _server.OnClientHostState(false); - } - - /// - /// Stops the local socket. - /// - internal bool StopConnection() - { - if (base.GetLocalConnectionState() == LocalConnectionState.Stopped || base.GetLocalConnectionState() == LocalConnectionState.Stopping) - return false; - - base.ClearQueue(_incoming); - //Immediately set stopped since no real connection exists. - SetLocalConnectionState(LocalConnectionState.Stopping, false); - SetLocalConnectionState(LocalConnectionState.Stopped, false); - _server.SetClientHostSocket(null); - - return true; - } - - /// - /// Iterations data received. - /// - internal void IterateIncoming() - { - if (base.GetLocalConnectionState() != LocalConnectionState.Started) - return; - - while (_incoming.Count > 0) - { - LocalPacket packet = _incoming.Dequeue(); - ArraySegment segment = new ArraySegment(packet.Data, 0, packet.Length); - base.Transport.HandleClientReceivedDataArgs(new ClientReceivedDataArgs(segment, (Channel)packet.Channel, Transport.Index)); - packet.Dispose(); - } - } - - /// - /// Called when the server sends the local client data. - /// - internal void ReceivedFromLocalServer(LocalPacket packet) - { - _incoming.Enqueue(packet); - } - - /// - /// Queues data to be sent to server. - /// - internal void SendToServer(byte channelId, ArraySegment segment) - { - if (base.GetLocalConnectionState() != LocalConnectionState.Started) - return; - if (_server.GetLocalConnectionState() != LocalConnectionState.Started) - return; - - LocalPacket packet = new LocalPacket(segment, channelId); - _server.ReceivedFromClientHost(packet); - } - } -} -#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/ClientHostSocket.cs.meta b/Assets/FishNet/Plugins/FishyFacepunch/Core/ClientHostSocket.cs.meta deleted file mode 100644 index 9e94555..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/ClientHostSocket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 112bec8b5281832468d85543d0b6e31c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/ClientSocket.cs b/Assets/FishNet/Plugins/FishyFacepunch/Core/ClientSocket.cs deleted file mode 100644 index 151c9d1..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/ClientSocket.cs +++ /dev/null @@ -1,238 +0,0 @@ -#if !FishyFacepunch -using FishNet.Managing.Logging; -using FishNet.Transporting; -using Steamworks; -using Steamworks.Data; -using System; -using System.Threading; -using System.Threading.Tasks; -using UnityEngine; - -namespace FishyFacepunch.Client -{ - public class ClientSocket : CommonSocket - { - #region Private. - /// - /// SteamId for host. - /// - private SteamId _hostSteamID = 0; - /// - /// Socket to use. - /// - private Connection HostConnection => HostConnectionManager.Connection; - - /// - /// Use the internal connection manager from steam. - /// - private FishyConnectionManager HostConnectionManager; - - /// - /// Task used to check for timeout. - /// - private CancellationTokenSource cancelToken; - private TaskCompletionSource connectedComplete; - private TimeSpan ConnectionTimeout; - - /// - /// Task used to check for timeout. - /// - private bool _Error = false; - - #endregion - - /// - /// Initializes this for use. - /// - /// - internal override void Initialize(Transport t) - { - base.Initialize(t); - } - - /// - /// Starts the client connection. - /// - /// - /// - /// - /// - internal async void StartConnection(string address, ushort port) - { - cancelToken = new CancellationTokenSource(); - SteamNetworkingSockets.OnConnectionStatusChanged += OnConnectionStatusChanged; - ConnectionTimeout = TimeSpan.FromSeconds(Math.Max(1, base.Transport.GetTimeout(false))); - - SetLocalConnectionState(LocalConnectionState.Starting, false); - - try - { - if (SteamClient.IsValid) - { - connectedComplete = new TaskCompletionSource(); - if (!IsValidAddress(address)) - { - _hostSteamID = UInt64.Parse(address); - HostConnectionManager = SteamNetworkingSockets.ConnectRelay(_hostSteamID); - } - else - { - HostConnectionManager = SteamNetworkingSockets.ConnectNormal(NetAddress.From(address, port)); - } - HostConnectionManager.ForwardMessage = OnMessageReceived; - Task connectedCompleteTask = connectedComplete.Task; - Task timeOutTask = Task.Delay(ConnectionTimeout, cancelToken.Token); - - if (await Task.WhenAny(connectedCompleteTask, timeOutTask) != connectedCompleteTask) - { - if (cancelToken.IsCancellationRequested) - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Error)) - Debug.LogError($"The connection attempt was cancelled."); - } - else if (timeOutTask.IsCompleted) - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Error)) - Debug.LogError($"Connection to {address} timed out."); - StopConnection(); - } - SetLocalConnectionState(LocalConnectionState.Stopped, false); - } - } - else - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Error)) - Debug.LogError("SteamWorks not initialized"); - SetLocalConnectionState(LocalConnectionState.Stopped, false); - } - } - catch (FormatException) - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Error)) - Debug.LogError($"Connection string was not in the right format. Did you enter a SteamId?"); - SetLocalConnectionState(LocalConnectionState.Stopped, false); - _Error = true; - } - catch (Exception ex) - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Error)) - Debug.LogError(ex.Message); - SetLocalConnectionState(LocalConnectionState.Stopped, false); - _Error = true; - } - finally - { - if (_Error) - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Error)) - Debug.LogError("Connection failed."); - SetLocalConnectionState(LocalConnectionState.Stopped, false); - } - } - } - - /// - /// Called when local connection state changes. - /// - private void OnConnectionStatusChanged(Connection conn, ConnectionInfo info) - { - if (info.State == ConnectionState.Connected) - { - SetLocalConnectionState(LocalConnectionState.Started, false); - connectedComplete.SetResult(connectedComplete.Task); - } - else if (info.State == ConnectionState.ClosedByPeer || info.State == ConnectionState.ProblemDetectedLocally) - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Common)) - Debug.Log($"Connection was closed by peer, {info.EndReason}"); - StopConnection(); - } - else - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Common)) - Debug.Log($"Connection state changed: {info.State.ToString()} - {info.EndReason}"); - } - } - - /// - /// Stops the local socket. - /// - internal bool StopConnection() - { - if (base.GetLocalConnectionState() == LocalConnectionState.Stopped || base.GetLocalConnectionState() == LocalConnectionState.Stopping) - return false; - - SetLocalConnectionState(LocalConnectionState.Stopping, false); - - cancelToken?.Cancel(); - - //Reset callback. - SteamNetworkingSockets.OnConnectionStatusChanged -= OnConnectionStatusChanged; - - if (HostConnectionManager != null) - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Common)) - Debug.Log("Sending Disconnect message"); - HostConnection.Close(false, 0, "Graceful disconnect"); - HostConnectionManager = null; - } - - SetLocalConnectionState(LocalConnectionState.Stopped, false); - - return true; - } - - /// - /// Iterations data received. - /// - internal void IterateIncoming() - { - if (base.GetLocalConnectionState() != LocalConnectionState.Started) - return; - - HostConnectionManager.Receive(MAX_MESSAGES); - } - - private void OnMessageReceived(IntPtr dataPtr, int size) - { - (byte[] data, int ch) = ProcessMessage(dataPtr, size); - base.Transport.HandleClientReceivedDataArgs(new ClientReceivedDataArgs(new ArraySegment(data), (Channel)ch, Transport.Index)); - } - - /// - /// Queues data to be sent to server. - /// - /// - /// - internal void SendToServer(byte channelId, ArraySegment segment) - { - if (base.GetLocalConnectionState() != LocalConnectionState.Started) - return; - - Result res = base.Send(HostConnection, segment, channelId); - if (res == Result.NoConnection || res == Result.InvalidParam) - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Common)) - Debug.Log($"Connection to server was lost."); - StopConnection(); - } - else if (res != Result.OK) - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Error)) - Debug.LogError($"Could not send: {res.ToString()}"); - } - } - - /// - /// Sends queued data to server. - /// - internal void IterateOutgoing() - { - if (base.GetLocalConnectionState() != LocalConnectionState.Started) - return; - - HostConnection.Flush(); - } - } -} -#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/ClientSocket.cs.meta b/Assets/FishNet/Plugins/FishyFacepunch/Core/ClientSocket.cs.meta deleted file mode 100644 index ebb2a90..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/ClientSocket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c5c258174868ee54cb570bef71c82404 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/CommonSocket.cs b/Assets/FishNet/Plugins/FishyFacepunch/Core/CommonSocket.cs deleted file mode 100644 index 7d7bd7d..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/CommonSocket.cs +++ /dev/null @@ -1,177 +0,0 @@ -#if !FishyFacepunch -using FishNet.Managing.Logging; -using FishNet.Transporting; -using Steamworks; -using Steamworks.Data; -using System; -using System.Collections.Generic; -using System.Net; -using System.Runtime.InteropServices; -using UnityEngine; - -namespace FishyFacepunch -{ - - public abstract class CommonSocket - { - - #region Public. - /// - /// Current ConnectionState. - /// - private LocalConnectionState _connectionState = LocalConnectionState.Stopped; - /// - /// Returns the current ConnectionState. - /// - /// - internal LocalConnectionState GetLocalConnectionState() - { - return _connectionState; - } - /// - /// Sets a new connection state. - /// - /// - protected virtual void SetLocalConnectionState(LocalConnectionState connectionState, bool asServer) - { - //If state hasn't changed. - if (connectionState == _connectionState) - return; - - _connectionState = connectionState; - if (asServer) - Transport.HandleServerConnectionState(new ServerConnectionStateArgs(connectionState, Transport.Index)); - else - Transport.HandleClientConnectionState(new ClientConnectionStateArgs(connectionState, Transport.Index)); - } - #endregion - - #region Protected. - /// - /// Transport controlling this socket. - /// - protected Transport Transport = null; - /// - /// Pointers for received messages per connection. - /// - protected IntPtr[] MessagePointers = new IntPtr[MAX_MESSAGES]; - /// - /// Buffer used to receive data. - /// - protected byte[] InboundBuffer = null; - #endregion - - #region Const. - /// - /// Maximum number of messages which can be received per connection. - /// - protected const int MAX_MESSAGES = 256; - #endregion - - internal void ClearQueue(Queue lpq) - { - while (lpq.Count > 0) - { - LocalPacket lp = lpq.Dequeue(); - lp.Dispose(); - } - } - /// - /// Initializes this for use. - /// - /// - internal virtual void Initialize(Transport t) - { - Transport = t; - //Get whichever channel has max MTU and resize buffer. - int maxMTU = Transport.GetMTU(0); - maxMTU = Math.Max(maxMTU, Transport.GetMTU(1)); - InboundBuffer = new byte[maxMTU]; - } - - /// - /// Check if this is a valid address to start a p2p or c2s session. - /// - /// - /// - protected bool IsValidAddress(string address) - { - //If address is required then make sure it can be parsed. - if (!string.IsNullOrEmpty(address)) - { - if (!IPAddress.TryParse(address, out IPAddress result)) - { - return false; - } - else - { - return true; - } - } - else - { - return false; - } - } - - /// - /// Sends data over the steamConnection. - /// - /// - /// - /// - /// - protected Result Send(Connection conn, ArraySegment segment, byte channelId) - { - /* Have to resize array to include channel index - * if array isn't large enough to fit it. This is because - * we don't know what channel data comes in on so - * the channel has to be packed into the data sent. - * Odds of the array having to resize are extremely low - * so while this is not ideal, it's still very low risk. */ - if ((segment.Array.Length - 1) <= (segment.Offset + segment.Count)) - { - byte[] arr = segment.Array; - Array.Resize(ref arr, arr.Length + 1); - arr[arr.Length - 1] = channelId; - } - //If large enough just increase the segment and set the channel byte. - else - { - segment.Array[segment.Offset + segment.Count] = channelId; - } - //Make a new segment so count is right. - segment = new ArraySegment(segment.Array, segment.Offset, segment.Count + 1); - - GCHandle pinnedArray = GCHandle.Alloc(segment.Array, GCHandleType.Pinned); - IntPtr pData = pinnedArray.AddrOfPinnedObject() + segment.Offset; - - SendType sendFlag = (channelId == (byte)Channel.Unreliable) ? SendType.Unreliable : SendType.Reliable; - Result result = conn.SendMessage(pData, segment.Count, sendFlag); - if (result != Result.OK) - { - if (Transport.NetworkManager.CanLog(LoggingType.Warning)) - Debug.LogWarning($"Send issue: {result}"); - } - - pinnedArray.Free(); - return result; - } - - /// - /// Returns a message from the steam network. - /// - /// - /// - /// - protected (byte[], int) ProcessMessage(IntPtr ptrs, int size) - { - byte[] managedArray = new byte[size]; - Marshal.Copy(ptrs, managedArray, 0, size); - int channel = managedArray[managedArray.Length - 1]; - Array.Resize(ref managedArray, managedArray.Length - 1); - return (managedArray, channel); - } - } -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/CommonSocket.cs.meta b/Assets/FishNet/Plugins/FishyFacepunch/Core/CommonSocket.cs.meta deleted file mode 100644 index 34fb757..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/CommonSocket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3bc85d49720cf5844bf19af677e4f5f5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/FishyConnectionManager.cs b/Assets/FishNet/Plugins/FishyFacepunch/Core/FishyConnectionManager.cs deleted file mode 100644 index e05b936..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/FishyConnectionManager.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Steamworks; -using System; - -public class FishyConnectionManager : ConnectionManager -{ - public Action ForwardMessage; - - public override void OnMessage(IntPtr data, int size, long messageNum, long recvTime, int channel) - { - ForwardMessage(data, size); - } -} \ No newline at end of file diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/FishyConnectionManager.cs.meta b/Assets/FishNet/Plugins/FishyFacepunch/Core/FishyConnectionManager.cs.meta deleted file mode 100644 index e04a569..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/FishyConnectionManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4200e3c1bd9ce214baf0cc323ef78429 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/FishySocketManager.cs b/Assets/FishNet/Plugins/FishyFacepunch/Core/FishySocketManager.cs deleted file mode 100644 index 58a8908..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/FishySocketManager.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Steamworks; -using Steamworks.Data; -using System; - -public class FishySocketManager : SocketManager -{ - public Action ForwardMessage; - - public override void OnMessage(Connection connection, NetIdentity identity, IntPtr data, int size, long messageNum, long recvTime, int channel) - { - ForwardMessage(connection, data, size); - } -} \ No newline at end of file diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/FishySocketManager.cs.meta b/Assets/FishNet/Plugins/FishyFacepunch/Core/FishySocketManager.cs.meta deleted file mode 100644 index 4567fed..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/FishySocketManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1180bddcdfeaad44e80261cedd2b806d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/LocalPacket.cs b/Assets/FishNet/Plugins/FishyFacepunch/Core/LocalPacket.cs deleted file mode 100644 index e48887d..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/LocalPacket.cs +++ /dev/null @@ -1,25 +0,0 @@ -using FishNet.Utility.Performance; -using System; - -namespace FishyFacepunch -{ - internal struct LocalPacket - { - public byte[] Data; - public int Length; - public byte Channel; - public LocalPacket(ArraySegment data, byte channel) - { - Data = ByteArrayPool.Retrieve(data.Count); - Length = data.Count; - Buffer.BlockCopy(data.Array, data.Offset, Data, 0, Length); - Channel = channel; - } - - public void Dispose() - { - if (Data != null) - ByteArrayPool.Store(Data); - } - } -} diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/LocalPacket.cs.meta b/Assets/FishNet/Plugins/FishyFacepunch/Core/LocalPacket.cs.meta deleted file mode 100644 index 1e83600..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/LocalPacket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c1e0f33bdfade44489a2decb96d23c72 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/ServerSocket.cs b/Assets/FishNet/Plugins/FishyFacepunch/Core/ServerSocket.cs deleted file mode 100644 index 622bafa..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/ServerSocket.cs +++ /dev/null @@ -1,425 +0,0 @@ -#if !FishyFacepunch -using FishNet.Managing.Logging; -using FishNet.Transporting; -using FishyFacepunch.Client; -using Steamworks; -using Steamworks.Data; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace FishyFacepunch.Server -{ - public class ServerSocket : CommonSocket - { - #region Public. - /// - /// Gets the current ConnectionState of a remote client on the server. - /// - /// ConnectionId to get ConnectionState for. - internal RemoteConnectionState GetConnectionState(int connectionId) - { - //Remote clients can only have Started or Stopped states since we cannot know in between. - if (_steamConnections.Second.ContainsKey(connectionId)) - return RemoteConnectionState.Started; - else - return RemoteConnectionState.Stopped; - } - #endregion - - #region Private. - /// - /// SteamConnections for ConnectionIds. - /// - private BidirectionalDictionary _steamConnections = new BidirectionalDictionary(); - /// - /// SteamIds for ConnectionIds. - /// - private BidirectionalDictionary _steamIds = new BidirectionalDictionary(); - /// - /// Maximum number of remote connections. - /// - private int _maximumClients; - /// - /// Next Id to use for a connection. - /// - private int _nextConnectionId; - /// - /// Socket for the connection. - /// - private FishySocketManager _socket; - /// - /// ConnectionIds which can be reused. - /// - private Queue _cachedConnectionIds = new Queue(); - /// - /// Contains state of the client host. True is started, false is stopped. - /// - private bool _clientHostStarted = false; - /// - /// Packets received from local client. - /// - private Queue _clientHostIncoming = new Queue(); - /// - /// Socket for client host. Will be null if not being used. - /// - private ClientHostSocket _clientHost; - #endregion - - /// - /// Initializes this for use. - /// - /// - internal override void Initialize(Transport t) - { - base.Initialize(t); - } - - /// - /// Resets the socket if invalid. - /// - internal void ResetInvalidSocket() - { - /* Force connection state to stopped if listener is invalid. - * Not sure if steam may change this internally so better - * safe than sorry and check before trying to connect - * rather than being stuck in the incorrect state. */ - if (_socket == default) - base.SetLocalConnectionState(LocalConnectionState.Stopped, true); - } - /// - /// Starts the server. - /// - internal bool StartConnection(string address, ushort port, int maximumClients) - { - SteamNetworkingSockets.OnConnectionStatusChanged += OnRemoteConnectionState; - - SetMaximumClients(maximumClients); - _nextConnectionId = 0; - _cachedConnectionIds.Clear(); - - base.SetLocalConnectionState(LocalConnectionState.Starting, true); - - if (_socket != null) - { - _socket?.Close(); - _socket = default; - } - -#if UNITY_SERVER - _socket = SteamNetworkingSockets.CreateNormalSocket(NetAddress.From(address, port)); -#else - _socket = SteamNetworkingSockets.CreateRelaySocket(); -#endif - _socket.ForwardMessage = OnMessageReceived; - - base.SetLocalConnectionState(LocalConnectionState.Started, true); - - return true; - } - - /// - /// Stops the local socket. - /// - internal bool StopConnection() - { - if (base.GetLocalConnectionState() == LocalConnectionState.Stopped) - return false; - - base.SetLocalConnectionState(LocalConnectionState.Stopping, true); - - if (_socket != null) - { - SteamNetworkingSockets.OnConnectionStatusChanged -= OnRemoteConnectionState; - _socket?.Close(); - _socket = default; - } - - base.SetLocalConnectionState(LocalConnectionState.Stopped, true); - - return true; - } - - /// - /// Stops a remote client from the server, disconnecting the client. - /// - /// ConnectionId of the client to disconnect. - internal bool StopConnection(int connectionId) - { - if (connectionId == FishyFacepunch.CLIENT_HOST_ID) - { - if (_clientHost != null) - { - _clientHost.StopConnection(); - return true; - } - else - { - return false; - } - - } - else - { - if (_steamConnections.Second.TryGetValue(connectionId, out Connection steamConn)) - { - return StopConnection(connectionId, steamConn); - } - else - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Error)) - Debug.LogError($"Steam connection not found for connectionId {connectionId}."); - return false; - } - } - } - /// - /// Stops a remote client from the server, disconnecting the client. - /// - /// - /// - private bool StopConnection(int connectionId, Connection socket) - { - socket.Close(false, 0, "Graceful disconnect"); - _steamConnections.Remove(connectionId); - _steamIds.Remove(connectionId); - if (base.Transport.NetworkManager.CanLog(LoggingType.Common)) - Debug.Log($"Client with ConnectionID {connectionId} disconnected."); - base.Transport.HandleRemoteConnectionState(new RemoteConnectionStateArgs(RemoteConnectionState.Stopped, connectionId, Transport.Index)); - _cachedConnectionIds.Enqueue(connectionId); - - return true; - } - - /// - /// Called when a remote connection state changes. - /// - private void OnRemoteConnectionState(Connection conn, ConnectionInfo info) - { - ulong clientSteamID = info.Identity.SteamId; - if (info.State == ConnectionState.Connecting) - { - if (_steamConnections.Count >= _maximumClients) - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Common)) - Debug.Log($"Incoming connection {clientSteamID} was rejected because would exceed the maximum connection count."); - - conn.Close(false, 0, "Max Connection Count"); - return; - } - - Result res; - - if ((res = conn.Accept()) == Result.OK) - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Common)) - Debug.Log($"Accepting connection {clientSteamID}"); - } - else - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Common)) - Debug.Log($"Connection {clientSteamID} could not be accepted: {res.ToString()}"); - } - } - else if (info.State == ConnectionState.Connected) - { - int connectionId = (_cachedConnectionIds.Count > 0) ? _cachedConnectionIds.Dequeue() : _nextConnectionId++; - _steamConnections.Add(conn, connectionId); - _steamIds.Add(clientSteamID, connectionId); - - if (base.Transport.NetworkManager.CanLog(LoggingType.Common)) - Debug.Log($"Client with SteamID {clientSteamID} connected. Assigning connection id {connectionId}"); - base.Transport.HandleRemoteConnectionState(new RemoteConnectionStateArgs(RemoteConnectionState.Started, connectionId, Transport.Index)); - } - else if (info.State == ConnectionState.ClosedByPeer || info.State == ConnectionState.ProblemDetectedLocally) - { - if (_steamConnections.TryGetValue(conn, out int connId)) - { - StopConnection(connId, conn); - } - } - else - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Common)) - Debug.Log($"Connection {clientSteamID} state changed: {info.State.ToString()}"); - } - } - - - /// - /// Allows for Outgoing queue to be iterated. - /// - internal void IterateOutgoing() - { - if (base.GetLocalConnectionState() != LocalConnectionState.Started) - return; - - foreach (Connection conn in _steamConnections.FirstTypes) - { - conn.Flush(); - } - } - - /// - /// Iterates the Incoming queue. - /// - /// - internal void IterateIncoming() - { - //Stopped or trying to stop. - if (base.GetLocalConnectionState() == LocalConnectionState.Stopped || base.GetLocalConnectionState() == LocalConnectionState.Stopping) - return; - - //Iterate local client packets first. - while (_clientHostIncoming.Count > 0) - { - LocalPacket packet = _clientHostIncoming.Dequeue(); - ArraySegment segment = new ArraySegment(packet.Data, 0, packet.Length); - base.Transport.HandleServerReceivedDataArgs(new ServerReceivedDataArgs(segment, (Channel)packet.Channel, FishyFacepunch.CLIENT_HOST_ID, Transport.Index)); - packet.Dispose(); - } - - _socket.Receive(MAX_MESSAGES); - } - - private void OnMessageReceived(Connection conn, IntPtr dataPtr, int size) - { - (byte[] data, int ch) = ProcessMessage(dataPtr, size); - base.Transport.HandleServerReceivedDataArgs(new ServerReceivedDataArgs(new ArraySegment(data), (Channel)ch, _steamConnections[conn], Transport.Index)); - } - - /// - /// Sends data to a client. - /// - /// - /// - /// - internal void SendToClient(byte channelId, ArraySegment segment, int connectionId) - { - if (base.GetLocalConnectionState() != LocalConnectionState.Started) - return; - - //Check if sending local client first, send and exit if so. - if (connectionId == FishyFacepunch.CLIENT_HOST_ID) - { - if (_clientHost != null) - { - LocalPacket packet = new LocalPacket(segment, channelId); - _clientHost.ReceivedFromLocalServer(packet); - } - return; - } - - if (_steamConnections.TryGetValue(connectionId, out Connection steamConn)) - { - Result res = base.Send(steamConn, segment, channelId); - - if (res == Result.NoConnection || res == Result.InvalidParam) - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Common)) - Debug.Log($"Connection to {connectionId} was lost."); - StopConnection(connectionId, steamConn); - } - else if (res != Result.OK) - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Error)) - Debug.LogError($"Could not send: {res.ToString()}"); - } - } - else - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Error)) - Debug.LogError($"ConnectionId {connectionId} does not exist, data will not be sent."); - } - } - - /// - /// Gets the address of a remote connection Id. - /// - /// - /// - internal string GetConnectionAddress(int connectionId) - { - if (_steamIds.TryGetValue(connectionId, out SteamId steamId)) - { - return steamId.ToString(); - } - else - { - if (base.Transport.NetworkManager.CanLog(LoggingType.Error)) - Debug.LogError($"ConnectionId {connectionId} is invalid; address cannot be returned."); - - return string.Empty; - } - } - - - /// - /// Sets maximum number of clients allowed to connect to the server. If applied at runtime and clients exceed this value existing clients will stay connected but new clients may not connect. - /// - /// - internal void SetMaximumClients(int value) - { - _maximumClients = Math.Min(value, FishyFacepunch.CLIENT_HOST_ID - 1); - } - internal int GetMaximumClients() - { - return _maximumClients; - } - - #region ClientHost (local client). - /// - /// Sets ClientHost value. - /// - /// - internal void SetClientHostSocket(ClientHostSocket socket) - { - _clientHost = socket; - } - /// - /// Called when the local client stops. - /// - internal void OnClientHostState(bool started) - { - - _clientHostStarted = started; - FishyFacepunch ff = (FishyFacepunch)base.Transport; - SteamId steamId = new SteamId() - { - Value = ff.LocalUserSteamID - }; - - //If not started flush incoming from local client. - if (!started && _clientHostStarted) - { - base.ClearQueue(_clientHostIncoming); - base.Transport.HandleRemoteConnectionState(new RemoteConnectionStateArgs(RemoteConnectionState.Stopped, FishyFacepunch.CLIENT_HOST_ID, Transport.Index)); - _steamIds.Remove(steamId); - } - //If started. - else if (started) - { - _steamIds[steamId] = FishyFacepunch.CLIENT_HOST_ID; - base.Transport.HandleRemoteConnectionState(new RemoteConnectionStateArgs(RemoteConnectionState.Started, FishyFacepunch.CLIENT_HOST_ID, Transport.Index)); - } - - _clientHostStarted = started; - } - - /// - /// Queues a received packet from the local client. - /// - internal void ReceivedFromClientHost(LocalPacket packet) - { - if (!_clientHostStarted) - { - packet.Dispose(); - return; - } - - _clientHostIncoming.Enqueue(packet); - } - #endregion - } -} -#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/FishNet/Plugins/FishyFacepunch/Core/ServerSocket.cs.meta b/Assets/FishNet/Plugins/FishyFacepunch/Core/ServerSocket.cs.meta deleted file mode 100644 index cdfb777..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/Core/ServerSocket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a0f5d2e6e0da6a244a3fa589e4f6bba2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Plugins/FishyFacepunch/FishyFacepunch.cs b/Assets/FishNet/Plugins/FishyFacepunch/FishyFacepunch.cs deleted file mode 100644 index 2ae2a05..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/FishyFacepunch.cs +++ /dev/null @@ -1,518 +0,0 @@ -#if !FishyFacepunch -using FishNet.Managing; -using FishNet.Transporting; -using Steamworks; -using System; -using UnityEngine; - -namespace FishyFacepunch -{ - public class FishyFacepunch : Transport - { - ~FishyFacepunch() - { - Shutdown(); - } - - #region Public. - [System.NonSerialized] - public ulong LocalUserSteamID; - #endregion - - #region Serialized. - /// - /// Steam application Id. - /// - [Tooltip("Steam application Id.")] - [SerializeField] - private uint _steamAppID = 480; - - [Header("Server")] - /// - /// Address server should bind to. - /// - [Tooltip("Address server should bind to.")] - [SerializeField] - private string _serverBindAddress = string.Empty; - /// - /// Port to use. - /// - [Tooltip("Port to use.")] - [SerializeField] - private ushort _port = 27015; - /// - /// Maximum number of players which may be connected at once. - /// - [Tooltip("Maximum number of players which may be connected at once.")] - [Range(1, ushort.MaxValue)] - [SerializeField] - private ushort _maximumClients = 16; - - [Header("Client")] - /// - /// Address client should connect to. - /// - [Tooltip("Address client should connect to.")] - [SerializeField] - private string _clientAddress = string.Empty; - - [Tooltip("Timeout for connecting in seconds.")] - [SerializeField] - private int _timeout = 25; - #endregion - - #region Private. - /// - /// MTUs for each channel. - /// - private int[] _mtus; - /// - /// Client for the transport. - /// - private Client.ClientSocket _client = new Client.ClientSocket(); - /// - /// Client when acting as host. - /// - private Client.ClientHostSocket _clientHost = new Client.ClientHostSocket(); - /// - /// Server for the transport. - /// - private Server.ServerSocket _server = new Server.ServerSocket(); - #endregion - - #region Const. - /// - /// Id to use for client when acting as host. - /// - internal const int CLIENT_HOST_ID = short.MaxValue; - #endregion - - #region Initialization and Unity. - public override void Initialize(NetworkManager networkManager, int transportIndex) - { - base.Initialize(networkManager, transportIndex); - - CreateChannelData(); - -#if !UNITY_SERVER - SteamClient.Init(_steamAppID, true); - SteamNetworking.AllowP2PPacketRelay(true); -#endif - _clientHost.Initialize(this); - _client.Initialize(this); - _server.Initialize(this); - } - - private void OnDestroy() - { - Shutdown(); - } - - private void Update() - { - _clientHost.CheckSetStarted(); - } - #endregion - - #region Setup. - /// - /// Creates ChannelData for the transport. - /// - private void CreateChannelData() - { - _mtus = new int[2] - { - 1048576, - 1200 - }; - } - - /// - /// Tries to initialize steam network access. - /// - private void InitializeRelayNetworkAccess() - { -#if !UNITY_SERVER - SteamNetworkingUtils.InitRelayNetworkAccess(); - LocalUserSteamID = Steamworks.SteamClient.SteamId.Value; -#endif - } - #endregion - - #region ConnectionStates. - /// - /// Gets the IP address of a remote connection Id. - /// - /// - /// - public override string GetConnectionAddress(int connectionId) - { - return _server.GetConnectionAddress(connectionId); - } - /// - /// Called when a connection state changes for the local client. - /// - public override event Action OnClientConnectionState; - /// - /// Called when a connection state changes for the local server. - /// - public override event Action OnServerConnectionState; - /// - /// Called when a connection state changes for a remote client. - /// - public override event Action OnRemoteConnectionState; - /// - /// Gets the current local ConnectionState. - /// - /// True if getting ConnectionState for the server. - public override LocalConnectionState GetConnectionState(bool server) - { - if (server) - return _server.GetLocalConnectionState(); - else - return _client.GetLocalConnectionState(); - } - /// - /// Gets the current ConnectionState of a remote client on the server. - /// - /// ConnectionId to get ConnectionState for. - public override RemoteConnectionState GetConnectionState(int connectionId) - { - return _server.GetConnectionState(connectionId); - } - /// - /// Handles a ConnectionStateArgs for the local client. - /// - /// - public override void HandleClientConnectionState(ClientConnectionStateArgs connectionStateArgs) - { - OnClientConnectionState?.Invoke(connectionStateArgs); - } - /// - /// Handles a ConnectionStateArgs for the local server. - /// - /// - public override void HandleServerConnectionState(ServerConnectionStateArgs connectionStateArgs) - { - OnServerConnectionState?.Invoke(connectionStateArgs); - } - /// - /// Handles a ConnectionStateArgs for a remote client. - /// - /// - public override void HandleRemoteConnectionState(RemoteConnectionStateArgs connectionStateArgs) - { - OnRemoteConnectionState?.Invoke(connectionStateArgs); - } - #endregion - - #region Iterating. - /// - /// Processes data received by the socket. - /// - /// True to process data received on the server. - public override void IterateIncoming(bool server) - { - if (server) - { - _server.IterateIncoming(); - - } - else - { - _client.IterateIncoming(); - _clientHost.IterateIncoming(); - } - } - - /// - /// Processes data to be sent by the socket. - /// - /// True to process data received on the server. - public override void IterateOutgoing(bool server) - { - if (server) - _server.IterateOutgoing(); - else - _client.IterateOutgoing(); - } - #endregion - - #region ReceivedData. - /// - /// Called when client receives data. - /// - public override event Action OnClientReceivedData; - /// - /// Handles a ClientReceivedDataArgs. - /// - /// - public override void HandleClientReceivedDataArgs(ClientReceivedDataArgs receivedDataArgs) - { - OnClientReceivedData?.Invoke(receivedDataArgs); - } - /// - /// Called when server receives data. - /// - public override event Action OnServerReceivedData; - /// - /// Handles a ClientReceivedDataArgs. - /// - /// - public override void HandleServerReceivedDataArgs(ServerReceivedDataArgs receivedDataArgs) - { - OnServerReceivedData?.Invoke(receivedDataArgs); - } - #endregion - - #region Sending. - /// - /// Sends to the server or all clients. - /// - /// Channel to use. - /// /// Data to send. - public override void SendToServer(byte channelId, ArraySegment segment) - { - _client.SendToServer(channelId, segment); - _clientHost.SendToServer(channelId, segment); - } - /// - /// Sends data to a client. - /// - /// - /// - /// - public override void SendToClient(byte channelId, ArraySegment segment, int connectionId) - { - _server.SendToClient(channelId, segment, connectionId); - } - #endregion - - #region Configuration. - /// - /// Returns the maximum number of clients allowed to connect to the server. If the transport does not support this method the value -1 is returned. - /// - /// - public override int GetMaximumClients() - { - return _server.GetMaximumClients(); - } - /// - /// Sets maximum number of clients allowed to connect to the server. If applied at runtime and clients exceed this value existing clients will stay connected but new clients may not connect. - /// - /// - public override void SetMaximumClients(int value) - { - _server.SetMaximumClients(value); - } - /// - /// Sets which address the client will connect to. - /// - /// - public override void SetClientAddress(string address) - { - _clientAddress = address; - } - public override void SetServerBindAddress(string address, IPAddressType addressType) - { - _serverBindAddress = address; - } - /// - /// Sets which port to use. - /// - /// - public override void SetPort(ushort port) - { - _port = port; - } - /// - /// Returns the adjusted timeout as float - /// - /// - public override float GetTimeout(bool asServer) - { - return _timeout; - } - #endregion - - #region Start and stop. - /// - /// Starts the local server or client using configured settings. - /// - /// True to start server. - public override bool StartConnection(bool server) - { - Debug.Log("StartConnection fishy server: " + server); - - if (server) - return StartServer(); - else - return StartClient(_clientAddress); - } - - /// - /// Stops the local server or client. - /// - /// True to stop server. - public override bool StopConnection(bool server) - { - if (server) - return StopServer(); - else - return StopClient(); - } - - /// - /// Stops a remote client from the server, disconnecting the client. - /// - /// ConnectionId of the client to disconnect. - /// True to abrutly stp the client socket without waiting socket thread. - public override bool StopConnection(int connectionId, bool immediately) - { - return StopClient(connectionId, immediately); - } - - /// - /// Stops both client and server. - /// - public override void Shutdown() - { - //Stops client then server connections. - StopConnection(false); - StopConnection(true); - } - - #region Privates. - /// - /// Starts server. - /// - /// True if there were no blocks. A true response does not promise a socket will or has connected. - private bool StartServer() - { - bool clientRunning = false; -#if !UNITY_SERVER - if (!SteamClient.IsValid) - { - Debug.LogError("Steam Facepunch not initialized. Server could not be started."); - return false; - } - //if (_client.GetLocalConnectionState() != LocalConnectionState.Stopped) - //{ - // Debug.LogError("Server cannot run while client is running."); - // return false; - //} - - clientRunning = (_client.GetLocalConnectionState() != LocalConnectionState.Stopped); - /* If remote _client is running then stop it - * and start the client host variant. */ - if (clientRunning) - _client.StopConnection(); -#endif - - _server.ResetInvalidSocket(); - if (_server.GetLocalConnectionState() != LocalConnectionState.Stopped) - { - Debug.LogError("Server is already running."); - return false; - } - InitializeRelayNetworkAccess(); - - bool result = _server.StartConnection(_serverBindAddress, _port, _maximumClients); - - //If need to restart client. - if (result && clientRunning) - StartConnection(false); - - return result; - } - - /// - /// Stops server. - /// - private bool StopServer() - { - return _server.StopConnection(); - } - - /// - /// Starts the client. - /// - /// - /// True if there were no blocks. A true response does not promise a socket will or has connected. - private bool StartClient(string address) - { - if (!SteamClient.IsValid) - { - Debug.LogError("Steam Facepunch not initialized. Client could not be started."); - return false; - } - - //If not acting as a host. - if (_server.GetLocalConnectionState() == LocalConnectionState.Stopped) - { - if (_client.GetLocalConnectionState() != LocalConnectionState.Stopped) - { - Debug.LogError("Client is already running."); - return false; - } - //Stop client host if running. - if (_clientHost.GetLocalConnectionState() != LocalConnectionState.Stopped) - _clientHost.StopConnection(); - //Initialize. - InitializeRelayNetworkAccess(); - - _client.StartConnection(address, _port); - } - //Acting as host. - else - { - _clientHost.StartConnection(_server); - } - - return true; - } - - /// - /// Stops the client. - /// - private bool StopClient() - { - bool result = false; - result |= _client.StopConnection(); - result |= _clientHost.StopConnection(); - return result; - } - - /// - /// Stops a remote client on the server. - /// - /// - /// True to abrutly stp the client socket without waiting socket thread. - private bool StopClient(int connectionId, bool immediately) - { - return _server.StopConnection(connectionId); - } - #endregion - #endregion - - #region Channels. - /// - /// Gets the MTU for a channel. This should take header size into consideration. - /// For example, if MTU is 1200 and a packet header for this channel is 10 in size, this method should return 1190. - /// - /// - /// - public override int GetMTU(byte channel) - { - if (channel >= _mtus.Length) - { - Debug.LogError($"Channel {channel} is out of bounds."); - return 0; - } - - return _mtus[channel]; - } - #endregion - } -} -#endif // !DISABLESTEAMWORKS \ No newline at end of file diff --git a/Assets/FishNet/Plugins/FishyFacepunch/FishyFacepunch.cs.meta b/Assets/FishNet/Plugins/FishyFacepunch/FishyFacepunch.cs.meta deleted file mode 100644 index 6482ab5..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/FishyFacepunch.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9da90c29836670c49809661c5c09cd5d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Plugins/FishyFacepunch/VERSION.txt b/Assets/FishNet/Plugins/FishyFacepunch/VERSION.txt deleted file mode 100644 index 7c32728..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/VERSION.txt +++ /dev/null @@ -1 +0,0 @@ -2.1.1 \ No newline at end of file diff --git a/Assets/FishNet/Plugins/FishyFacepunch/VERSION.txt.meta b/Assets/FishNet/Plugins/FishyFacepunch/VERSION.txt.meta deleted file mode 100644 index a6eeb74..0000000 --- a/Assets/FishNet/Plugins/FishyFacepunch/VERSION.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 1db9d679a4e8b8d4c9d5ab6cb2d3ad0f -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Authenticating.meta b/Assets/FishNet/Runtime/Authenticating.meta deleted file mode 100644 index 6915aae..0000000 --- a/Assets/FishNet/Runtime/Authenticating.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 0fcbb1078d7aa6d4c808c7913ed26092 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Authenticating/Authenticator.cs b/Assets/FishNet/Runtime/Authenticating/Authenticator.cs deleted file mode 100644 index 9272131..0000000 --- a/Assets/FishNet/Runtime/Authenticating/Authenticator.cs +++ /dev/null @@ -1,51 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing; -using System; -using UnityEngine; - -namespace FishNet.Authenticating -{ - /// - /// When inherited from this can be used to create a custom authentication process before clients may communicate with the server. - /// - public abstract class Authenticator : MonoBehaviour - { - #region Public. - /// - /// True if this authenticator has been intiialzied. - /// - public bool Initialized { get; private set; } - #endregion - - #region Protected. - /// - /// NetworkManager for this Authenticator. - /// - protected NetworkManager NetworkManager { get; private set; } - #endregion - - /// - /// Called when authenticator has concluded a result for a connection. Boolean is true if authentication passed, false if failed. - /// Server listens for this event automatically. - /// - public abstract event Action OnAuthenticationResult; - - /// - /// Initializes this script for use. - /// - /// - public virtual void InitializeOnce(NetworkManager networkManager) - { - NetworkManager = networkManager; - Initialized = true; - } - - /// - /// Called on the server immediately after a client connects. Can be used to send data to the client for authentication. - /// - /// Connection which is not yet authenticated. - public virtual void OnRemoteConnection(NetworkConnection connection) { } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Authenticating/Authenticator.cs.meta b/Assets/FishNet/Runtime/Authenticating/Authenticator.cs.meta deleted file mode 100644 index fe94f3f..0000000 --- a/Assets/FishNet/Runtime/Authenticating/Authenticator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a9adfb82407774645a1f455ceb9298f9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Broadcast.meta b/Assets/FishNet/Runtime/Broadcast.meta deleted file mode 100644 index 2268277..0000000 --- a/Assets/FishNet/Runtime/Broadcast.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 25caa1205d1af6742a85ede29e1a672e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Broadcast/Helping.meta b/Assets/FishNet/Runtime/Broadcast/Helping.meta deleted file mode 100644 index 06cb025..0000000 --- a/Assets/FishNet/Runtime/Broadcast/Helping.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 8d0473552b6e6834abb8a336d060797a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Broadcast/Helping/BroadcastHelper.cs b/Assets/FishNet/Runtime/Broadcast/Helping/BroadcastHelper.cs deleted file mode 100644 index c1452da..0000000 --- a/Assets/FishNet/Runtime/Broadcast/Helping/BroadcastHelper.cs +++ /dev/null @@ -1,19 +0,0 @@ -using FishNet.Object.Helping; - -namespace FishNet.Broadcast.Helping -{ - internal static class BroadcastHelper - { - /// - /// Gets the key for a broadcast type. - /// - /// - /// - /// - public static ushort GetKey() - { - return typeof(T).FullName.GetStableHash16(); - } - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Broadcast/Helping/BroadcastHelper.cs.meta b/Assets/FishNet/Runtime/Broadcast/Helping/BroadcastHelper.cs.meta deleted file mode 100644 index c8e4514..0000000 --- a/Assets/FishNet/Runtime/Broadcast/Helping/BroadcastHelper.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c314af08d630630449b7b7af740b9c7d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Broadcast/IBroadcast.cs b/Assets/FishNet/Runtime/Broadcast/IBroadcast.cs deleted file mode 100644 index 5fe07f2..0000000 --- a/Assets/FishNet/Runtime/Broadcast/IBroadcast.cs +++ /dev/null @@ -1,8 +0,0 @@ - -namespace FishNet.Broadcast -{ - /// - /// Include this interface on types intended to be used with Broadcast. - /// - public interface IBroadcast { } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Broadcast/IBroadcast.cs.meta b/Assets/FishNet/Runtime/Broadcast/IBroadcast.cs.meta deleted file mode 100644 index c63e51a..0000000 --- a/Assets/FishNet/Runtime/Broadcast/IBroadcast.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 88ec864df25feed49bdcdab7f880531d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Config.json b/Assets/FishNet/Runtime/Config.json deleted file mode 100644 index a2e3019..0000000 --- a/Assets/FishNet/Runtime/Config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "StripReleaseBuilds": true -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Config.json.meta b/Assets/FishNet/Runtime/Config.json.meta deleted file mode 100644 index baa766c..0000000 --- a/Assets/FishNet/Runtime/Config.json.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 9f1ece47c2d48194ea4827bf592a2279 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Connection.meta b/Assets/FishNet/Runtime/Connection.meta deleted file mode 100644 index 4658695..0000000 --- a/Assets/FishNet/Runtime/Connection.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: bc8933915f599d44d98ae151e3fd0da7 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Connection/Buffer.cs b/Assets/FishNet/Runtime/Connection/Buffer.cs deleted file mode 100644 index 404d31e..0000000 --- a/Assets/FishNet/Runtime/Connection/Buffer.cs +++ /dev/null @@ -1,259 +0,0 @@ -using FishNet.Managing; -using FishNet.Managing.Logging; -using FishNet.Managing.Transporting; -using FishNet.Serializing; -using FishNet.Utility.Performance; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.Connection -{ - /// - /// A byte buffer that automatically resizes. - /// - internal class ByteBuffer - { - /// - /// How many more bytes may fit into the buffer. - /// - internal int Remaining => (Size - Length); - /// - /// Buffer data. - /// - internal byte[] Data { get; private set; } - /// - /// How many bytes currently into Data. This will include the reserve. - /// - internal int Length { get; private set; } - /// - /// Size of the buffer. Data.Length may exceed this value as it uses a pooled array. - /// - internal int Size { get; private set; } - /// - /// True if data has been written. - /// - internal bool HasData { get; private set; } - /// - /// Bytes to reserve when resetting. - /// - private int _reserve; - - internal ByteBuffer(int size, int reserve = 0) - { - Data = ByteArrayPool.Retrieve(size); - Size = size; - _reserve = reserve; - Reset(); - } - - public void Dispose() - { - if (Data != null) - ByteArrayPool.Store(Data); - Data = null; - } - - /// - /// Resets instance without clearing Data. - /// - internal void Reset() - { - Length = _reserve; - HasData = false; - } - - /// - /// Copies segments without error checking, including tick for the first time data is added. - /// - /// - internal void CopySegment(uint tick, ArraySegment segment) - { - /* If data has not been written to buffer yet - * then write tick to the start. */ - if (!HasData) - { - int pos = 0; - WriterExtensions.WriteUInt32(Data, tick, ref pos); - } - - Buffer.BlockCopy(segment.Array, segment.Offset, Data, Length, segment.Count); - Length += segment.Count; - HasData = true; - } - /// - /// Copies segments without error checking. - /// - /// - internal void CopySegment(ArraySegment segment) - { - Buffer.BlockCopy(segment.Array, segment.Offset, Data, Length, segment.Count); - Length += segment.Count; - HasData = true; - } - - } - - internal class PacketBundle - { - /// - /// True if data has been written. - /// - internal bool HasData => _buffers[0].HasData; - /// - /// All buffers written. Collection is not cleared when reset but rather the index in which to write is. - /// - private List _buffers = new List(); - /// - /// Buffer which is being written to. - /// - private int _bufferIndex; - /// - /// Maximum size packet the transport can handle. - /// - private int _maximumTransportUnit; - /// - /// Number of buffers written to. Will return 0 if nothing has been written. - /// - public int WrittenBuffers => (!HasData) ? 0 : (_bufferIndex + 1); - /// - /// Number of bytes to reserve at the beginning of each buffer. - /// - private int _reserve; - /// - /// NetworkManager this is for. - /// - private NetworkManager _networkManager; - - internal PacketBundle(NetworkManager manager, int mtu, int reserve = 0) - { - //Allow bytes for the tick. - reserve += TransportManager.TICK_BYTES; - - _networkManager = manager; - _maximumTransportUnit = mtu; - _reserve = reserve; - AddBuffer(); - - Reset(); - } - - public void Dispose() - { - for (int i = 0; i < _buffers.Count; i++) - _buffers[i].Dispose(); - } - - /// - /// Adds a buffer using current settings. - /// - private ByteBuffer AddBuffer() - { - ByteBuffer ba = new ByteBuffer(_maximumTransportUnit, _reserve); - _buffers.Add(ba); - return ba; - } - - /// - /// Resets using current settings. - /// - internal void Reset() - { - _bufferIndex = 0; - - for (int i = 0; i < _buffers.Count; i++) - _buffers[i].Reset(); - } - - /// - /// Writes a segment to this packet bundle using the current WriteIndex. - /// - /// True to force data into a new buffer. - internal void Write(ArraySegment segment, bool forceNewBuffer = false) - { - //Nothing to be written. - if (segment.Count == 0) - return; - - /* If the segment count is larger than the mtu then - * something went wrong. Nothing should call this method - * directly except the TransportManager, which will automatically - * split packets that exceed MTU into reliable ordered. */ - if (segment.Count > _maximumTransportUnit) - { - _networkManager.LogError($"Segment is length of {segment.Count} while MTU is {_maximumTransportUnit}. Packet was not split properly and will not be sent."); - return; - } - - ByteBuffer ba = _buffers[_bufferIndex]; - /* Make a new buffer if... - * forcing a new buffer and data has already been written to the current. - * or--- - * segment.Count is more than what is remaining in the buffer. */ - bool useNewBuffer = (forceNewBuffer && ba.Length > _reserve) || - (segment.Count > ba.Remaining); - if (useNewBuffer) - { - _bufferIndex++; - //If need to make a new buffer then do so. - if (_buffers.Count <= _bufferIndex) - { - ba = AddBuffer(); - } - else - { - ba = _buffers[_bufferIndex]; - ba.Reset(); - } - } - - uint tick = _networkManager.TimeManager.LocalTick; - ba.CopySegment(tick, segment); - } - - /// - /// Gets a buffer for the specified index. Returns true and outputs the buffer if it was successfully found. - /// - /// Index of the buffer to retrieve. - /// Buffer retrieved from the list. Null if the specified buffer was not found. - internal bool GetBuffer(int index, out ByteBuffer bb) - { - bb = null; - - if (index >= _buffers.Count || index < 0) - { - _networkManager.LogError($"Index of {index} is out of bounds. There are {_buffers.Count} available."); - return false; - } - if (index > _bufferIndex) - { - _networkManager.LogError($"Index of {index} exceeds the number of written buffers. There are {WrittenBuffers} written buffers."); - return false; - } - - bb = _buffers[index]; - return bb.HasData; - } - - /// - /// Returns a PacketBundle for a channel. ResetPackets must be called afterwards. - /// - /// - /// True if PacketBundle is valid on the index and contains data. - internal static bool GetPacketBundle(int channel, List bundles, out PacketBundle mtuBuffer) - { - //Out of bounds. - if (channel >= bundles.Count) - { - mtuBuffer = null; - return false; - } - - mtuBuffer = bundles[channel]; - return mtuBuffer.HasData; - } - } - - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Connection/Buffer.cs.meta b/Assets/FishNet/Runtime/Connection/Buffer.cs.meta deleted file mode 100644 index 85d9ae8..0000000 --- a/Assets/FishNet/Runtime/Connection/Buffer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: eb2f3ce9b5ac27f40b7daa9364fb4d60 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Connection/NetworkConnection.Buffer.cs b/Assets/FishNet/Runtime/Connection/NetworkConnection.Buffer.cs deleted file mode 100644 index 76721e3..0000000 --- a/Assets/FishNet/Runtime/Connection/NetworkConnection.Buffer.cs +++ /dev/null @@ -1,110 +0,0 @@ -using FishNet.Broadcast; -using FishNet.Managing; -using FishNet.Managing.Logging; -using FishNet.Managing.Transporting; -using FishNet.Transporting; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.Connection -{ - public partial class NetworkConnection - { - - #region Private. - /// - /// PacketBundles to send to this connection. An entry will be made for each channel. - /// - private List _toClientBundles = new List(); - /// - /// True if this object has been dirtied. - /// - private bool _serverDirtied; - #endregion - - /// - /// Initializes this script. - /// - private void InitializeBuffer() - { - for (byte i = 0; i < TransportManager.CHANNEL_COUNT; i++) - { - int mtu = NetworkManager.TransportManager.GetLowestMTU(i); - _toClientBundles.Add(new PacketBundle(NetworkManager, mtu)); - } - } - - - /// - /// Sends a broadcast to this connection. - /// - /// Type of broadcast to send. - /// Broadcast data being sent; for example: an instance of your broadcast type. - /// True if the client must be authenticated for this broadcast to send. - /// Channel to send on. - public void Broadcast(T message, bool requireAuthenticated = true, Channel channel = Channel.Reliable) where T : struct, IBroadcast - { - if (!IsActive) - NetworkManager.LogError($"Connection is not valid, cannot send broadcast."); - else - NetworkManager.ServerManager.Broadcast(this, message, requireAuthenticated, channel); - } - - /// - /// Sends data from the server to a client. - /// - /// True to force data into a new buffer. - internal void SendToClient(byte channel, ArraySegment segment, bool forceNewBuffer = false) - { - //Cannot send data when disconnecting. - if (Disconnecting) - return; - - if (!IsActive) - { - NetworkManager.LogWarning($"Data cannot be sent to connection {ClientId} because it is not active."); - return; - } - //If channel is out of bounds then default to the first channel. - if (channel >= _toClientBundles.Count) - channel = 0; - - _toClientBundles[channel].Write(segment, forceNewBuffer); - ServerDirty(); - } - - /// - /// Returns a PacketBundle for a channel. ResetPackets must be called afterwards. - /// - /// - /// True if PacketBundle is valid on the index and contains data. - internal bool GetPacketBundle(int channel, out PacketBundle packetBundle) - { - return PacketBundle.GetPacketBundle(channel, _toClientBundles, out packetBundle); - } - - /// - /// Indicates the server has data to send to this connection. - /// - private void ServerDirty() - { - bool wasDirty = _serverDirtied; - _serverDirtied = true; - - //If not yet dirty then tell transport manager this is dirty. - if (!wasDirty) - NetworkManager.TransportManager.ServerDirty(this); - } - - /// - /// Resets that there is data to send. - /// - internal void ResetServerDirty() - { - _serverDirtied = false; - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Connection/NetworkConnection.Buffer.cs.meta b/Assets/FishNet/Runtime/Connection/NetworkConnection.Buffer.cs.meta deleted file mode 100644 index 2b3f00e..0000000 --- a/Assets/FishNet/Runtime/Connection/NetworkConnection.Buffer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5bc17ee5bac499347a6fbad9dd24b7b0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Connection/NetworkConnection.LOD.cs b/Assets/FishNet/Runtime/Connection/NetworkConnection.LOD.cs deleted file mode 100644 index 771e2ad..0000000 --- a/Assets/FishNet/Runtime/Connection/NetworkConnection.LOD.cs +++ /dev/null @@ -1,48 +0,0 @@ -using FishNet.Object; -using System; -using System.Collections.Generic; - -namespace FishNet.Connection -{ - - /// - /// A container for a connected client used to perform actions on and gather information for the declared client. - /// - public partial class NetworkConnection : IEquatable - { - /// - /// Level of detail for each NetworkObject. - /// Since this is called frequently this field is intentionally not an accessor to increase performance. - /// - public Dictionary LevelOfDetails = new Dictionary(); - /// - /// Number oftimes this connection may send a forced LOD update. - /// - internal int AllowedForcedLodUpdates; - /// - /// Last tick an LOD was sent. - /// On client and clientHost this is LocalTick. - /// On server only this is LastPacketTick for the connection. - /// - internal uint LastLevelOfDetailUpdate; - /// - /// Returns if the client has not sent an LOD update for expectedInterval. - /// - /// - internal bool IsLateForLevelOfDetail(uint expectedInterval) - { - //Local client is immune since server and client share ticks. - if (IsLocalClient) - return false; - - return ((LastPacketTick - LastLevelOfDetailUpdate) > expectedInterval); - } - - /// - /// Number of level of detail update infractions for this connection. - /// - internal int LevelOfDetailInfractions; - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Connection/NetworkConnection.LOD.cs.meta b/Assets/FishNet/Runtime/Connection/NetworkConnection.LOD.cs.meta deleted file mode 100644 index ada1054..0000000 --- a/Assets/FishNet/Runtime/Connection/NetworkConnection.LOD.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d9aba23f6fe8fd849a39712926efe055 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Connection/NetworkConnection.PingPong.cs b/Assets/FishNet/Runtime/Connection/NetworkConnection.PingPong.cs deleted file mode 100644 index 5e2feb4..0000000 --- a/Assets/FishNet/Runtime/Connection/NetworkConnection.PingPong.cs +++ /dev/null @@ -1,103 +0,0 @@ -using FishNet.Managing; -using FishNet.Managing.Timing; -using System; -using UnityEngine; - -namespace FishNet.Connection -{ - - /// - /// A container for a connected client used to perform actions on and gather information for the declared client. - /// - public partial class NetworkConnection : IEquatable - { -#pragma warning disable CS0414 - #region Private. - /// - /// Last tick this connection sent a ping. - /// - private uint _lastPingTick; - /// - /// Number of times client has excessively sent a ping. - /// - private float _excessivePingCount; - /// - /// Ticks expected between each ping. - /// - private uint _requiredPingTicks; - #endregion - - #region Const. - /// - /// Number of times a ping may occur excessively before server will punish connection. - /// - private const byte EXCESSIVE_PING_LIMIT = 10; - #endregion -#pragma warning restore CS0414 - /// - /// Initializes for ping. - /// - private void InitializePing() - { - //Give the client some room for error. - float requiredInterval = (NetworkManager.TimeManager.PingInterval * 0.85f); - //Round down so required ticks is lower. - _requiredPingTicks = NetworkManager.TimeManager.TimeToTicks(requiredInterval, TickRounding.RoundDown); - } - - - /// - /// Resets PingPong values. - /// - private void ResetPingPong() - { - _excessivePingCount = 0; - _lastPingTick = 0; - } - - /// - /// Called when a ping is received from this connection. Returns if can respond to ping. - /// - /// True to respond to ping, false to kick connection. - internal bool CanPingPong() - { - /* Only check ping conditions in build. Editors are prone to pausing which can - * improperly kick clients. */ -#if UNITY_EDITOR - return true; -#else - TimeManager tm = (NetworkManager == null) ? InstanceFinder.TimeManager : NetworkManager.TimeManager; - //Server FPS is running low, timing isn't reliable enough to kick clients. - if (tm.LowFrameRate) - return true; - - uint currentTick = tm.Tick; - uint difference = (currentTick - _lastPingTick); - _lastPingTick = currentTick; - - //Ping sent too quickly. - if (difference < _requiredPingTicks) - { - _excessivePingCount += 1f; - //Ping limit hit. - if (_excessivePingCount >= EXCESSIVE_PING_LIMIT) - { - NetworkManager.LogWarning($"Kicked connectionId {ClientId} for excessive pings."); - Disconnect(true); - } - - //Return to not send pong back. - return false; - } - //Ping isnt too fast. - else - { - _excessivePingCount = UnityEngine.Mathf.Max(0f, _excessivePingCount - 0.5f); - return true; - } -#endif - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Connection/NetworkConnection.PingPong.cs.meta b/Assets/FishNet/Runtime/Connection/NetworkConnection.PingPong.cs.meta deleted file mode 100644 index edf2c73..0000000 --- a/Assets/FishNet/Runtime/Connection/NetworkConnection.PingPong.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 20633bf6995f6534ba2b27e1eab3054d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Connection/NetworkConnection.QOL.cs b/Assets/FishNet/Runtime/Connection/NetworkConnection.QOL.cs deleted file mode 100644 index 817b74f..0000000 --- a/Assets/FishNet/Runtime/Connection/NetworkConnection.QOL.cs +++ /dev/null @@ -1,69 +0,0 @@ -using FishNet.Managing; -using FishNet.Managing.Logging; -using FishNet.Managing.Server; -using FishNet.Serializing; -using System; - -namespace FishNet.Connection -{ - - /// - /// A container for a connected client used to perform actions on and gather information for the declared client. - /// - public partial class NetworkConnection : IEquatable - { - - #region Public. - /// - /// Returns true if this connection is a clientHost. - /// - public bool IsHost => (NetworkManager == null) ? false : (NetworkManager.IsServer && (this == NetworkManager.ClientManager.Connection)); - /// - /// Returns if this connection is for the local client. - /// - public bool IsLocalClient => (NetworkManager == null) ? false : (NetworkManager.ClientManager.Connection == this); - #endregion - - /// - /// Returns the address of this connection. - /// - /// - public string GetAddress() - { - if (!IsValid) - return string.Empty; - if (NetworkManager == null) - return string.Empty; - - return NetworkManager.TransportManager.Transport.GetConnectionAddress(ClientId); - } - - /// - /// Kicks a connection immediately while invoking OnClientKick. - /// - /// Reason client is being kicked. - /// How to print logging as. - /// Optional message to be debug logged. - public void Kick(KickReason kickReason, LoggingType loggingType = LoggingType.Common, string log = "") - { - NetworkManager.ServerManager.Kick(this, kickReason, loggingType, log); - } - - - /// - /// Kicks a connection immediately while invoking OnClientKick. - /// - /// Reader to clear before kicking. - /// Reason client is being kicked. - /// How to print logging as. - /// Optional message to be debug logged. - public void Kick(Reader reader, KickReason kickReason, LoggingType loggingType = LoggingType.Common, string log = "") - { - NetworkManager.ServerManager.Kick(this, reader, kickReason, loggingType, log); - } - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Connection/NetworkConnection.QOL.cs.meta b/Assets/FishNet/Runtime/Connection/NetworkConnection.QOL.cs.meta deleted file mode 100644 index b92ca8e..0000000 --- a/Assets/FishNet/Runtime/Connection/NetworkConnection.QOL.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7d45abc242399194b85e6c16bcb3676b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Connection/NetworkConnection.cs b/Assets/FishNet/Runtime/Connection/NetworkConnection.cs deleted file mode 100644 index 1383f80..0000000 --- a/Assets/FishNet/Runtime/Connection/NetworkConnection.cs +++ /dev/null @@ -1,404 +0,0 @@ -using FishNet.Documenting; -using FishNet.Managing; -using FishNet.Object; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine.SceneManagement; - -namespace FishNet.Connection -{ - - /// - /// A container for a connected client used to perform actions on and gather information for the declared client. - /// - public partial class NetworkConnection : IEquatable - { - - #region Public. - /// - /// Called after this connection has loaded start scenes. Boolean will be true if asServer. Available to this connection and server. - /// - public event Action OnLoadedStartScenes; - /// - /// Called after connection gains ownership of an object, and after the object has been added to Objects. Available to this connection and server. - /// - public event Action OnObjectAdded; - /// - /// Called after connection loses ownership of an object, and after the object has been removed from Objects. Available to this connection and server. - /// - public event Action OnObjectRemoved; - /// - /// NetworkManager managing this class. - /// - public NetworkManager NetworkManager { get; private set; } - /// - /// True if connection has loaded start scenes. Available to this connection and server. - /// - public bool LoadedStartScenes() => (_loadedStartScenesAsServer || _loadedStartScenesAsClient); - /// - /// - /// - public bool LoadedStartScenes(bool asServer) - { - if (asServer) - return _loadedStartScenesAsServer; - else - return _loadedStartScenesAsClient; - } - /// - /// True if loaded start scenes as server. - /// - private bool _loadedStartScenesAsServer; - /// - /// True if loaded start scenes as client. - /// - private bool _loadedStartScenesAsClient; - /// - /// ObjectIds to use for predicted spawning. - /// - internal Queue PredictedObjectIds = new Queue(); - /// - /// True if this connection is authenticated. Only available to server. - /// - public bool Authenticated { get; private set; } - /// - /// True if this connection IsValid and not Disconnecting. - /// - public bool IsActive => (ClientId >= 0 && !Disconnecting); - /// - /// True if this connection is valid. An invalid connection indicates no client is set for this reference. - /// - public bool IsValid => (ClientId >= 0); - /// - /// Unique Id for this connection. - /// - public int ClientId = -1; - /// - /// - /// - private HashSet _objects = new HashSet(); - /// - /// Objects owned by this connection. Available to this connection and server. - /// - public IReadOnlyCollection Objects => _objects; - /// - /// The first object within Objects. - /// - public NetworkObject FirstObject { get; private set; } - /// - /// Scenes this connection is in. Available to this connection and server. - /// - public HashSet Scenes { get; private set; } = new HashSet(); - /// - /// True if this connection is being disconnected. Only available to server. - /// - public bool Disconnecting { get; private set; } - /// - /// Tick when Disconnecting was set. - /// - internal uint DisconnectingTick { get; private set; } - /// - /// Custom data associated with this connection which may be modified by the user. - /// The value of this field are not synchronized over the network. - /// - public object CustomData = null; - /// - /// Local tick when the connection last replicated. - /// - public uint LocalReplicateTick { get; internal set; } - /// - /// Tick of the last packet received from this connection. - /// This value is only available on the server. - /// - /* This is not used internally. At this time it's just - * here for the users convienence. */ - public uint LastPacketTick { get; private set; } - /// - /// Sets LastPacketTick value. - /// - /// - internal void SetLastPacketTick(uint value) - { - //If new largest tick from the client then update client tick data. - if (value > LastPacketTick) - { - _latestTick = value; - _serverLatestTick = NetworkManager.TimeManager.Tick; - } - LastPacketTick = value; - } - /// - /// Latest tick that did not arrive out of order from this connection. - /// - private uint _latestTick; - /// - /// Tick on the server when latestTick was set. - /// - private uint _serverLatestTick; - [Obsolete("Use LocalTick instead.")] //Remove on 2023/06/01 - public uint Tick => LocalTick; - /// - /// Current approximate local tick as it is on this connection. - /// - public uint LocalTick - { - get - { - NetworkManager nm = NetworkManager; - if (nm != null) - { - uint diff = (nm.TimeManager.Tick - _serverLatestTick); - return (diff + _latestTick); - } - - //Fall through, could not process. - return 0; - } - - } - #endregion - - #region Const. - /// - /// Value used when ClientId has not been set. - /// - public const int UNSET_CLIENTID_VALUE = -1; - #endregion - - #region Comparers. - public override bool Equals(object obj) - { - if (obj is NetworkConnection nc) - return (nc.ClientId == this.ClientId); - else - return false; - } - public bool Equals(NetworkConnection nc) - { - if (nc is null) - return false; - //If either is -1 Id. - if (this.ClientId == NetworkConnection.UNSET_CLIENTID_VALUE || nc.ClientId == NetworkConnection.UNSET_CLIENTID_VALUE) - return false; - //Same object. - if (System.Object.ReferenceEquals(this, nc)) - return true; - - return (this.ClientId == nc.ClientId); - } - public override int GetHashCode() - { - return ClientId; - } - public static bool operator ==(NetworkConnection a, NetworkConnection b) - { - if (a is null && b is null) - return true; - if (a is null && !(b is null)) - return false; - - return (b == null) ? a.Equals(b) : b.Equals(a); - } - public static bool operator !=(NetworkConnection a, NetworkConnection b) - { - return !(a == b); - } - #endregion - - [APIExclude] - public NetworkConnection() { } - [APIExclude] - public NetworkConnection(NetworkManager manager, int clientId, bool asServer) - { - Initialize(manager, clientId, asServer); - } - - public void Dispose() - { - foreach (PacketBundle p in _toClientBundles) - p.Dispose(); - _toClientBundles.Clear(); - } - - /// - /// Initializes this for use. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void Initialize(NetworkManager nm, int clientId, bool asServer) - { - NetworkManager = nm; - ClientId = clientId; - //Only the server uses the ping and buffer. - if (asServer) - { - InitializeBuffer(); - InitializePing(); - } - } - - /// - /// Resets this instance. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void Reset() - { - _latestTick = 0; - _serverLatestTick = 0; - LastPacketTick = 0; - ClientId = -1; - ClearObjects(); - Authenticated = false; - NetworkManager = null; - _loadedStartScenesAsClient = false; - _loadedStartScenesAsServer = false; - SetDisconnecting(false); - Scenes.Clear(); - PredictedObjectIds.Clear(); - ResetPingPong(); - LevelOfDetails.Clear(); - AllowedForcedLodUpdates = 0; - LastLevelOfDetailUpdate = 0; - LevelOfDetailInfractions = 0; - } - - /// - /// Sets Disconnecting boolean for this connection. - /// - internal void SetDisconnecting(bool value) - { - Disconnecting = value; - if (Disconnecting) - DisconnectingTick = NetworkManager.TimeManager.LocalTick; - } - - /// - /// Disconnects this connection. - /// - /// True to disconnect immediately. False to send any pending data first. - public void Disconnect(bool immediately) - { - if (Disconnecting) - { - NetworkManager.LogWarning($"ClientId {ClientId} is already disconnecting."); - return; - } - - SetDisconnecting(true); - //If immediately then force disconnect through transport. - if (immediately) - NetworkManager.TransportManager.Transport.StopConnection(ClientId, true); - //Otherwise mark dirty so server will push out any pending information, and then disconnect. - else - ServerDirty(); - } - - /// - /// Returns if just loaded start scenes and sets them as loaded if not. - /// - /// - internal bool SetLoadedStartScenes(bool asServer) - { - bool loadedToCheck = (asServer) ? _loadedStartScenesAsServer : _loadedStartScenesAsClient; - //Result becomes true if not yet loaded start scenes. - bool result = !loadedToCheck; - if (asServer) - _loadedStartScenesAsServer = true; - else - _loadedStartScenesAsClient = true; - - OnLoadedStartScenes?.Invoke(this, asServer); - - return result; - } - - /// - /// Sets connection as authenticated. - /// - internal void ConnectionAuthenticated() - { - Authenticated = true; - } - - /// - /// Adds to Objects owned by this connection. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void AddObject(NetworkObject nob) - { - _objects.Add(nob); - //If adding the first object then set new FirstObject. - if (_objects.Count == 1) - FirstObject = nob; - - OnObjectAdded?.Invoke(nob); - } - - /// - /// Removes from Objects owned by this connection. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void RemoveObject(NetworkObject nob) - { - _objects.Remove(nob); - //If removing the first object then set a new one. - if (nob == FirstObject) - SetFirstObject(); - - OnObjectRemoved?.Invoke(nob); - } - - /// - /// Clears all Objects. - /// - private void ClearObjects() - { - _objects.Clear(); - FirstObject = null; - } - - /// - /// Sets FirstObject using the first element in Objects. - /// - private void SetFirstObject() - { - if (_objects.Count == 0) - { - FirstObject = null; - } - else - { - foreach (NetworkObject nob in Objects) - { - FirstObject = nob; - break; - } - } - } - - /// - /// Adds a scene to this connections Scenes. - /// - /// - /// - internal bool AddToScene(Scene scene) - { - return Scenes.Add(scene); - } - - /// - /// Removes a scene to this connections Scenes. - /// - /// - /// - internal bool RemoveFromScene(Scene scene) - { - return Scenes.Remove(scene); - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Connection/NetworkConnection.cs.meta b/Assets/FishNet/Runtime/Connection/NetworkConnection.cs.meta deleted file mode 100644 index 20973ee..0000000 --- a/Assets/FishNet/Runtime/Connection/NetworkConnection.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 01c7bfc71e29621408451fa2fa6b1a0b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Documenting.meta b/Assets/FishNet/Runtime/Documenting.meta deleted file mode 100644 index 213ed84..0000000 --- a/Assets/FishNet/Runtime/Documenting.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 0478042f95cb685419656df549fdd04c -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Documenting/Attributes.cs b/Assets/FishNet/Runtime/Documenting/Attributes.cs deleted file mode 100644 index c25e901..0000000 --- a/Assets/FishNet/Runtime/Documenting/Attributes.cs +++ /dev/null @@ -1,8 +0,0 @@ - -using System; - -namespace FishNet.Documenting -{ - public class APIExcludeAttribute : Attribute { } - -} diff --git a/Assets/FishNet/Runtime/Documenting/Attributes.cs.meta b/Assets/FishNet/Runtime/Documenting/Attributes.cs.meta deleted file mode 100644 index 5c4e30d..0000000 --- a/Assets/FishNet/Runtime/Documenting/Attributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9d101aaaeb244ac48bfe2d7d05308c1c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/CodeStripping.cs b/Assets/FishNet/Runtime/Editor/CodeStripping.cs deleted file mode 100644 index 3946666..0000000 --- a/Assets/FishNet/Runtime/Editor/CodeStripping.cs +++ /dev/null @@ -1,118 +0,0 @@ - -using FishNet.Configuring; -using System.IO; -using UnityEngine; -using System.Xml.Serialization; - -#if UNITY_EDITOR -using FishNet.Editing.PrefabCollectionGenerator; -using UnityEditor.Compilation; -using UnityEditor.Build.Reporting; -using UnityEditor; -using UnityEditor.Build; -#endif - -namespace FishNet.Configuring -{ - - - public class CodeStripping - - { - - /// - /// True if making a release build for client. - /// - public static bool ReleasingForClient => (Configuration.Configurations.CodeStripping.IsBuilding && !Configuration.Configurations.CodeStripping.IsHeadless && !Configuration.Configurations.CodeStripping.IsDevelopment); - /// - /// True if making a release build for server. - /// - public static bool ReleasingForServer => (Configuration.Configurations.CodeStripping.IsBuilding && Configuration.Configurations.CodeStripping.IsHeadless && !Configuration.Configurations.CodeStripping.IsDevelopment); - /// - /// Returns if to remove server logic. - /// - /// - public static bool RemoveServerLogic - { - get - { - - - /* This is to protect non pro users from enabling this - * without the extra logic code. */ -#pragma warning disable CS0162 // Unreachable code detected - return false; -#pragma warning restore CS0162 // Unreachable code detected - } - } - /// - /// True if building and stripping is enabled. - /// - public static bool StripBuild - { - get - { - - - /* This is to protect non pro users from enabling this - * without the extra logic code. */ -#pragma warning disable CS0162 // Unreachable code detected - return false; -#pragma warning restore CS0162 // Unreachable code detected - } - } - /// - /// Technique to strip methods. - /// - public static StrippingTypes StrippingType => (StrippingTypes)Configuration.Configurations.CodeStripping.StrippingType; - - private static object _compilationContext; - public int callbackOrder => 0; -#if UNITY_EDITOR - - public void OnPreprocessBuild(BuildReport report) - { - Generator.IgnorePostProcess = true; - Generator.GenerateFull(); - CompilationPipeline.compilationStarted += CompilationPipelineOnCompilationStarted; - CompilationPipeline.compilationFinished += CompilationPipelineOnCompilationFinished; - - - } - /* Solution for builds ending with errors and not triggering OnPostprocessBuild. - * Link: https://gamedev.stackexchange.com/questions/181611/custom-build-failure-callback - */ - private void CompilationPipelineOnCompilationStarted(object compilationContext) - { - _compilationContext = compilationContext; - } - - private void CompilationPipelineOnCompilationFinished(object compilationContext) - { - if (compilationContext != _compilationContext) - return; - - _compilationContext = null; - - CompilationPipeline.compilationStarted -= CompilationPipelineOnCompilationStarted; - CompilationPipeline.compilationFinished -= CompilationPipelineOnCompilationFinished; - - BuildingEnded(); - } - - private void BuildingEnded() - { - - - Generator.IgnorePostProcess = false; - } - - public void OnPostprocessBuild(BuildReport report) - { - - BuildingEnded(); - } -#endif - } - -} diff --git a/Assets/FishNet/Runtime/Editor/CodeStripping.cs.meta b/Assets/FishNet/Runtime/Editor/CodeStripping.cs.meta deleted file mode 100644 index dec4f86..0000000 --- a/Assets/FishNet/Runtime/Editor/CodeStripping.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0c7409efe2f84e7428d5c6c97ed7d32e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Configuring.meta b/Assets/FishNet/Runtime/Editor/Configuring.meta deleted file mode 100644 index bf77916..0000000 --- a/Assets/FishNet/Runtime/Editor/Configuring.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e789fd90a3d65864bbead2949dbdbb36 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Configuring/ConfigurationData.cs b/Assets/FishNet/Runtime/Editor/Configuring/ConfigurationData.cs deleted file mode 100644 index 95127ee..0000000 --- a/Assets/FishNet/Runtime/Editor/Configuring/ConfigurationData.cs +++ /dev/null @@ -1,146 +0,0 @@ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Xml.Serialization; - -#if UNITY_EDITOR -using UnityEditor; -#endif - -namespace FishNet.Configuring -{ - - public enum StrippingTypes : int - { - Redirect = 0, - Empty_Experimental = 1, - } - public enum SearchScopeType : int - { - EntireProject = 0, - SpecificFolders = 1, - } - - public class PrefabGeneratorConfigurations - { - public bool Enabled = true; - public bool LogToConsole = true; - public bool FullRebuild = false; - public bool SaveChanges = true; - public string DefaultPrefabObjectsPath = Path.Combine("Assets", "DefaultPrefabObjects.asset"); - public int SearchScope = (int)SearchScopeType.EntireProject; - public List ExcludedFolders = new List(); - public List IncludedFolders = new List(); - } - - public class CodeStrippingConfigurations - { - public bool IsBuilding = false; - public bool IsDevelopment = false; - public bool IsHeadless = false; - public bool StripReleaseBuilds = false; - public int StrippingType = (int)StrippingTypes.Redirect; - } - - - public class ConfigurationData - { - //Non serialized doesn't really do anything, its just for me. - [System.NonSerialized] - public bool Loaded; - - public PrefabGeneratorConfigurations PrefabGenerator = new PrefabGeneratorConfigurations(); - public CodeStrippingConfigurations CodeStripping = new CodeStrippingConfigurations(); - } - - public static class ConfigurationDataExtension - { - /// - /// Returns if a differs from b. - /// - public static bool HasChanged(this ConfigurationData a, ConfigurationData b) - { - return (a.CodeStripping.StripReleaseBuilds != b.CodeStripping.StripReleaseBuilds); - } - /// - /// Copies all values from source to target. - /// - public static void CopyTo(this ConfigurationData source, ConfigurationData target) - { - target.CodeStripping.StripReleaseBuilds = source.CodeStripping.StripReleaseBuilds; - } - - - /// - /// Writes a configuration data. - /// - public static void Write(this ConfigurationData cd, bool refreshAssetDatabase) - { - /* Why is this a thing you ask? Because Unity makes it VERY difficult to read values from - * memory during builds since on some Unity versions the building application is on a different - * processor. In result instead of using memory to read configurationdata the values - * must be written to disk then load the disk values as needed. - * - * Fortunatelly the file is extremely small and this does not occur often at all. The disk read - * will occur once per script save, and once per assembly when building. */ - try - { - string path = Configuration.GetAssetsPath(Configuration.CONFIG_FILE_NAME); - XmlSerializer serializer = new XmlSerializer(typeof(ConfigurationData)); - TextWriter writer = new StreamWriter(path); - serializer.Serialize(writer, cd); - writer.Close(); -#if UNITY_EDITOR - if (refreshAssetDatabase) - { - AssetDatabase.SaveAssets(); - AssetDatabase.Refresh(); - } -#endif - } - catch (Exception ex) - { - throw new Exception($"An error occurred while writing ConfigurationData. Message: {ex.Message}"); - } - - } - - - /// - /// Writes a configuration data. - /// - public static void Write(this ConfigurationData cd, string path, bool refreshAssetDatabase) - { - /* Why is this a thing you ask? Because Unity makes it VERY difficult to read values from - * memory during builds since on some Unity versions the building application is on a different - * processor. In result instead of using memory to read configurationdata the values - * must be written to disk then load the disk values as needed. - * - * Fortunatelly the file is extremely small and this does not occur often at all. The disk read - * will occur once per script save, and once per assembly when building. */ - try - { - XmlSerializer serializer = new XmlSerializer(typeof(ConfigurationData)); - TextWriter writer = new StreamWriter(path); - serializer.Serialize(writer, cd); - writer.Close(); -#if UNITY_EDITOR - if (refreshAssetDatabase) - { - AssetDatabase.SaveAssets(); - AssetDatabase.Refresh(); - } -#endif - } - catch (Exception ex) - { - throw new Exception($"An error occurred while writing ConfigurationData. Message: {ex.Message}"); - } - - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Editor/Configuring/ConfigurationData.cs.meta b/Assets/FishNet/Runtime/Editor/Configuring/ConfigurationData.cs.meta deleted file mode 100644 index 95ea289..0000000 --- a/Assets/FishNet/Runtime/Editor/Configuring/ConfigurationData.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4be37e1b0afd29944ad4fa0b92ed8c7e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Configuring/ConfigurationEditor.cs b/Assets/FishNet/Runtime/Editor/Configuring/ConfigurationEditor.cs deleted file mode 100644 index 3b04bae..0000000 --- a/Assets/FishNet/Runtime/Editor/Configuring/ConfigurationEditor.cs +++ /dev/null @@ -1,126 +0,0 @@ -#if UNITY_EDITOR -using FishNet.Editing.PrefabCollectionGenerator; -using FishNet.Object; -using FishNet.Utility.Extension; -using FishNet.Utility.Performance; -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using UnityEngine.SceneManagement; - -namespace FishNet.Editing -{ - public class ConfigurationEditor : EditorWindow - { - - [MenuItem("Fish-Networking/Configuration", false, 0)] - public static void ShowConfiguration() - { - SettingsService.OpenProjectSettings("Project/Fish-Networking/Configuration"); - } - - } - - public class RebuildSceneIdMenu : MonoBehaviour - { - /// - /// Rebuilds sceneIds for open scenes. - /// - [MenuItem("Fish-Networking/Rebuild SceneIds", false, 20)] - public static void RebuildSceneIds() - { - int generatedCount = 0; - for (int i = 0; i < SceneManager.sceneCount; i++) - { - Scene s = SceneManager.GetSceneAt(i); - - ListCache nobs; - SceneFN.GetSceneNetworkObjects(s, false, out nobs); - for (int z = 0; z < nobs.Written; z++) - { - NetworkObject nob = nobs.Collection[z]; - nob.TryCreateSceneID(); - EditorUtility.SetDirty(nob); - } - generatedCount += nobs.Written; - - ListCaches.StoreCache(nobs); - } - - Debug.Log($"Generated sceneIds for {generatedCount} objects over {SceneManager.sceneCount} scenes. Please save your open scenes."); - } - - - } - - public class RefreshDefaultPrefabsMenu : MonoBehaviour - { - /// - /// Rebuilds the DefaultPrefabsCollection file. - /// - [MenuItem("Fish-Networking/Refresh Default Prefabs", false, 22)] - public static void RebuildDefaultPrefabs() - { - Debug.Log("Refreshing default prefabs."); - Generator.GenerateFull(null, true); - } - - } - - - public class RemoveDuplicateNetworkObjectsMenu : MonoBehaviour - { - /// - /// Iterates all network object prefabs in the project and open scenes, removing NetworkObject components which exist multiple times on a single object. - /// - [MenuItem("Fish-Networking/Remove Duplicate NetworkObjects", false, 21)] - - public static void RemoveDuplicateNetworkObjects() - { - List foundNobs = new List(); - - foreach (string path in Generator.GetPrefabFiles("Assets", new HashSet(), true)) - { - NetworkObject nob = AssetDatabase.LoadAssetAtPath(path); - if (nob != null) - foundNobs.Add(nob); - } - - //Now add scene objects. - for (int i = 0; i < SceneManager.sceneCount; i++) - { - Scene s = SceneManager.GetSceneAt(i); - - ListCache nobs; - SceneFN.GetSceneNetworkObjects(s, false, out nobs); - for (int z = 0; z < nobs.Written; z++) - { - NetworkObject nob = nobs.Collection[z]; - nob.TryCreateSceneID(); - EditorUtility.SetDirty(nob); - } - for (int z = 0; z < nobs.Written; z++) - foundNobs.Add(nobs.Collection[i]); - - ListCaches.StoreCache(nobs); - } - - //Remove duplicates. - int removed = 0; - foreach (NetworkObject nob in foundNobs) - { - int count = nob.RemoveDuplicateNetworkObjects(); - if (count > 0) - removed += count; - } - - Debug.Log($"Removed {removed} duplicate NetworkObjects. Please save your open scenes and project."); - } - - } - - - - -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Editor/Configuring/ConfigurationEditor.cs.meta b/Assets/FishNet/Runtime/Editor/Configuring/ConfigurationEditor.cs.meta deleted file mode 100644 index 1106133..0000000 --- a/Assets/FishNet/Runtime/Editor/Configuring/ConfigurationEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8135b3a4c31cfb74896f1e9e77059c89 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Configuring/Configuring.cs b/Assets/FishNet/Runtime/Editor/Configuring/Configuring.cs deleted file mode 100644 index a43925e..0000000 --- a/Assets/FishNet/Runtime/Editor/Configuring/Configuring.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System.IO; -using System.Xml.Serialization; -using UnityEngine; - -#if UNITY_EDITOR -using UnityEditor.Compilation; -using UnityEditor.Build.Reporting; -using UnityEditor; -using UnityEditor.Build; -#endif - -namespace FishNet.Configuring -{ - - - public class Configuration - { - - /// - /// - /// - private static ConfigurationData _configurations; - /// - /// ConfigurationData to use. - /// - public static ConfigurationData Configurations - { - get - { - if (_configurations == null) - _configurations = LoadConfigurationData(); - if (_configurations == null) - throw new System.Exception("Fish-Networking Configurations could not be loaded. Certain features such as code-stripping may not function."); - return _configurations; - } - private set - { - _configurations = value; - } - } - - /// - /// File name for configuration disk data. - /// - public const string CONFIG_FILE_NAME = "FishNet.Config.XML"; - - /// - /// Returns the path for the configuration file. - /// - /// - internal static string GetAssetsPath(string additional = "") - { - string a = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "Assets"); - if (additional != "") - a = Path.Combine(a, additional); - return a; - } - /// - /// Returns FishNetworking ConfigurationData. - /// - /// - internal static ConfigurationData LoadConfigurationData() - { - //return new ConfigurationData(); - if (_configurations == null || !_configurations.Loaded) - { - string configPath = GetAssetsPath(CONFIG_FILE_NAME); - //string configPath = string.Empty; - //File is on disk. - if (File.Exists(configPath)) - { - FileStream fs = null; - try - { - XmlSerializer serializer = new XmlSerializer(typeof(ConfigurationData)); - fs = new FileStream(configPath, FileMode.Open, FileAccess.Read, FileShare.Read); - _configurations = (ConfigurationData)serializer.Deserialize(fs); - } - finally - { - fs?.Close(); - } - _configurations.Loaded = true; - } - else - { - //If null then make a new instance. - if (_configurations == null) - _configurations = new ConfigurationData(); - //Don't unset loaded, if its true then it should have proper info. - //_configurationData.Loaded = false; - } - } - - return _configurations; - - } - - } - - -} diff --git a/Assets/FishNet/Runtime/Editor/Configuring/Configuring.cs.meta b/Assets/FishNet/Runtime/Editor/Configuring/Configuring.cs.meta deleted file mode 100644 index 0d34195..0000000 --- a/Assets/FishNet/Runtime/Editor/Configuring/Configuring.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8d05bf07ec9af2c46a1fe6c24871cccb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Configuring/FIshNetGettingStartedEditor.cs b/Assets/FishNet/Runtime/Editor/Configuring/FIshNetGettingStartedEditor.cs deleted file mode 100644 index 9b24f81..0000000 --- a/Assets/FishNet/Runtime/Editor/Configuring/FIshNetGettingStartedEditor.cs +++ /dev/null @@ -1,172 +0,0 @@ -#if UNITY_EDITOR -using UnityEditor; -using UnityEngine; - -namespace FishNet.Editing -{ - - /// - /// Contributed by YarnCat! Thank you! - /// - public class FishNetGettingStartedEditor : EditorWindow - { - private Texture2D _fishnetLogo, _reviewButtonBg, _reviewButtonBgHover; - private GUIStyle _labelStyle, _reviewButtonStyle; - - private const string SHOWED_GETTING_STARTED = "ShowedFishNetGettingStarted"; - - [MenuItem("Fish-Networking/Getting Started")] - public static void GettingStartedMenu() - { - FishNetGettingStartedEditor window = (FishNetGettingStartedEditor)EditorWindow.GetWindow(typeof(FishNetGettingStartedEditor)); - window.position = new Rect(0, 0, 320, 355); - Rect mainPos; -#if UNITY_2020_1_OR_NEWER - mainPos = EditorGUIUtility.GetMainWindowPosition(); -#else - mainPos = new Rect(Vector2.zero, Vector2.zero); -#endif - var pos = window.position; - float w = (mainPos.width - pos.width) * 0.5f; - float h = (mainPos.height - pos.height) * 0.5f; - pos.x = mainPos.x + w; - pos.y = mainPos.y + h; - window.position = pos; - - window._fishnetLogo = (Texture2D)AssetDatabase.LoadAssetAtPath("Assets/FishNet/Runtime/Editor/Textures/UI/Logo_With_Text.png", typeof(Texture)); - window._labelStyle = new GUIStyle("label"); - window._labelStyle.fontSize = 24; - window._labelStyle.wordWrap = true; - //window.labelStyle.alignment = TextAnchor.MiddleCenter; - window._labelStyle.normal.textColor = new Color32(74, 195, 255, 255); - - window._reviewButtonBg = MakeBackgroundTexture(1, 1, new Color32(52, 111, 255, 255)); - window._reviewButtonBgHover = MakeBackgroundTexture(1, 1, new Color32(99, 153, 255, 255)); - window._reviewButtonStyle = new GUIStyle("button"); - window._reviewButtonStyle.fontSize = 18; - window._reviewButtonStyle.fontStyle = FontStyle.Bold; - window._reviewButtonStyle.normal.background = window._reviewButtonBg; - window._reviewButtonStyle.active.background = window._reviewButtonBgHover; - window._reviewButtonStyle.focused.background = window._reviewButtonBgHover; - window._reviewButtonStyle.onFocused.background = window._reviewButtonBgHover; - window._reviewButtonStyle.hover.background = window._reviewButtonBgHover; - window._reviewButtonStyle.onHover.background = window._reviewButtonBgHover; - window._reviewButtonStyle.alignment = TextAnchor.MiddleCenter; - window._reviewButtonStyle.normal.textColor = new Color(1, 1, 1, 1); - - } - - - private static bool _subscribed; - - [InitializeOnLoadMethod] - private static void Initialize() - { - SubscribeToUpdate(); - } - - private static void SubscribeToUpdate() - { - if (Application.isBatchMode) - return; - - if (!_subscribed && !EditorApplication.isPlayingOrWillChangePlaymode) - { - _subscribed = true; - EditorApplication.update += ShowGettingStarted; - } - } - - private static void ShowGettingStarted() - { - EditorApplication.update -= ShowGettingStarted; - - bool shown = EditorPrefs.GetBool(SHOWED_GETTING_STARTED, false); - if (!shown) - { - EditorPrefs.SetBool(SHOWED_GETTING_STARTED, true); - ReviewReminderEditor.ResetDateTimeReminded(); - GettingStartedMenu(); - } - //If was already shown then check review reminder instead. - else - { - ReviewReminderEditor.CheckRemindToReview(); - } - } - - - void OnGUI() - { - - - GUILayout.Box(_fishnetLogo, GUILayout.Width(this.position.width), GUILayout.Height(128)); - GUILayout.Space(20); - - GUILayout.Label("Have you considered leaving us a review?", _labelStyle, GUILayout.Width(280)); - - GUILayout.Space(10); - - if (GUILayout.Button("Leave us a review!", _reviewButtonStyle)) - { - Application.OpenURL("https://assetstore.unity.com/packages/tools/network/fish-net-networking-evolved-207815"); - } - - GUILayout.Space(20); - - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("Documentation", GUILayout.Width(this.position.width * 0.485f))) - { - Application.OpenURL("https://fish-networking.gitbook.io/docs/"); - } - - if (GUILayout.Button("Discord", GUILayout.Width(this.position.width * 0.485f))) - { - Application.OpenURL("https://discord.gg/Ta9HgDh4Hj"); - } - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("FishNet Pro", GUILayout.Width(this.position.width * 0.485f))) - { - Application.OpenURL("https://fish-networking.gitbook.io/docs/master/pro"); - } - - if (GUILayout.Button("Github", GUILayout.Width(this.position.width * 0.485f))) - { - Application.OpenURL("https://github.com/FirstGearGames/FishNet"); - } - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("Pro Downloads", GUILayout.Width(this.position.width * 0.485f))) - { - Application.OpenURL("https://www.firstgeargames.com/"); - } - - if (GUILayout.Button("Examples", GUILayout.Width(this.position.width * 0.485f))) - { - Application.OpenURL("https://fish-networking.gitbook.io/docs/manual/tutorials/example-projects"); - } - EditorGUILayout.EndHorizontal(); - - //GUILayout.Space(20); - //_showOnStartupSelected = EditorGUILayout.Popup("Show on Startup", _showOnStartupSelected, showOnStartupOptions); - } - //private string[] showOnStartupOptions = new string[] { "Always", "On new version", "Never", }; - //private int _showOnStartupSelected = 1; - - private static Texture2D MakeBackgroundTexture(int width, int height, Color color) - { - Color[] pixels = new Color[width * height]; - for (int i = 0; i < pixels.Length; i++) - pixels[i] = color; - Texture2D backgroundTexture = new Texture2D(width, height); - backgroundTexture.SetPixels(pixels); - backgroundTexture.Apply(); - return backgroundTexture; - } - } - -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Editor/Configuring/FIshNetGettingStartedEditor.cs.meta b/Assets/FishNet/Runtime/Editor/Configuring/FIshNetGettingStartedEditor.cs.meta deleted file mode 100644 index 0ce3c87..0000000 --- a/Assets/FishNet/Runtime/Editor/Configuring/FIshNetGettingStartedEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 335aec9a9dce4944994cb57ac704ba5a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Configuring/ReviewReminderEditor.cs b/Assets/FishNet/Runtime/Editor/Configuring/ReviewReminderEditor.cs deleted file mode 100644 index 70028b8..0000000 --- a/Assets/FishNet/Runtime/Editor/Configuring/ReviewReminderEditor.cs +++ /dev/null @@ -1,171 +0,0 @@ -#if UNITY_EDITOR -using System; -using UnityEditor; -using UnityEngine; - -namespace FishNet.Editing -{ - - /// - /// Contributed by YarnCat! Thank you! - /// - public class ReviewReminderEditor : EditorWindow - { - private Texture2D _fishnetLogo, _reviewButtonBg, _reviewButtonBgHover; - private GUIStyle _labelStyle, _reviewButtonStyle; - - private const string DATETIME_REMINDED = "ReviewDateTimeReminded"; - private const string CHECK_REMIND_COUNT = "CheckRemindCount"; - private const string IS_ENABLED = "ReminderEnabled"; - - private static ReviewReminderEditor _window; - - internal static void CheckRemindToReview() - { - bool reminderEnabled = EditorPrefs.GetBool(IS_ENABLED, true); - if (!reminderEnabled) - return; - - /* Require at least two opens and 10 days - * to be passed before reminding. */ - int checkRemindCount = (EditorPrefs.GetInt(CHECK_REMIND_COUNT, 0) + 1); - EditorPrefs.SetInt(CHECK_REMIND_COUNT, checkRemindCount); - - //Not enough checks. - if (checkRemindCount < 2) - return; - - string dtStr = EditorPrefs.GetString(DATETIME_REMINDED, string.Empty); - //Somehow got cleared. Reset. - if (string.IsNullOrWhiteSpace(dtStr)) - { - ResetDateTimeReminded(); - return; - } - long binary; - //Failed to parse. - if (!long.TryParse(dtStr, out binary)) - { - ResetDateTimeReminded(); - return; - } - //Not enough time passed. - DateTime dt = DateTime.FromBinary(binary); - if ((DateTime.Now - dt).TotalDays < 10) - return; - - //If here then the reminder can be shown. - EditorPrefs.SetInt(CHECK_REMIND_COUNT, 0); - - ShowReminder(); - } - - internal static void ResetDateTimeReminded() - { - EditorPrefs.SetString(DATETIME_REMINDED, DateTime.Now.ToBinary().ToString()); - } - - private static void ShowReminder() - { - InitializeWindow(); - } - - static void InitializeWindow() - { - if (_window != null) - return; - _window = (ReviewReminderEditor)EditorWindow.GetWindow(typeof(ReviewReminderEditor)); - _window.position = new Rect(0f, 0f, 320f, 300f); - Rect mainPos; -#if UNITY_2020_1_OR_NEWER - mainPos = EditorGUIUtility.GetMainWindowPosition(); -#else - mainPos = new Rect(Vector2.zero, Vector2.zero); -#endif - var pos = _window.position; - float w = (mainPos.width - pos.width) * 0.5f; - float h = (mainPos.height - pos.height) * 0.5f; - pos.x = mainPos.x + w; - pos.y = mainPos.y + h; - _window.position = pos; - } - - static void StyleWindow() - { - InitializeWindow(); - _window._fishnetLogo = (Texture2D)AssetDatabase.LoadAssetAtPath("Assets/FishNet/Runtime/Editor/Textures/UI/Logo_With_Text.png", typeof(Texture)); - _window._labelStyle = new GUIStyle("label"); - _window._labelStyle.fontSize = 24; - _window._labelStyle.wordWrap = true; - //window.labelStyle.alignment = TextAnchor.MiddleCenter; - _window._labelStyle.normal.textColor = new Color32(74, 195, 255, 255); - - _window._reviewButtonBg = MakeBackgroundTexture(1, 1, new Color32(52, 111, 255, 255)); - _window._reviewButtonBgHover = MakeBackgroundTexture(1, 1, new Color32(99, 153, 255, 255)); - _window._reviewButtonStyle = new GUIStyle("button"); - _window._reviewButtonStyle.fontSize = 18; - _window._reviewButtonStyle.fontStyle = FontStyle.Bold; - _window._reviewButtonStyle.normal.background = _window._reviewButtonBg; - _window._reviewButtonStyle.active.background = _window._reviewButtonBgHover; - _window._reviewButtonStyle.focused.background = _window._reviewButtonBgHover; - _window._reviewButtonStyle.onFocused.background = _window._reviewButtonBgHover; - _window._reviewButtonStyle.hover.background = _window._reviewButtonBgHover; - _window._reviewButtonStyle.onHover.background = _window._reviewButtonBgHover; - _window._reviewButtonStyle.alignment = TextAnchor.MiddleCenter; - _window._reviewButtonStyle.normal.textColor = new Color(1, 1, 1, 1); - - } - - void OnGUI() - { - float thisWidth = this.position.width; - StyleWindow(); - GUILayout.Box(_fishnetLogo, GUILayout.Width(this.position.width), GUILayout.Height(160f)); - EditorGUILayout.BeginHorizontal(); - GUILayout.Space(8f); - GUILayout.Label("Have you considered leaving us a review?", _labelStyle, GUILayout.Width(thisWidth * 0.95f)); - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("Don't Ask Again", GUILayout.Width(this.position.width))) - { - this.Close(); - EditorPrefs.SetBool(IS_ENABLED, false); - } - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("Ask Later", GUILayout.Width(this.position.width))) - { - this.Close(); - Application.OpenURL("https://discord.gg/Ta9HgDh4Hj"); - } - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("Leave A Review", GUILayout.Width(this.position.width))) - { - this.Close(); - EditorPrefs.SetBool(IS_ENABLED, false); - Application.OpenURL("https://assetstore.unity.com/packages/tools/network/fish-net-networking-evolved-207815"); - } - EditorGUILayout.EndHorizontal(); - - //GUILayout.Space(20); - //_showOnStartupSelected = EditorGUILayout.Popup("Show on Startup", _showOnStartupSelected, showOnStartupOptions); - } - - private static Texture2D MakeBackgroundTexture(int width, int height, Color color) - { - Color[] pixels = new Color[width * height]; - for (int i = 0; i < pixels.Length; i++) - pixels[i] = color; - Texture2D backgroundTexture = new Texture2D(width, height); - backgroundTexture.SetPixels(pixels); - backgroundTexture.Apply(); - return backgroundTexture; - } - } - -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Editor/Configuring/ReviewReminderEditor.cs.meta b/Assets/FishNet/Runtime/Editor/Configuring/ReviewReminderEditor.cs.meta deleted file mode 100644 index cb27f6b..0000000 --- a/Assets/FishNet/Runtime/Editor/Configuring/ReviewReminderEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4260206b6a57e4243b56437f8f283084 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Configuring/SettingsProvider.cs b/Assets/FishNet/Runtime/Editor/Configuring/SettingsProvider.cs deleted file mode 100644 index ec66b2a..0000000 --- a/Assets/FishNet/Runtime/Editor/Configuring/SettingsProvider.cs +++ /dev/null @@ -1,86 +0,0 @@ -#if UNITY_EDITOR - -using UnityEngine; -using UnityEditor; -using FishNet.Configuring; - -using UnitySettingsProviderAttribute = UnityEditor.SettingsProviderAttribute; -using UnitySettingsProvider = UnityEditor.SettingsProvider; -using System.Collections.Generic; - -namespace FishNet.Configuring.Editing -{ - internal static class SettingsProvider - { - private static Vector2 _scrollView; - - [UnitySettingsProvider] - private static UnitySettingsProvider Create() - { - return new UnitySettingsProvider("Project/Fish-Networking/Configuration", SettingsScope.Project) - { - label = "Configuration", - - guiHandler = OnGUI, - - keywords = new string[] - { - "Fish", - "Networking", - "Configuration", - }, - }; - } - - private static void OnGUI(string searchContext) - { - ConfigurationData configuration = Configuration.LoadConfigurationData(); - - if (configuration == null) - { - EditorGUILayout.HelpBox("Unable to load configuration data.", MessageType.Error); - - return; - } - - EditorGUI.BeginChangeCheck(); - - GUIStyle scrollViewStyle = new GUIStyle() - { - padding = new RectOffset(10, 10, 10, 10), - }; - - _scrollView = GUILayout.BeginScrollView(_scrollView, scrollViewStyle); - - EditorGUILayout.BeginHorizontal(); - - GUIStyle toggleStyle = new GUIStyle(EditorStyles.toggle) - { - richText = true, - }; - - configuration.CodeStripping.StripReleaseBuilds = GUILayout.Toggle(configuration.CodeStripping.StripReleaseBuilds, $"{ObjectNames.NicifyVariableName(nameof(configuration.CodeStripping.StripReleaseBuilds))} (Pro Only)", toggleStyle); - - EditorGUILayout.EndHorizontal(); - - if (configuration.CodeStripping.StripReleaseBuilds) - { - EditorGUI.indentLevel++; - //Stripping Method. - List enumStrings = new List(); - foreach (string item in System.Enum.GetNames(typeof(StrippingTypes))) - enumStrings.Add(item); - configuration.CodeStripping.StrippingType = EditorGUILayout.Popup($"{ObjectNames.NicifyVariableName(nameof(configuration.CodeStripping.StrippingType))}", (int)configuration.CodeStripping.StrippingType, enumStrings.ToArray()); - - EditorGUILayout.HelpBox("Development builds will not have code stripped. Additionally, if you plan to run as host disable code stripping.", MessageType.Warning); - EditorGUI.indentLevel--; - } - - GUILayout.EndScrollView(); - - if (EditorGUI.EndChangeCheck()) Configuration.Configurations.Write(true); - } - } -} - -#endif diff --git a/Assets/FishNet/Runtime/Editor/Configuring/SettingsProvider.cs.meta b/Assets/FishNet/Runtime/Editor/Configuring/SettingsProvider.cs.meta deleted file mode 100644 index d668951..0000000 --- a/Assets/FishNet/Runtime/Editor/Configuring/SettingsProvider.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b3d7d3c45d53dea4e8a0a7da73d64021 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Constants.cs b/Assets/FishNet/Runtime/Editor/Constants.cs deleted file mode 100644 index 1e8523d..0000000 --- a/Assets/FishNet/Runtime/Editor/Constants.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FishNet.Documenting; - -namespace FishNet.Editing -{ - [APIExclude] - public static class EditingConstants - { - public const string PRO_ASSETS_LOCKED_TEXT = "Fields marked with * are only active with Fish-Networking Pro."; - public const string PRO_ASSETS_UNLOCKED_TEXT = "Thank you for supporting Fish-Networking! Pro asset features are unlocked."; - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Editor/Constants.cs.meta b/Assets/FishNet/Runtime/Editor/Constants.cs.meta deleted file mode 100644 index bfee3c7..0000000 --- a/Assets/FishNet/Runtime/Editor/Constants.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1d2683b3becd2c5488c1f338972d49e0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/DefaultPrefabsFinder.cs b/Assets/FishNet/Runtime/Editor/DefaultPrefabsFinder.cs deleted file mode 100644 index 626cabc..0000000 --- a/Assets/FishNet/Runtime/Editor/DefaultPrefabsFinder.cs +++ /dev/null @@ -1,126 +0,0 @@ -//#if UNITY_EDITOR -//using FishNet.Managing.Object; -//using FishNet.Object; -//using System.Collections.Generic; -//using System.IO; -//using UnityEditor; -//using UnityEngine; - -//namespace FishNet.Editing -//{ - -// [InitializeOnLoad] -// internal static class DefaultPrefabsFinder -// { -// /// -// /// True if initialized. -// /// -// [System.NonSerialized] -// private static bool _initialized; -// /// -// /// Found default prefabs. -// /// -// private static DefaultPrefabObjects _defaultPrefabs; - -// static DefaultPrefabsFinder() -// { -// EditorApplication.update += InitializeOnce; -// } - -// /// -// /// Finds and sets the default prefabs reference. -// /// -// internal static DefaultPrefabObjects GetDefaultPrefabsFile(out bool justPopulated) -// { -// if (_defaultPrefabs == null) -// { -// List results = Finding.GetScriptableObjects(true, true); -// if (results.Count > 0) -// _defaultPrefabs = (DefaultPrefabObjects)results[0]; -// } - -// justPopulated = false; -// //If not found then try to create file. -// if (_defaultPrefabs == null) -// { -// if (DefaultPrefabObjects.CanAutomate) -// { -// DefaultPrefabObjects dpo = ScriptableObject.CreateInstance(); -// //Get save directory. -// string savePath = Finding.GetFishNetRuntimePath(true); -// AssetDatabase.CreateAsset(dpo, Path.Combine(savePath, $"{nameof(DefaultPrefabObjects)}.asset")); -// } -// else -// { -// Debug.LogError($"Cannot create DefaultPrefabs because auto create is blocked."); -// } -// } - -// //If still null. -// if (_defaultPrefabs == null) -// Debug.LogWarning($"DefaultPrefabObjects not found. Prefabs list will not be automatically populated."); -// else -// justPopulated = PopulateDefaultPrefabs(); - -// return _defaultPrefabs; -// } - -// /// -// /// Initializes the default prefab. -// /// -// private static void InitializeOnce() -// { -// if (_initialized) -// return; -// _initialized = true; - -// Finding.GetFishNetRuntimePath(false); -// GetDefaultPrefabsFile(out _); - -// if (_defaultPrefabs != null) -// { -// //Populate any missing. -// if (_defaultPrefabs.GetObjectCount() == 0) -// PopulateDefaultPrefabs(); -// } -// } - - -// /// -// /// Finds all NetworkObjects in project and adds them to defaultPrefabs. -// /// -// /// True if was populated from assets. -// internal static bool PopulateDefaultPrefabs(bool log = true, bool clear = false) -// { -// if (_defaultPrefabs == null) -// return false; -// if (!DefaultPrefabObjects.CanAutomate) -// return false; -// if (clear) -// _defaultPrefabs.Clear(); -// if (_defaultPrefabs.GetObjectCount() > 0) -// return false; - -// List gameObjects = Finding.GetGameObjects(true, true, false); -// foreach (GameObject go in gameObjects) -// { -// if (go.TryGetComponent(out NetworkObject nob)) -// _defaultPrefabs.AddObject(nob); -// } - -// _defaultPrefabs.Sort(); - -// int entriesAdded = _defaultPrefabs.GetObjectCount(); -// //Only print if some were added. -// if (log && entriesAdded > 0) -// Debug.Log($"Default prefabs was populated with {entriesAdded} prefabs."); - -// EditorUtility.SetDirty(_defaultPrefabs); -// return true; -// } - -// } - - -//} -//#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Editor/DefaultPrefabsFinder.cs.meta b/Assets/FishNet/Runtime/Editor/DefaultPrefabsFinder.cs.meta deleted file mode 100644 index 1ee03df..0000000 --- a/Assets/FishNet/Runtime/Editor/DefaultPrefabsFinder.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2bd002f6c85dd4341bcaf163eaaa3ddf -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Finding.cs b/Assets/FishNet/Runtime/Editor/Finding.cs deleted file mode 100644 index 2d260c8..0000000 --- a/Assets/FishNet/Runtime/Editor/Finding.cs +++ /dev/null @@ -1,216 +0,0 @@ -#if UNITY_EDITOR -using FishNet.Utility.Constant; -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using UnityEngine.SceneManagement; - -namespace FishNet.Editing -{ - public static class Finding - { - #region Private. - /// - /// Path where the FishNet.Runtime assembly is. - /// - [System.NonSerialized] - private static string _fishNetRuntimePath = string.Empty; - /// - /// Path where the FishNet.Generated assembly is. - /// - private static string _fishNetGeneratedPath = string.Empty; - #endregion - - /// - /// Sets FishNet assembly paths. - /// - /// - private static void SetPaths(bool error) - { - if (_fishNetGeneratedPath != string.Empty && _fishNetRuntimePath != string.Empty) - return; - - string[] guids = AssetDatabase.FindAssets("t:asmdef", new string[] { "Assets" }); - string[] objectPaths = new string[guids.Length]; - for (int i = 0; i < guids.Length; i++) - objectPaths[i] = AssetDatabase.GUIDToAssetPath(guids[i]); - - string runtimeName = (UtilityConstants.RUNTIME_ASSEMBLY_NAME + ".asmdef").ToLower(); - string generatedName = (UtilityConstants.GENERATED_ASSEMBLY_NAME + ".asmdef").ToLower(); - /* Find all network managers which use Single prefab linking - * as well all network object prefabs. */ - foreach (string item in objectPaths) - { - //Found directory to create object in. - if (item.ToLower().Contains(runtimeName)) - _fishNetRuntimePath = System.IO.Path.GetDirectoryName(item); - else if (item.ToLower().Contains(generatedName)) - _fishNetGeneratedPath = System.IO.Path.GetDirectoryName(item); - - if (_fishNetGeneratedPath != string.Empty && _fishNetRuntimePath != string.Empty) - return; - } - } - /// - /// Gets path for where the FishNet.Runtime assembly is. - /// - /// - public static string GetFishNetRuntimePath(bool error) - { - SetPaths(error); - return _fishNetRuntimePath; - } - /// - /// Gets path for where the FishNet.Generated assembly is. - /// - /// - /// - public static string GetFishNetGeneratedPath(bool error) - { - SetPaths(error); - return _fishNetGeneratedPath; - } - - /// - /// Gets all GameObjects in Assets and optionally scenes. - /// - /// - /// - public static List GetGameObjects(bool userAssemblies, bool fishNetAssembly, bool includeScenes, string[] ignoredPaths = null) - { - List results = new List(); - - string[] guids; - string[] objectPaths; - - guids = AssetDatabase.FindAssets("t:GameObject", null); - objectPaths = new string[guids.Length]; - for (int i = 0; i < guids.Length; i++) - objectPaths[i] = AssetDatabase.GUIDToAssetPath(guids[i]); - - foreach (string item in objectPaths) - { - bool inFishNet = item.Contains(_fishNetRuntimePath); - if (inFishNet && !fishNetAssembly) - continue; - if (!inFishNet && !userAssemblies) - continue; - if (ignoredPaths != null) - { - bool ignore = false; - foreach (string path in ignoredPaths) - { - if (item.Contains(path)) - { - ignore = true; - break; - } - } - if (ignore) - continue; - } - - GameObject go = (GameObject)AssetDatabase.LoadAssetAtPath(item, typeof(GameObject)); - results.Add(go); - } - - if (includeScenes) - results.AddRange(GetSceneGameObjects()); - - return results; - } - - /// - /// Gets all GameObjects in all open scenes. - /// - /// - private static List GetSceneGameObjects() - { - List results = new List(); - - for (int i = 0; i < SceneManager.sceneCount; i++) - results.AddRange(GetSceneGameObjects(SceneManager.GetSceneAt(i))); - - return results; - } - /// - /// Gets all GameObjects in a scene. - /// - private static List GetSceneGameObjects(Scene s) - { - List results = new List(); - List buffer = new List(); - //Iterate all root objects for the scene. - GameObject[] gos = s.GetRootGameObjects(); - for (int i = 0; i < gos.Length; i++) - { - /* Get GameObjects within children of each - * root object then add them to the cache. */ - gos[i].GetComponentsInChildren(true, buffer); - foreach (Transform t in buffer) - results.Add(t.gameObject); - } - - return results; - } - - - /// - /// Gets created ScriptableObjects of T. - /// - /// - /// - public static List GetScriptableObjects(bool fishNetAssembly, bool breakOnFirst = false) - { - System.Type tType = typeof(T); - List results = new List(); - - string[] guids = AssetDatabase.FindAssets("t:ScriptableObject", new string[] { "Assets" }); - string[] objectPaths = new string[guids.Length]; - for (int i = 0; i < guids.Length; i++) - objectPaths[i] = AssetDatabase.GUIDToAssetPath(guids[i]); - - - /* This might be faster than using directory comparers. - * Don't really care since this occurs only at edit. */ - List fishNetPaths = new List(); - fishNetPaths.Add(_fishNetGeneratedPath.Replace(@"/", @"\")); - fishNetPaths.Add(_fishNetGeneratedPath.Replace(@"\", @"/")); - fishNetPaths.Add(_fishNetRuntimePath.Replace(@"/", @"\")); - fishNetPaths.Add(_fishNetRuntimePath.Replace(@"\", @"/")); - /* Find all network managers which use Single prefab linking - * as well all network object prefabs. */ - foreach (string item in objectPaths) - { - //This will skip hidden unity types. - if (!item.EndsWith(".asset")) - continue; - if (fishNetAssembly) - { - bool found = false; - foreach (string path in fishNetPaths) - { - if (item.Contains(path)) - { - found = true; - break; - } - } - if (!found) - continue; - } - UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath(item, tType); - if (obj != null && tType != null && obj.GetType() == tType) - { - results.Add(obj); - if (breakOnFirst) - return results; - } - } - - return results; - } - - } -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Editor/Finding.cs.meta b/Assets/FishNet/Runtime/Editor/Finding.cs.meta deleted file mode 100644 index 23a2fb5..0000000 --- a/Assets/FishNet/Runtime/Editor/Finding.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b777233d19062274f9eec6a982d8ff37 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/PlayModeTracker.cs b/Assets/FishNet/Runtime/Editor/PlayModeTracker.cs deleted file mode 100644 index 45f7b7c..0000000 --- a/Assets/FishNet/Runtime/Editor/PlayModeTracker.cs +++ /dev/null @@ -1,51 +0,0 @@ -#if UNITY_EDITOR -using System; -using UnityEditor; -using UnityEngine; - -namespace FishNet.Editing -{ - - [InitializeOnLoad] - public class PlayModeTracker - { - static PlayModeTracker() - { - EditorApplication.playModeStateChanged += OnPlayModeStateChanged; - } - - ~PlayModeTracker() - { - EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; - } - - /// - /// DateTime when the editor last exited playmode. - /// - private static DateTime _quitTime = DateTime.MaxValue; - - /// - /// True if the editor has exited playmode within past. - /// - /// - /// - internal static bool QuitRecently(float past) - { - past *= 1000; - return ((DateTime.Now - _quitTime).TotalMilliseconds < past); - } - - private static void OnPlayModeStateChanged(PlayModeStateChange stateChange) - { - switch (stateChange) - { - case (PlayModeStateChange.ExitingPlayMode): - _quitTime = DateTime.Now; - break; - } - } - - } -} - -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Editor/PlayModeTracker.cs.meta b/Assets/FishNet/Runtime/Editor/PlayModeTracker.cs.meta deleted file mode 100644 index d5fd5a2..0000000 --- a/Assets/FishNet/Runtime/Editor/PlayModeTracker.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d4a1d20c6a03a524ab21c7aebed106d0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator.meta b/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator.meta deleted file mode 100644 index 873aa1e..0000000 --- a/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 3da51acfc7419a544887f9eab923b0a7 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Generator.cs b/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Generator.cs deleted file mode 100644 index fbce389..0000000 --- a/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Generator.cs +++ /dev/null @@ -1,619 +0,0 @@ -#if UNITY_EDITOR - -using FishNet.Configuring; -using FishNet.Managing.Object; -using FishNet.Object; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using UnityEditor; -using UnityEngine; -using UnityDebug = UnityEngine.Debug; - -namespace FishNet.Editing.PrefabCollectionGenerator -{ - internal sealed class Generator : AssetPostprocessor - { - public Generator() - { - if (!_subscribed) - { - _subscribed = true; - EditorApplication.update += OnEditorUpdate; - } - } - ~Generator() - { - if (_subscribed) - { - _subscribed = false; - EditorApplication.update -= OnEditorUpdate; - } - } - - #region Types. - private struct SpecifiedFolder - { - public string Path; - public bool Recursive; - - public SpecifiedFolder(string path, bool recursive) - { - Path = path; - Recursive = recursive; - } - } - #endregion - - #region Public. - /// - /// True to ignore post process changes. - /// - public static bool IgnorePostProcess = false; - #endregion - - #region Private. - /// - /// Last asset to import when there was only one imported asset and no other changes. - /// - private static string _lastSingleImportedAsset = string.Empty; - /// - /// Cached DefaultPrefabObjects reference. - /// - private static DefaultPrefabObjects _cachedDefaultPrefabs; - /// - /// True to refresh prefabs next update. - /// - private static bool _retryRefreshDefaultPrefabs; - /// - /// True if already subscribed to EditorApplication.Update. - /// - private static bool _subscribed; - /// - /// True if ran once since editor started. - /// - [System.NonSerialized] - private static bool _ranOnce; - /// - /// Last paths of updated nobs during a changed update. - /// - [System.NonSerialized] - private static List _lastUpdatedNamePaths = new List(); - /// - /// Last frame changed was updated. - /// - [System.NonSerialized] - private static int _lastUpdatedFrame = -1; - /// - /// Length of assets strings during the last update. - /// - [System.NonSerialized] - private static int _lastUpdatedLengths = -1; - #endregion - - public static string[] GetPrefabFiles(string startingPath, HashSet excludedPaths, bool recursive) - { - //Opportunity to exit early if there are no excluded paths. - if (excludedPaths.Count == 0) - { - string[] strResults = Directory.GetFiles(startingPath, "*.prefab", SearchOption.AllDirectories); - return strResults; - } - //starting path is excluded. - if (excludedPaths.Contains(startingPath)) - return new string[0]; - - //Folders remaining to be iterated. - List enumeratedCollection = new List() { startingPath }; - //Only check other directories if recursive. - if (recursive) - { - //Find all folders which aren't excluded. - for (int i = 0; i < enumeratedCollection.Count; i++) - { - string[] allFolders = Directory.GetDirectories(enumeratedCollection[i], "*", SearchOption.TopDirectoryOnly); - for (int z = 0; z < allFolders.Length; z++) - { - string current = allFolders[z]; - //Not excluded. - if (!excludedPaths.Contains(current)) - enumeratedCollection.Add(current); - } - } - } - - //Valid prefab files. - List results = new List(); - //Build files from folders. - int count = enumeratedCollection.Count; - for (int i = 0; i < count; i++) - { - string[] r = Directory.GetFiles(enumeratedCollection[i], "*.prefab", SearchOption.TopDirectoryOnly); - results.AddRange(r); - } - - return results.ToArray(); - } - - /// - /// Removes paths which may overlap each other, such as sub directories. - /// - private static void RemoveOverlappingFolders(List folders) - { - for (int z = 0; z < folders.Count; z++) - { - for (int i = 0; i < folders.Count; i++) - { - //Do not check against self. - if (i == z) - continue; - - //Duplicate. - if (folders[z].Path.Equals(folders[i].Path, System.StringComparison.OrdinalIgnoreCase)) - { - UnityDebug.LogError($"The same path is specified multiple times in the DefaultPrefabGenerator settings. Remove the duplicate to clear this error."); - folders.RemoveAt(i); - break; - } - - /* We are checking if i can be within - * z. This is only possible if i is longer - * than z. */ - if (folders[i].Path.Length < folders[z].Path.Length) - continue; - /* Do not need to check if not recursive. - * Only recursive needs to be checked because - * a shorter recursive path could contain - * a longer path. */ - if (!folders[z].Recursive) - continue; - - //Compare paths. - string zPath = GetPathWithSeparator(folders[z].Path); - string iPath = zPath.Substring(0, zPath.Length); - //If paths match. - if (iPath.Equals(zPath, System.StringComparison.OrdinalIgnoreCase)) - { - UnityDebug.LogError($"Path {folders[i].Path} is included within recursive path {folders[z].Path}. Remove path {folders[i].Path} to clear this error."); - folders.RemoveAt(i); - break; - } - } - } - - string GetPathWithSeparator(string txt) - { - return txt.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) - + Path.DirectorySeparatorChar; - } - } - - /// - /// Returns a message to attach to logs if objects were dirtied. - /// - private static string GetDirtiedMessage(PrefabGeneratorConfigurations settings, bool dirtied) - { - if (!settings.SaveChanges && dirtied) - return " One or more NetworkObjects were dirtied. Please save your project."; - else - return string.Empty; - } - - /// - /// Updates prefabs by using only changed information. - /// - public static void GenerateChanged(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths, PrefabGeneratorConfigurations settings = null) - { - if (settings == null) - settings = Configuration.Configurations.PrefabGenerator; - if (!settings.Enabled) - return; - - bool log = settings.LogToConsole; - Stopwatch sw = (log) ? Stopwatch.StartNew() : null; - - DefaultPrefabObjects prefabCollection = GetDefaultPrefabObjects(settings); - //No need to error if nto found, GetDefaultPrefabObjects will. - if (prefabCollection == null) - return; - - int assetsLength = (importedAssets.Length + deletedAssets.Length + movedAssets.Length + movedFromAssetPaths.Length); - List changedNobPaths = new List(); - - System.Type goType = typeof(UnityEngine.GameObject); - IterateAssetCollection(importedAssets); - IterateAssetCollection(movedAssets); - - //True if dirtied by changes. - bool dirtied; - //First remove null entries. - int startCount = prefabCollection.GetObjectCount(); - prefabCollection.RemoveNull(); - dirtied = (prefabCollection.GetObjectCount() != startCount); - //First index which new objects will be added to. - int firstAddIndex = (prefabCollection.GetObjectCount() - 1); - - //Iterates strings adding prefabs to collection. - void IterateAssetCollection(string[] c) - { - foreach (string item in c) - { - System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(item); - if (assetType != goType) - continue; - - NetworkObject nob = AssetDatabase.LoadAssetAtPath(item); - if (nob != null) - { - changedNobPaths.Add(item); - prefabCollection.AddObject(nob, true); - dirtied = true; - } - } - } - - //To prevent out of range. - if (firstAddIndex < 0 || firstAddIndex >= prefabCollection.GetObjectCount()) - firstAddIndex = 0; - dirtied |= prefabCollection.SetAssetPathHashes(firstAddIndex); - - if (log && dirtied) - UnityDebug.Log($"Default prefab generator updated prefabs in {sw.ElapsedMilliseconds}ms.{GetDirtiedMessage(settings, dirtied)}"); - - //Check for redundancy. - int frameCount = Time.frameCount; - int changedCount = changedNobPaths.Count; - if (frameCount == _lastUpdatedFrame && assetsLength == _lastUpdatedLengths && (changedCount == _lastUpdatedNamePaths.Count) && changedCount > 0) - { - bool allMatch = true; - for (int i = 0; i < changedCount; i++) - { - if (changedNobPaths[i] != _lastUpdatedNamePaths[i]) - { - allMatch = false; - break; - } - } - - /* If the import results are the same as the last attempt, on the same frame - * then there is likely an issue saving the assets. */ - if (allMatch) - { - //Unset dirtied to prevent a save. - dirtied = false; - //Log this no matter what, it's critical. - UnityDebug.LogError($"Default prefab generator had a problem saving one or more assets. " + - $"This usually occurs when the assets cannot be saved due to missing scripts or serialization errors. " + - $"Please see above any prefabs which could not save any make corrections."); - } - - } - //Set last values. - _lastUpdatedFrame = Time.frameCount; - _lastUpdatedNamePaths = changedNobPaths; - _lastUpdatedLengths = assetsLength; - - EditorUtility.SetDirty(prefabCollection); - if (dirtied && settings.SaveChanges) - AssetDatabase.SaveAssets(); - } - - /// - /// Generates prefabs by iterating all files within settings parameters. - /// - public static void GenerateFull(PrefabGeneratorConfigurations settings = null, bool forced = false) - { - if (settings == null) - settings = Configuration.Configurations.PrefabGenerator; - if (!forced && !settings.Enabled) - return; - bool log = settings.LogToConsole; - - Stopwatch sw = (log) ? Stopwatch.StartNew() : null; - List foundNobs = new List(); - HashSet excludedPaths = new HashSet(settings.ExcludedFolders); - - //If searching the entire project. - if (settings.SearchScope == (int)SearchScopeType.EntireProject) - { - foreach (string path in GetPrefabFiles("Assets", excludedPaths, true)) - { - NetworkObject nob = AssetDatabase.LoadAssetAtPath(path); - if (nob != null) - foundNobs.Add(nob); - } - } - //Specific folders. - else if (settings.SearchScope == (int)SearchScopeType.SpecificFolders) - { - List folders = GetSpecifiedFolders(settings.IncludedFolders.ToList()); - RemoveOverlappingFolders(folders); - - foreach (SpecifiedFolder sf in folders) - { - //If specified folder doesn't exist then continue. - if (!Directory.Exists(sf.Path)) - continue; - - foreach (string path in GetPrefabFiles(sf.Path, excludedPaths, sf.Recursive)) - { - NetworkObject nob = AssetDatabase.LoadAssetAtPath(path); - if (nob != null) - foundNobs.Add(nob); - } - } - } - //Unhandled. - else - { - UnityDebug.LogError($"{settings.SearchScope} is not handled; default prefabs will not generator properly."); - } - - DefaultPrefabObjects prefabCollection = GetDefaultPrefabObjects(settings); - //No need to error if not found, GetDefaultPrefabObjects will throw. - if (prefabCollection == null) - return; - - //Clear and add built list. - prefabCollection.Clear(); - prefabCollection.AddObjects(foundNobs, false); - bool dirtied = prefabCollection.SetAssetPathHashes(0); - - int newCount = prefabCollection.GetObjectCount(); - if (log) - { - string dirtiedMessage = (newCount > 0) ? GetDirtiedMessage(settings, dirtied) : string.Empty; - UnityDebug.Log($"Default prefab generator found {newCount} prefabs in {sw.ElapsedMilliseconds}ms.{dirtiedMessage}"); - } - //Only set dirty if and save if prefabs were found. - if (newCount > 0) - { - EditorUtility.SetDirty(prefabCollection); - if (settings.SaveChanges) - AssetDatabase.SaveAssets(); - } - } - - /// - /// Iterates folders building them into SpecifiedFolders. - /// - private static List GetSpecifiedFolders(List folders) - { - List results = new List(); - //Remove astericks. - foreach (string path in folders) - { - int pLength = path.Length; - if (pLength == 0) - continue; - - bool recursive; - string p; - //If the last character indicates resursive. - if (path.Substring(pLength - 1, 1) == "*") - { - p = path.Substring(0, pLength - 1); - recursive = true; - } - else - { - p = path; - recursive = false; - } - - results.Add(new SpecifiedFolder(p, recursive)); - } - - return results; - } - - /// - /// Returns the DefaultPrefabObjects file. - /// - private static DefaultPrefabObjects GetDefaultPrefabObjects(PrefabGeneratorConfigurations settings = null) - { - if (settings == null) - settings = Configuration.Configurations.PrefabGenerator; - - //Load the prefab collection - string defaultPrefabsPath = settings.DefaultPrefabObjectsPath; - defaultPrefabsPath = defaultPrefabsPath.Replace(@"\", "/"); - string fullDefaultPrefabsPath = (defaultPrefabsPath.Length > 0) ? Path.GetFullPath(defaultPrefabsPath) : string.Empty; - - //If cached prefabs is not the same path as assetPath. - if (_cachedDefaultPrefabs != null) - { - string unityAssetPath = AssetDatabase.GetAssetPath(_cachedDefaultPrefabs); - string fullCachedPath = (unityAssetPath.Length > 0) ? Path.GetFullPath(unityAssetPath) : string.Empty; - if (fullCachedPath != fullDefaultPrefabsPath) - _cachedDefaultPrefabs = null; - } - - //If cached is null try to get it. - if (_cachedDefaultPrefabs == null) - { - //Only try to load it if file exist. - if (File.Exists(fullDefaultPrefabsPath)) - { - _cachedDefaultPrefabs = AssetDatabase.LoadAssetAtPath(defaultPrefabsPath); - if (_cachedDefaultPrefabs == null) - { - //If already retried then throw an error. - if (_retryRefreshDefaultPrefabs) - { - UnityDebug.LogError("DefaultPrefabObjects file exists but it could not be loaded by Unity. Use the Fish-Networking menu to Refresh Default Prefabs."); - } - else - { - UnityDebug.Log("DefaultPrefabObjects file exists but it could not be loaded by Unity. Trying to reload the file next frame."); - _retryRefreshDefaultPrefabs = true; - } - return null; - } - } - } - - if (_cachedDefaultPrefabs == null) - { - string fullPath = Path.GetFullPath(defaultPrefabsPath); - UnityDebug.Log($"Creating a new DefaultPrefabsObject at {fullPath}."); - string directory = Path.GetDirectoryName(fullPath); - - if (!Directory.Exists(directory)) - { - Directory.CreateDirectory(directory); - AssetDatabase.Refresh(); - } - - _cachedDefaultPrefabs = ScriptableObject.CreateInstance(); - AssetDatabase.CreateAsset(_cachedDefaultPrefabs, defaultPrefabsPath); - AssetDatabase.SaveAssets(); - } - - if (_cachedDefaultPrefabs != null && _retryRefreshDefaultPrefabs) - UnityDebug.Log("DefaultPrefabObjects found on the second iteration."); - return _cachedDefaultPrefabs; - } - - /// - /// Called every frame the editor updates. - /// - private static void OnEditorUpdate() - { - if (!_retryRefreshDefaultPrefabs) - return; - - GenerateFull(); - _retryRefreshDefaultPrefabs = false; - } - - /// - /// Called by Unity when assets are modified. - /// - private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) - { - if (Application.isPlaying) - return; - //If retrying next frame don't bother updating, next frame will do a full refresh. - if (_retryRefreshDefaultPrefabs) - return; - //Post process is being ignored. Could be temporary or user has disabled this feature. - if (IgnorePostProcess) - return; - /* Don't iterate if updating or compiling as that could cause an infinite loop - * due to the prefabs being generated during an update, which causes the update - * to start over, which causes the generator to run again, which... you get the idea. */ - if (EditorApplication.isCompiling) - return; - - DefaultPrefabObjects prefabCollection = GetDefaultPrefabObjects(); - if (prefabCollection == null) - return; - PrefabGeneratorConfigurations settings = Configuration.Configurations.PrefabGenerator; - - if (prefabCollection.GetObjectCount() == 0) - { - //If there are no prefabs then do a full rebuild. Odds of there being none are pretty much nill. - GenerateFull(settings); - } - else - { - int totalChanges = importedAssets.Length + deletedAssets.Length + movedAssets.Length + movedFromAssetPaths.Length; - //Nothing has changed. This shouldn't occur but unity is funny so we're going to check anyway. - if (totalChanges == 0) - return; - - //normalizes path. - string dpoPath = Path.GetFullPath(settings.DefaultPrefabObjectsPath); - //If total changes is 1 and the only changed file is the default prefab collection then do nothing. - if (totalChanges == 1) - { - //Do not need to check movedFromAssetPaths because that's not possible for this check. - if ((importedAssets.Length == 1 && Path.GetFullPath(importedAssets[0]) == dpoPath) - || (deletedAssets.Length == 1 && Path.GetFullPath(deletedAssets[0]) == dpoPath) - || (movedAssets.Length == 1 && Path.GetFullPath(movedAssets[0]) == dpoPath)) - return; - - /* If the only change is an import then check if the imported file - * is the same as the last, and if so check into returning early. - * For some reason occasionally when files are saved unity runs postprocess - * multiple times on the same file. */ - string imported = (importedAssets.Length == 1) ? importedAssets[0] : null; - if (imported != null && imported == _lastSingleImportedAsset) - { - //If here then the file is the same. Make sure it's already in the collection before returning. - System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(imported); - //Not a gameObject, no reason to continue. - if (assetType != typeof(GameObject)) - return; - - NetworkObject nob = AssetDatabase.LoadAssetAtPath(imported); - //If is a networked object. - if (nob != null) - { - //Already added! - if (prefabCollection.Prefabs.Contains(nob)) - return; - } - } - else if (imported != null) - { - _lastSingleImportedAsset = imported; - } - } - - - bool fullRebuild = settings.FullRebuild; - /* If updating FN. This needs to be done a better way. - * Parsing the actual version file would be better. - * I'll get to it next release. */ - if (!_ranOnce) - { - _ranOnce = true; - fullRebuild = true; - } - else - { - CheckForVersionFile(importedAssets); - CheckForVersionFile(deletedAssets); - CheckForVersionFile(movedAssets); - CheckForVersionFile(movedFromAssetPaths); - } - - /* See if any of the changed files are the version file. - * A new version file suggests an update. Granted, this could occur if - * other assets imported a new version file as well but better - * safe than sorry. */ - void CheckForVersionFile(string[] arr) - { - string targetText = "VERSION.txt".ToLower(); - int targetLength = targetText.Length; - - for (int i = 0; i < arr.Length; i++) - { - string item = arr[i]; - int itemLength = item.Length; - if (itemLength < targetLength) - continue; - - item = item.ToLower(); - int startIndex = (itemLength - targetLength); - if (item.Substring(startIndex, targetLength) == targetText) - { - fullRebuild = true; - return; - } - } - } - - if (fullRebuild) - GenerateFull(settings); - else - GenerateChanged(importedAssets, deletedAssets, movedAssets, movedFromAssetPaths, settings); - } - } - } -} - -#endif diff --git a/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Generator.cs.meta b/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Generator.cs.meta deleted file mode 100644 index 20b7c5c..0000000 --- a/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Generator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 68e990388e202d54aa0fe9e7aa8cc716 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Settings.cs b/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Settings.cs deleted file mode 100644 index 82a20af..0000000 --- a/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Settings.cs +++ /dev/null @@ -1,103 +0,0 @@ -#if UNITY_EDITOR - -using System; -using System.Collections.Generic; -using System.IO; -using UnityEngine; - -namespace FishNet.Editing.PrefabCollectionGenerator -{ - internal sealed class PrefabCollectionGeneratorConfigurationsz - { - #region Types. - public enum SearchScopeType : byte - { - EntireProject = 0, - SpecificFolders = 1 - } - #endregion - - //#region Public. - ///// - ///// True if prefab generation is enabled. - ///// - //public bool Enabled; - ///// - ///// True to rebuild all prefabs during any change. False to only check changed prefabs. - ///// - //public bool FullRebuild; - ///// - ///// True to log results to console. - ///// - //public bool LogToConsole; - ///// - ///// True to automatically save assets when default prefabs change. - ///// - //public bool SaveChanges; - ///// - ///// Path where prefabs file is created. - ///// - //public string AssetPath; - ///// - ///// How to search for files. - ///// - //public SearchScopeType SearchScope = SearchScopeType.EntireProject; - ///// - ///// Folders to exclude when using SearchScopeType.SpecificFolders. - ///// - //public List ExcludedFolders = new List(); - ///// - ///// Folders to include when using SearchScopeType.SpecificFolders. - ///// - //public List IncludedFolders = new List(); - //#endregion - - //#region Private. - ///// - ///// Library folder for project. Presumably where files are saved, but this is changing. This is going away in favor of FN config. //fnconfig. - ///// - //private static string DirectoryPath => Path.Combine(Path.GetDirectoryName(Application.dataPath), "Library"); - ///// - ///// Full path of settings file. This is going away in favor of FN config. //fnconfig. - ///// - //private static string FilePath => Path.Combine(DirectoryPath, $"FishNet.Runtime.Editor.PrefabObjects.Generation.{nameof(Settings)}.json"); - // #endregion - - // public Settings() - //{ - // Enabled = true; - // LogToConsole = true; - // FullRebuild = false; - // SaveChanges = true; - // SearchScope = SearchScopeType.EntireProject; - - // AssetPath = $"Assets{Path.DirectorySeparatorChar}FishNet{Path.DirectorySeparatorChar}Runtime{Path.DirectorySeparatorChar}DefaultPrefabObjects.asset"; - //} - - //public void Save() - //{ - // //Create save folder if it doesn't exist. This is going away in favor of FN config. //fnconfig. - // if (!Directory.Exists(DirectoryPath)) - // Directory.CreateDirectory(DirectoryPath); - - // File.WriteAllText(FilePath, JsonUtility.ToJson(this)); - //} - - //public static Settings Load() - //{ - // try - // { - // if (File.Exists(FilePath)) - // return JsonUtility.FromJson(File.ReadAllText(FilePath)); - // } - // catch (Exception ex) - // { - // Debug.LogError($"An error has occurred when loading the prefab collection generator settings: {ex}"); - // } - - // return new Settings(); - //} - } -} - -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Settings.cs.meta b/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Settings.cs.meta deleted file mode 100644 index ef397a2..0000000 --- a/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/Settings.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0fa5ae5e1c43e004c87577ab53180f70 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/SettingsProvider.cs b/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/SettingsProvider.cs deleted file mode 100644 index c3a73bf..0000000 --- a/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/SettingsProvider.cs +++ /dev/null @@ -1,238 +0,0 @@ -#if UNITY_EDITOR - -using System; -using System.Collections.Generic; -using System.IO; -using System.Text.RegularExpressions; -using UnityEditor; -using UnityEngine; - -using UnitySettingsProviderAttribute = UnityEditor.SettingsProviderAttribute; -using UnitySettingsProvider = UnityEditor.SettingsProvider; -using FishNet.Configuring; -using System.Linq; - -namespace FishNet.Editing.PrefabCollectionGenerator -{ - internal static class SettingsProvider - { - private static readonly Regex SlashRegex = new Regex(@"[\\//]"); - - private static PrefabGeneratorConfigurations _settings; - - private static GUIContent _folderIcon; - private static GUIContent _deleteIcon; - - private static Vector2 _scrollVector; - - private static bool _showFolders; - - [UnitySettingsProvider] - private static UnitySettingsProvider Create() - { - return new UnitySettingsProvider("Project/Fish-Networking/Prefab Objects Generator", SettingsScope.Project) - { - label = "Prefab Objects Generator", - - guiHandler = OnGUI, - - keywords = new string[] - { - "Fish", - "Networking", - "Prefab", - "Objects", - "Generator", - }, - }; - } - - private static void OnGUI(string searchContext) - { - if (_settings == null) - _settings = Configuration.Configurations.PrefabGenerator; - if (_folderIcon == null) - _folderIcon = EditorGUIUtility.IconContent("d_FolderOpened Icon"); - if (_deleteIcon == null) - _deleteIcon = EditorGUIUtility.IconContent("P4_DeletedLocal"); - - EditorGUI.BeginChangeCheck(); - GUIStyle scrollViewStyle = new GUIStyle() - { - padding = new RectOffset(10, 10, 10, 10), - }; - - _scrollVector = EditorGUILayout.BeginScrollView(_scrollVector, scrollViewStyle); - - _settings.Enabled = EditorGUILayout.Toggle(ObjectNames.NicifyVariableName(nameof(_settings.Enabled)), _settings.Enabled); - _settings.LogToConsole = EditorGUILayout.Toggle(ObjectNames.NicifyVariableName(nameof(_settings.LogToConsole)), _settings.LogToConsole); - _settings.FullRebuild = EditorGUILayout.Toggle(ObjectNames.NicifyVariableName(nameof(_settings.FullRebuild)), _settings.FullRebuild); - _settings.SaveChanges = EditorGUILayout.Toggle(ObjectNames.NicifyVariableName(nameof(_settings.SaveChanges)), _settings.SaveChanges); - - GUILayoutOption iconWidthConstraint = GUILayout.MaxWidth(32.0f); - GUILayoutOption iconHeightConstraint = GUILayout.MaxHeight(EditorGUIUtility.singleLineHeight); - - EditorGUILayout.BeginHorizontal(); - - string oldAssetPath = _settings.DefaultPrefabObjectsPath; - string newAssetPath = EditorGUILayout.DelayedTextField(ObjectNames.NicifyVariableName(nameof(_settings.DefaultPrefabObjectsPath)), oldAssetPath); - - if (GUILayout.Button(_folderIcon, iconWidthConstraint, iconHeightConstraint)) - { - if (TrySaveFilePathInsideAssetsFolder(null, Application.dataPath, "DefaultPrefabObjects", "asset", out string result)) - newAssetPath = result; - else - EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{ObjectNames.NicifyVariableName(nameof(_settings.DefaultPrefabObjectsPath))} must be inside the Assets folder.")); - } - - if (!newAssetPath.Equals(oldAssetPath, StringComparison.OrdinalIgnoreCase)) - { - if (newAssetPath.StartsWith($"Assets{Path.DirectorySeparatorChar}", StringComparison.OrdinalIgnoreCase)) - { - if (File.Exists(newAssetPath)) - { - EditorWindow.focusedWindow.ShowNotification(new GUIContent("Another asset already exists at the new path.")); - } - else - { - Generator.IgnorePostProcess = true; - - if (File.Exists(oldAssetPath)) - AssetDatabase.MoveAsset(oldAssetPath, newAssetPath); - _settings.DefaultPrefabObjectsPath = newAssetPath; - - Generator.IgnorePostProcess = false; - } - } - else - { - EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{ObjectNames.NicifyVariableName(nameof(_settings.DefaultPrefabObjectsPath))} must be inside the Assets folder.")); - } - } - - EditorGUILayout.EndHorizontal(); - - int currentSearchScope = _settings.SearchScope; - SearchScopeType searchScopeType = (SearchScopeType)EditorGUILayout.EnumPopup(ValueToSearchScope(_settings.SearchScope)); - _settings.SearchScope = (int)searchScopeType; - SearchScopeType ValueToSearchScope(int value) => (SearchScopeType)value; - if (_settings.SearchScope == (int)SearchScopeType.EntireProject) - { - EditorGUILayout.HelpBox("Searching the entire project for prefabs can become very slow. Consider switching the search scope to specific folders instead.", MessageType.Warning); - - if (GUILayout.Button("Switch")) - _settings.SearchScope = (int)SearchScopeType.SpecificFolders; - } - //If search scope changed then update prefabs. - if (currentSearchScope != _settings.SearchScope && (SearchScopeType)_settings.SearchScope == SearchScopeType.EntireProject) - Generator.GenerateFull(); - - List folders = null; - string foldersName = null; - - if (_settings.SearchScope == (int)SearchScopeType.EntireProject) - { - folders = _settings.ExcludedFolders; - foldersName = ObjectNames.NicifyVariableName(nameof(_settings.ExcludedFolders)); - } - else if (_settings.SearchScope == (int)SearchScopeType.SpecificFolders) - { - folders = _settings.IncludedFolders; - foldersName = ObjectNames.NicifyVariableName(nameof(_settings.IncludedFolders)); - } - - string folderName = foldersName.Substring(0, foldersName.Length - 1); - - if ((_showFolders = EditorGUILayout.Foldout(_showFolders, $"{foldersName} ({folders.Count})")) && folders != null) - { - EditorGUI.indentLevel++; - - for (int i = 0; i < folders.Count; i++) - { - EditorGUILayout.BeginHorizontal(); - - string oldFolder = folders[i]; - string newFolder = SlashRegex.Replace(EditorGUILayout.DelayedTextField(oldFolder), Path.DirectorySeparatorChar.ToString()); - if (!newFolder.Equals(oldFolder, StringComparison.OrdinalIgnoreCase)) - { - if (newFolder.StartsWith($"Assets{Path.DirectorySeparatorChar}", StringComparison.OrdinalIgnoreCase)) - folders[i] = newFolder; - else - EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{folderName} must be inside the Assets folder.")); - } - - if (GUILayout.Button(_folderIcon, iconWidthConstraint, iconHeightConstraint)) - { - if (TryOpenFolderPathInsideAssetsFolder(null, Application.dataPath, null, out string result)) - folders[i] = result; - else - EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{folderName} must be inside the Assets folder.")); - } - - if (GUILayout.Button(_deleteIcon, iconWidthConstraint, iconHeightConstraint)) folders.RemoveAt(i); - - EditorGUILayout.EndHorizontal(); - } - - EditorGUI.indentLevel--; - - if (_settings.SearchScope == (int)SearchScopeType.SpecificFolders) EditorGUILayout.HelpBox("You can include subfolders by appending an asterisk (*) to a path.", MessageType.None); - - if (GUILayout.Button("Browse")) - { - if (TryOpenFolderPathInsideAssetsFolder(null, Application.dataPath, null, out string result)) - { - folders.Add(result); - } - else - { - EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{folderName} must be inside the Assets folder.")); - } - } - } - - if (EditorGUI.EndChangeCheck()) - Configuration.Configurations.Write(true); - if (GUILayout.Button("Generate")) - Generator.GenerateFull(); - - EditorGUILayout.HelpBox("Consider pressing 'Generate' after changing the settings.", MessageType.Info); - - EditorGUILayout.EndScrollView(); - } - - private static bool TrySaveFilePathInsideAssetsFolder(string title, string directory, string name, string extension, out string result) - { - result = null; - - string selectedPath = EditorUtility.SaveFilePanel(title, directory, name, extension); - - if (selectedPath.StartsWith(Application.dataPath, StringComparison.OrdinalIgnoreCase)) - { - result = SlashRegex.Replace(selectedPath.Remove(0, Path.GetDirectoryName(Application.dataPath).Length + 1), Path.DirectorySeparatorChar.ToString()); - - return true; - } - - return false; - } - - private static bool TryOpenFolderPathInsideAssetsFolder(string title, string folder, string name, out string result) - { - result = null; - - string selectedPath = EditorUtility.OpenFolderPanel(title, folder, name); - - if (selectedPath.StartsWith(Application.dataPath, StringComparison.OrdinalIgnoreCase)) - { - result = SlashRegex.Replace(selectedPath.Remove(0, Path.GetDirectoryName(Application.dataPath).Length + 1), Path.DirectorySeparatorChar.ToString()); - - return true; - } - - return false; - } - } -} - -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/SettingsProvider.cs.meta b/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/SettingsProvider.cs.meta deleted file mode 100644 index 01a488e..0000000 --- a/Assets/FishNet/Runtime/Editor/PrefabCollectionGenerator/SettingsProvider.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7451fcc5eeb5b89468ab2ce22f678b26 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/PrefabProcessor.cs b/Assets/FishNet/Runtime/Editor/PrefabProcessor.cs deleted file mode 100644 index ea1fa69..0000000 --- a/Assets/FishNet/Runtime/Editor/PrefabProcessor.cs +++ /dev/null @@ -1,85 +0,0 @@ -//#if UNITY_EDITOR -//using FishNet.Managing.Object; -//using FishNet.Object; -//using UnityEditor; -//using UnityEngine; - -//namespace FishNet.Editing -//{ -// internal class PrefabProcessor : AssetPostprocessor -// { -// #region Private. -// /// -// /// ScriptableObject to store default prefabs. -// /// -// private static DefaultPrefabObjects _defaultPrefabs; -// #endregion - -// /// -// /// Called after assets are created or imported. -// /// -// /// -// /// -// /// -// /// -//#if UNITY_2021_3_OR_NEWER -// private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths, bool didDomainReload) -//#else -// private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) -//#endif -// { - -//#if UNITY_2021_3_OR_NEWER -// if (didDomainReload) -// return; -//#endif -// bool justPopulated; -// if (_defaultPrefabs == null) -// _defaultPrefabs = DefaultPrefabsFinder.GetDefaultPrefabsFile(out justPopulated); -// else -// justPopulated = DefaultPrefabsFinder.PopulateDefaultPrefabs(); -// //Not found. -// if (_defaultPrefabs == null) -// return; - -// //True if null must be removed as well. -// bool removeNull = (deletedAssets.Length > 0 || movedAssets.Length > 0 || movedFromAssetPaths.Length > 0); -// if (removeNull) -// _defaultPrefabs.RemoveNull(); - -// /* Only need to add new prefabs if not justPopulated. -// * justPopulated would have already picked up the new prefabs. */ -// if (justPopulated) -// return; - -// System.Type goType = typeof(UnityEngine.GameObject); -// foreach (string item in importedAssets) -// { -// System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(item); -// if (assetType != goType) -// continue; - -// GameObject go = (GameObject)AssetDatabase.LoadAssetAtPath(item, typeof(GameObject)); -// //If is a gameobject. -// if (go != null) -// { - -// NetworkObject nob; -// //Not a network object. -// if (!go.TryGetComponent(out nob)) -// continue; - -// /* Check for duplicates because adding a component to a prefab will also call this function -// * which will result in this function calling multiple times for the same object. */ -// _defaultPrefabs.AddObject(nob, true); -// } -// } - -// EditorUtility.SetDirty(_defaultPrefabs); -// } - -// } - -//} - -//#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Editor/PrefabProcessor.cs.meta b/Assets/FishNet/Runtime/Editor/PrefabProcessor.cs.meta deleted file mode 100644 index 5c1d41e..0000000 --- a/Assets/FishNet/Runtime/Editor/PrefabProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f78656ace4bbad94288ff6238a2b518c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/ScriptingDefines.cs b/Assets/FishNet/Runtime/Editor/ScriptingDefines.cs deleted file mode 100644 index 2ef6eae..0000000 --- a/Assets/FishNet/Runtime/Editor/ScriptingDefines.cs +++ /dev/null @@ -1,74 +0,0 @@ -#if UNITY_EDITOR -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; - -namespace FishNet -{ - internal static class ScriptingDefines - { - [InitializeOnLoadMethod] - public static void AddDefineSymbols() - { - string currentDefines = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup); - /* Convert current defines into a hashset. This is so we can - * determine if any of our defines were added. Only save playersettings - * when a define is added. */ - HashSet definesHs = new HashSet(); - string[] currentArr = currentDefines.Split(';'); - //Add current defines into hs. - foreach (string item in currentArr) - definesHs.Add(item); - - string proDefine = "FISHNET_PRO"; - string versionPrefix = "FISHNET_V"; - string thisVersion = $"{versionPrefix}3"; - string[] fishNetDefines = new string[] - { - "FISHNET", - thisVersion, - - }; - bool modified = false; - //Now add FN defines. - foreach (string item in fishNetDefines) - modified |= definesHs.Add(item); - - /* Remove pro define if not on pro. This might look a little - * funny because the code below varies depending on if pro or not. */ - -#pragma warning disable CS0162 // Unreachable code detected - modified |= definesHs.Remove(proDefine); -#pragma warning restore CS0162 // Unreachable code detected - - List definesToRemove = new List(); - int versionPrefixLength = versionPrefix.Length; - //Remove old versions. - foreach (string item in definesHs) - { - //Do not remove this version. - if (item == thisVersion) - continue; - - //If length is possible to be a version prefix and is so then remove it. - if (item.Length >= versionPrefixLength && item.Substring(0, versionPrefixLength) == versionPrefix) - definesToRemove.Add(item); - } - - modified |= (definesToRemove.Count > 0); - foreach (string item in definesToRemove) - { - definesHs.Remove(item); - Debug.Log($"Removed unused Fish-Networking define {item}."); - } - - if (modified) - { - Debug.Log("Added or removed Fish-Networking defines within player settings."); - string changedDefines = string.Join(";", definesHs); - PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, changedDefines); - } - } - } -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Editor/ScriptingDefines.cs.meta b/Assets/FishNet/Runtime/Editor/ScriptingDefines.cs.meta deleted file mode 100644 index 4ebc6d2..0000000 --- a/Assets/FishNet/Runtime/Editor/ScriptingDefines.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 893e5074d486a0e4aaf7803436fef791 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Textures.meta b/Assets/FishNet/Runtime/Editor/Textures.meta deleted file mode 100644 index c8e8ef0..0000000 --- a/Assets/FishNet/Runtime/Editor/Textures.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 0c9efa228205fac47af86971242e97f9 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Textures/Icon.meta b/Assets/FishNet/Runtime/Editor/Textures/Icon.meta deleted file mode 100644 index ed9af2f..0000000 --- a/Assets/FishNet/Runtime/Editor/Textures/Icon.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: cc19ac8f58640dd4bb062b1024d23ecc -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Textures/Icon/fishnet_light.png b/Assets/FishNet/Runtime/Editor/Textures/Icon/fishnet_light.png deleted file mode 100644 index 084c0e6e72afce3e99d539e25ee751517c2fad53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41016 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 diff --git a/Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Client_Background.png.meta b/Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Client_Background.png.meta deleted file mode 100644 index be69e05..0000000 --- a/Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Client_Background.png.meta +++ /dev/null @@ -1,116 +0,0 @@ -fileFormatVersion: 2 -guid: 2d50394614f8feb4eb0567fb7618d84d -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 11 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 0 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - applyGammaDecoding: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: iPhone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - spritePackingTag: - pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Indicator.png b/Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Indicator.png deleted file mode 100644 index 80192f5c3b75d720fe814c5d2e1efc17c621a068..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2891 zcmcIm4QvzV8Gg@LjYCBtguj&~9M_gDr04tb|1D0O#wl@%QwZ6BvaLDaontq#&$TbH z!${(lNrXQwYFU3m(nghNw``(_qG~DasMc*^o7!a4wlWpakd%fsj3sREIgZ;+ zfuTxRw(ooIp6~gd_wV~|_lCN43+CTG9{?8kYP|IT1{^}#bPN7>Z2rToc*&2|Y)t^% zTB!dB=gk>ZZnzpP(_GZZ?Qx)Z8SxP{Hh@y#PD$){72q`y};T3SK-)1N> z1JRn@RHeQkxy8SMtWx6&=`eG&#Ih{uaG6D?!@>nzcauEJa}4XkFU_)o#UWUnWcEYh za&b8*)O+vEE{2wy3TawQV3=ewX--L`c1c zAGyalZ(>4KToE-j-k_>2vzgj3%R=%NGfRGbb2uui$wY~+C_6#%ikjl4^sLbwN3+%j zjuSYSz}j#uu;^$yh4hP$B1nTz-zGy-dqmttDx+xT84u@qy zlx2&Jm29-cDK1*!txnn*pBr7tNy&aw-dN-zXhBg^ekn}pqpMfRR zpq3QlN@Wv9`u`Reb1m@+vF-ZOt#+1IWQ&A5hl``FL90XuB*{rzoYtU|54boRXPkm|c|dZe~AxnlVJce{^2*VDhg`RF&E7~S7z z{`QjZe0J~4=WRbJec`qKr6X?b&((Xo=hxjy`kp(u>Qr@m1g{HjqbtEAwx3%!77QdSGy{x4*xC z`q6*g2A`f9>3}zWI`~jqXXn+6XV0G9G`0;+zFwGa{MK-n^Q&jd^U~{$9#S1XaroTn zuMs`F!Su_^^N!Slv2lt>-3OQYF6O79G11*i_+eXjt5!_Y@$DTxUv(a;(Zu;OD&TV`PpCY)I zga>|gdEV#}Vs!CuR;AZm__#cMU~GJR+{`dt9jVmMi*DN$wjcbcJU{((Av{Gd+pD#< z{^RY5iHQp#Ywg}&Q{u^Ln;!ToNuT z{--)F4JpPc?wOHw2#ORy(T2xAdjC^j+60ZI z7>#boM57x`49@T?`_r$wA6yLwUo0*h-iOqf$z5K6cPZFjYlKg1hJj%; zA4IbbO_zZLl)TMAn((rgScGcct1ysH{>bF)t9yQEgdhuvMWehS8hr7u&Pf_R+=%_u zSAV5^aY^a{{*WH$Nt<8 diff --git a/Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Indicator.png.meta b/Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Indicator.png.meta deleted file mode 100644 index 7eb6afd..0000000 --- a/Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Indicator.png.meta +++ /dev/null @@ -1,116 +0,0 @@ -fileFormatVersion: 2 -guid: 2b3dca501a9d8c8479dc71dd068aa8b8 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 11 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 0 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - applyGammaDecoding: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: iPhone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - spritePackingTag: - pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Server_Background.png b/Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Server_Background.png deleted file mode 100644 index f4d8573a31783396f036b118ea9fd01a0a932a88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9320 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 IYS@SU7bo}6y#N3J diff --git a/Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Server_Background.png.meta b/Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Server_Background.png.meta deleted file mode 100644 index 54f3c33..0000000 --- a/Assets/FishNet/Runtime/Editor/Textures/UI/Button_Dark_Server_Background.png.meta +++ /dev/null @@ -1,116 +0,0 @@ -fileFormatVersion: 2 -guid: 1b187e63031bf7849b249c8212440c3b -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 11 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 0 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - applyGammaDecoding: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: iPhone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - spritePackingTag: - pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Editor/Textures/UI/Logo_With_Text.png b/Assets/FishNet/Runtime/Editor/Textures/UI/Logo_With_Text.png deleted file mode 100644 index 5e5d02e1a9508802f7d1942fd957366adbd7f02e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37614 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 Tc+Vsu;MWT!4aI7Ci=h7lQEy3% diff --git a/Assets/FishNet/Runtime/Editor/Textures/UI/Logo_With_Text.png.meta b/Assets/FishNet/Runtime/Editor/Textures/UI/Logo_With_Text.png.meta deleted file mode 100644 index 23c249b..0000000 --- a/Assets/FishNet/Runtime/Editor/Textures/UI/Logo_With_Text.png.meta +++ /dev/null @@ -1,96 +0,0 @@ -fileFormatVersion: 2 -guid: 5ea1cf1e0e57aff4e9ad3cd4246b0e80 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 11 - mipmaps: - mipMapMode: 0 - enableMipMap: 1 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 1 - aniso: 1 - mipBias: 0 - wrapU: 0 - wrapV: 0 - wrapW: 0 - nPOTScale: 1 - lightmap: 0 - compressionQuality: 50 - spriteMode: 0 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 0 - spriteTessellationDetail: -1 - textureType: 0 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - spritePackingTag: - pSDRemoveMatte: 0 - pSDShowRemoveMatteOption: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/FishNet.Runtime.asmdef b/Assets/FishNet/Runtime/FishNet.Runtime.asmdef deleted file mode 100644 index 9ff34a4..0000000 --- a/Assets/FishNet/Runtime/FishNet.Runtime.asmdef +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "FishNet.Runtime", - "references": [ - "GUID:9e24947de15b9834991c9d8411ea37cf", - "GUID:84651a3751eca9349aac36a66bba901b", - "GUID:69448af7b92c7f342b298e06a37122aa" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": true, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/FishNet.Runtime.asmdef.meta b/Assets/FishNet/Runtime/FishNet.Runtime.asmdef.meta deleted file mode 100644 index f153703..0000000 --- a/Assets/FishNet/Runtime/FishNet.Runtime.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 7c88a4a7926ee5145ad2dfa06f454c67 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated.meta b/Assets/FishNet/Runtime/Generated.meta deleted file mode 100644 index 396b552..0000000 --- a/Assets/FishNet/Runtime/Generated.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: ff7d76a12b1ab04449cefe1ba58b5cde -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component.meta b/Assets/FishNet/Runtime/Generated/Component.meta deleted file mode 100644 index 9074fd6..0000000 --- a/Assets/FishNet/Runtime/Generated/Component.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 953b8f1e48e9769439f19dc81a0406dc -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator.meta b/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator.meta deleted file mode 100644 index b910d85..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 40310629b512873468cfaf757b6fd377 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/Editor.meta b/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/Editor.meta deleted file mode 100644 index a5402a7..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e5ab06c5b11d85d4688a573ad0fdefdd -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/Editor/NetworkAnimatorEditor.cs b/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/Editor/NetworkAnimatorEditor.cs deleted file mode 100644 index 6e7576b..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/Editor/NetworkAnimatorEditor.cs +++ /dev/null @@ -1,187 +0,0 @@ -#if UNITY_EDITOR -using FishNet.Editing; -using System.Collections.Generic; -using UnityEditor; -using UnityEditor.Animations; -using UnityEngine; - -namespace FishNet.Component.Animating.Editing -{ - - [CustomEditor(typeof(NetworkAnimator), true)] - [CanEditMultipleObjects] - public class NetworkAnimatorEditor : Editor - { - private SerializedProperty _animator; - private SerializedProperty _interpolation; - //private SerializedProperty _synchronizeInterval; - private SerializedProperty _smoothFloats; - private SerializedProperty _clientAuthoritative; - private SerializedProperty _sendToOwner; - private RuntimeAnimatorController _lastRuntimeAnimatorController; - private AnimatorController _lastAnimatorController; - - protected virtual void OnEnable() - { - _animator = serializedObject.FindProperty("_animator"); - _interpolation = serializedObject.FindProperty("_interpolation"); - //_synchronizeInterval = serializedObject.FindProperty("_synchronizeInterval"); - _smoothFloats = serializedObject.FindProperty("_smoothFloats"); - - _clientAuthoritative = serializedObject.FindProperty("_clientAuthoritative"); - _sendToOwner = serializedObject.FindProperty("_sendToOwner"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - NetworkAnimator na = (NetworkAnimator)target; - - GUI.enabled = false; - EditorGUILayout.ObjectField("Script:", MonoScript.FromMonoBehaviour(na), typeof(NetworkAnimator), false); - GUI.enabled = true; - - -#pragma warning disable CS0162 // Unreachable code detected - EditorGUILayout.HelpBox(EditingConstants.PRO_ASSETS_LOCKED_TEXT, MessageType.Warning); -#pragma warning restore CS0162 // Unreachable code detected - - //Animator - EditorGUILayout.LabelField("Animator", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_animator, new GUIContent("Animator", "The animator component to synchronize.")); - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - - //Synchronization Processing. - EditorGUILayout.LabelField("Synchronization Processing", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_interpolation); - //EditorGUILayout.PropertyField(_synchronizeInterval, new GUIContent("Synchronize Interval", "How often to synchronize this animator.")); - EditorGUILayout.PropertyField(_smoothFloats, new GUIContent("Smooth Floats", "True to smooth floats on spectators rather than snap to their values immediately. Commonly set to true for smooth blend tree animations.")); - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - - //Authority. - EditorGUILayout.LabelField("Authority", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_clientAuthoritative, new GUIContent("Client Authoritative", "True if using client authoritative movement.")); - if (_clientAuthoritative.boolValue == false) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_sendToOwner, new GUIContent("Synchronize To Owner", "True to synchronize server results back to owner. Typically used when you are sending inputs to the server and are relying on the server response to move the transform.")); - EditorGUI.indentLevel--; - } - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - - DrawParameters(na); - - serializedObject.ApplyModifiedProperties(); - } - - - private void DrawParameters(NetworkAnimator na) - { - EditorGUILayout.LabelField("* Synchronized Parameters", EditorStyles.boldLabel); - EditorGUILayout.HelpBox("This setting allows you to optionally completely prevent the synchronization of certain parameters. Both Fish-Networking free and Pro will only synchronize changes as they occur.", MessageType.Info); - - if (Application.isPlaying) - { - EditorGUILayout.HelpBox("This feature can only be configured while out of play mode.", MessageType.Info); - return; - } - if (na == null) - return; - Animator animator = na.Animator; - if (animator == null) - return; - - RuntimeAnimatorController runtimeController = (animator.runtimeAnimatorController is AnimatorOverrideController aoc) ? aoc.runtimeAnimatorController : animator.runtimeAnimatorController; - if (runtimeController == null) - { - na.IgnoredParameters.Clear(); - return; - } - - /* If runtime controller changed - * or editor controller is null - * then get new editor controller. */ - if (runtimeController != _lastRuntimeAnimatorController || _lastAnimatorController == null) - _lastAnimatorController = (AnimatorController)AssetDatabase.LoadAssetAtPath(AssetDatabase.GetAssetPath(runtimeController), typeof(AnimatorController)); - _lastRuntimeAnimatorController = runtimeController; - - Color defaultColor = GUI.backgroundColor; - float width = Screen.width; - float spacePerEntry = 125f; - //Buttons seem to be longer than spacePerEntry. Why, because who knows... - float extraSpaceJustBecause = 60; - float spacer = 20f; - width -= spacer; - int entriesPerWidth = Mathf.Max(1, Mathf.FloorToInt(width / (spacePerEntry + extraSpaceJustBecause))); - - List aps = new List(); - //Create a parameter detail for each parameter that can be synchronized. - int count = 0; - foreach (AnimatorControllerParameter item in _lastAnimatorController.parameters) - { - count++; - //Over 240 parameters; who would do this!? - if (count >= 240) - continue; - - aps.Add(item); - } - - int apsCount = aps.Count; - for (int i = 0; i < apsCount; i++) - { - using (GUILayout.HorizontalScope hs = new GUILayout.HorizontalScope()) - { - GUILayout.Space(spacer); - int z = 0; - while (z < entriesPerWidth && (z + i < apsCount)) - { - //If this z+i would exceed entries then break. - if (z + i >= apsCount) - break; - - AnimatorControllerParameter item = aps[i + z]; - string parameterName = item.name; - bool ignored = na.IgnoredParameters.Contains(parameterName); - - Color c = (ignored) ? Color.gray : Color.green; - GUI.backgroundColor = c; - if (GUILayout.Button(item.name, GUILayout.Width(spacePerEntry))) - { - if (Application.isPlaying) - { - Debug.Log("Synchronized parameters may not be changed while playing."); - } - else - { - if (ignored) - na.IgnoredParameters.Remove(parameterName); - else - na.IgnoredParameters.Add(parameterName); - } - } - - z++; - } - - i += (z - 1); - } - - GUI.backgroundColor = defaultColor; - } - } - - - - } - -} - - -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/Editor/NetworkAnimatorEditor.cs.meta b/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/Editor/NetworkAnimatorEditor.cs.meta deleted file mode 100644 index c72bdf3..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/Editor/NetworkAnimatorEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 65609e99a0823a347a2f615b0e6f736e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/NetworkAnimator.cs b/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/NetworkAnimator.cs deleted file mode 100644 index e33cdfc..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/NetworkAnimator.cs +++ /dev/null @@ -1,1449 +0,0 @@ -using FishNet.Component.Transforming; -using FishNet.Connection; -using FishNet.Documenting; -using FishNet.Managing.Logging; -using FishNet.Managing.Server; -using FishNet.Object; -using FishNet.Serializing; -using FishNet.Utility; -using FishNet.Utility.Performance; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - - -namespace FishNet.Component.Animating -{ - [AddComponentMenu("FishNet/Component/NetworkAnimator")] - public sealed class NetworkAnimator : NetworkBehaviour - { - #region Types. - ///

- /// Data received from the server. - /// - private struct ReceivedServerData - { - /// - /// Gets an Arraysegment of received data. - /// - public ArraySegment GetArraySegment() => new ArraySegment(_data, 0, _length); - /// - /// How much data written. - /// - private int _length; - /// - /// Buffer which contains data. - /// - private byte[] _data; - - public ReceivedServerData(ArraySegment segment) - { - _length = segment.Count; - _data = ByteArrayPool.Retrieve(_length); - Buffer.BlockCopy(segment.Array, segment.Offset, _data, 0, _length); - } - - public void Dispose() - { - if (_data != null) - ByteArrayPool.Store(_data); - } - } - private struct StateChange - { - /// - /// True if a crossfade. - /// - public bool IsCrossfade; - /// - /// Hash to crossfade into. - /// - public int Hash; - /// - /// True if using FixedTime. - /// - public bool FixedTime; - /// - /// Duration of crossfade. - /// - public float DurationTime; - /// - /// Offset time of crossfade. - /// - public float OffsetTime; - /// - /// Normalized transition time of crossfade. - /// - public float NormalizedTransitionTime; - - public StateChange(int hash, bool fixedTime, float duration, float offset, float normalizedTransition) - { - IsCrossfade = true; - Hash = hash; - FixedTime = fixedTime; - DurationTime = duration; - OffsetTime = offset; - NormalizedTransitionTime = normalizedTransition; - } - } - /// - /// Animator updates received from clients when using Client Authoritative. - /// - private class ClientAuthoritativeUpdate - { - /// - /// - /// - public ClientAuthoritativeUpdate() - { - //Start buffers off at 8 bytes nad grow them as needed. - for (int i = 0; i < MAXIMUM_BUFFER_COUNT; i++) - _buffers.Add(new byte[MAXIMUM_DATA_SIZE]); - - _bufferLengths = new int[MAXIMUM_BUFFER_COUNT]; - } - - #region Public. - /// - /// True to force all animator data and ignore buffers. - /// - public bool ForceAll { get; private set; } - /// - /// Number of entries in Buffers. - /// - public int BufferCount = 0; - #endregion - - #region Private. - /// - /// Length of buffers. - /// - private int[] _bufferLengths; - /// - /// Buffers. - /// - private List _buffers = new List(); - #endregion - - #region Const. - /// - /// Maximum size data may be. - /// - private const int MAXIMUM_DATA_SIZE = 1000; - /// - /// Maximum number of allowed buffers. - /// - public const int MAXIMUM_BUFFER_COUNT = 2; - #endregion - - public void AddToBuffer(ref ArraySegment data) - { - int dataCount = data.Count; - /* Data will never get this large, it's quite impossible. - * Just ignore the data if it does, client is likely performing - * an attack. */ - if (dataCount > MAXIMUM_DATA_SIZE) - return; - - //If index exceeds buffer count. - if (BufferCount >= MAXIMUM_BUFFER_COUNT) - { - ForceAll = true; - return; - } - - /* If here, can write to buffer. */ - byte[] buffer = _buffers[BufferCount]; - Buffer.BlockCopy(data.Array, data.Offset, buffer, 0, dataCount); - _bufferLengths[BufferCount] = dataCount; - BufferCount++; - } - - /// - /// Sets referenced data to buffer and it's length for index. - /// - /// - /// - /// - public void GetBuffer(int index, ref byte[] buffer, ref int length) - { - if (index > _buffers.Count) - { - Debug.LogWarning("Index exceeds Buffers count."); - return; - } - if (index > _bufferLengths.Length) - { - Debug.LogWarning("Index exceeds BufferLengths count."); - return; - } - - buffer = _buffers[index]; - length = _bufferLengths[index]; - } - /// - /// Resets buffers. - /// - public void Reset() - { - BufferCount = 0; - ForceAll = false; - } - - } - /// - /// Information on how to smooth to a float value. - /// - private struct SmoothedFloat - { - public SmoothedFloat(float rate, float target) - { - Rate = rate; - Target = target; - } - - public readonly float Rate; - public readonly float Target; - } - - /// - /// Details about a trigger update. - /// - private struct TriggerUpdate - { - public byte ParameterIndex; - public bool Setting; - - public TriggerUpdate(byte parameterIndex, bool setting) - { - ParameterIndex = parameterIndex; - Setting = setting; - } - } - /// - /// Details about an animator parameter. - /// - private class ParameterDetail - { - /// - /// Parameter information. - /// - public readonly AnimatorControllerParameter ControllerParameter = null; - /// - /// Index within the types collection for this parameters value. The exception is with triggers; if the parameter type is a trigger then a value of 1 is set, 0 is unset. - /// - public readonly byte TypeIndex = 0; - /// - /// Hash for the animator string. - /// - public readonly int Hash; - - public ParameterDetail(AnimatorControllerParameter controllerParameter, byte typeIndex) - { - ControllerParameter = controllerParameter; - TypeIndex = typeIndex; - Hash = controllerParameter.nameHash; - } - } - #endregion - - #region Public. - /// - /// Parameters which will not be synchronized. - /// - [SerializeField, HideInInspector] - internal List IgnoredParameters = new List(); - #endregion - - #region Serialized. - /// - /// The animator component to synchronize. - /// - [Tooltip("The animator component to synchronize.")] - [SerializeField] - private Animator _animator; - /// - /// The animator component to synchronize. - /// - public Animator Animator { get { return _animator; } } - /// - /// True to smooth float value changes for spectators. - /// - [Tooltip("True to smooth float value changes for spectators.")] - [SerializeField] - private bool _smoothFloats = true; - /// - /// How many ticks to interpolate. - /// - [Tooltip("How many ticks to interpolate.")] - [Range(1, NetworkTransform.MAX_INTERPOLATION)] - [SerializeField] - private ushort _interpolation = 2; - ///// - ///// How often to synchronize this animator. - ///// - //[Tooltip("How often to synchronize this animator.")] - //[Range(0.01f, 0.5f)] - //[SerializeField] - //private float _synchronizeInterval = 0.1f; - /// - /// - /// - [Tooltip("True if using client authoritative animations.")] - [SerializeField] - private bool _clientAuthoritative = true; - /// - /// True if using client authoritative animations. - /// - public bool ClientAuthoritative { get { return _clientAuthoritative; } } - /// - /// True to synchronize server results back to owner. Typically used when you are changing animations on the server and are relying on the server response to update the clients animations. - /// - [Tooltip("True to synchronize server results back to owner. Typically used when you are changing animations on the server and are relying on the server response to update the clients animations.")] - [SerializeField] - private bool _sendToOwner; - #endregion - - #region Private. - /// - /// All parameter values, excluding triggers. - /// - private List _parameterDetails = new List(); - /// - /// Last int values. - /// - private List _ints = new List(); - /// - /// Last float values. - /// - private List _floats = new List(); - /// - /// Last bool values. - /// - private List _bools = new List(); - /// - /// Last layer weights. - /// - private float[] _layerWeights; - /// - /// Last speed. - /// - private float _speed; - ///// - ///// Next time client may send parameter updates. - ///// - //private float _nextClientSendTime = -1f; - ///// - ///// Next time server may send parameter updates. - ///// - //private float _nextServerSendTime = -1f; - /// - /// Trigger values set by using SetTrigger and ResetTrigger. - /// - private List _triggerUpdates = new List(); - /// - /// Updates going to clients. - /// - private List _toClientsBuffer = new List(); - /// - /// Returns if the animator is exist and is active. - /// - private bool _isAnimatorEnabled - { - get - { - bool failedChecks = (_animator == null || !_animator.enabled || _animator.runtimeAnimatorController == null); - return !failedChecks; - } - } - /// - /// Float valeus to smooth towards. - /// - private Dictionary _smoothedFloats = new Dictionary(); - /// - /// Returns if floats can be smoothed for this client. - /// - private bool _canSmoothFloats - { - get - { - //Don't smooth on server only. - if (!base.IsClient) - return false; - //Smoothing is disabled. - if (!_smoothFloats) - return false; - //No reason to smooth for self. - if (base.IsOwner && ClientAuthoritative) - return false; - - //Fall through. - return true; - } - } - /// - /// Layers which need to have their state synchronized. Key is the layer, Value is the state change information. - /// - private Dictionary _unsynchronizedLayerStates = new Dictionary(); - /// - /// Layers which need to have their state blend synchronized. Key is ParameterIndex, Value is next state hash. - /// - //private Dictionary _unsynchronizedLayerStates = new HashSet(); - /// - /// Last animator set. - /// - private Animator _lastAnimator; - /// - /// Last Controller set. - /// - private RuntimeAnimatorController _lastController; - /// - /// PooledWriter for this animator. - /// - private PooledWriter _writer = new PooledWriter(); - /// - /// Holds client authoritative updates received to send to other clients. - /// - private ClientAuthoritativeUpdate _clientAuthoritativeUpdates; - /// - /// True to forceAll next timed send. - /// - private bool _forceAllOnTimed; - /// - /// Animations received which should be applied. - /// - private Queue _fromServerBuffer = new Queue(); - /// - /// Tick when the buffer may begin to run. - /// - private uint _startTick = uint.MaxValue; - #endregion - - #region Const. - ///// - ///// How much time to fall behind when using smoothing. Only increase value if the smoothing is sometimes jittery. Recommended values are between 0 and 0.04. - ///// - //private const float INTERPOLATION = 0.02f; - /// - /// ParameterDetails index which indicates a layer weight change. - /// - private const byte LAYER_WEIGHT = 240; - /// - /// ParameterDetails index which indicates an animator speed change. - /// - private const byte SPEED = 241; - /// - /// ParameterDetails index which indicates a layer state change. - /// - private const byte STATE = 242; - /// - /// ParameterDetails index which indicates a crossfade change. - /// - private const byte CROSSFADE = 243; - #endregion - - private void Awake() - { - InitializeOnce(); - } - - [APIExclude] - public override void OnSpawnServer(NetworkConnection connection) - { - base.OnSpawnServer(connection); - if (!_isAnimatorEnabled) - return; - if (AnimatorUpdated(out ArraySegment updatedBytes, true)) - TargetAnimatorUpdated(connection, updatedBytes); - } - - public override void OnStartNetwork() - { - base.OnStartNetwork(); - base.TimeManager.OnPreTick += TimeManager_OnPreTick; - base.TimeManager.OnPostTick += TimeManager_OnPostTick; - } - - [APIExclude] - public override void OnStartServer() - { - base.OnStartServer(); - //If using client authoritative then initialize clientAuthoritativeUpdates. - if (_clientAuthoritative) - { - _clientAuthoritativeUpdates = new ClientAuthoritativeUpdate(); - //Expand to clients buffer count to however many buffers can be held. - for (int i = 0; i < ClientAuthoritativeUpdate.MAXIMUM_BUFFER_COUNT; i++) - _toClientsBuffer.Add(new byte[0]); - } - else - { - _toClientsBuffer.Add(new byte[0]); - } - } - - public override void OnStopNetwork() - { - base.OnStopNetwork(); - base.TimeManager.OnPreTick -= TimeManager_OnPreTick; - base.TimeManager.OnPostTick -= TimeManager_OnPostTick; - } - - - /// - /// Called right before a tick occurs, as well before data is read. - /// - private void TimeManager_OnPreTick() - { - if (!_isAnimatorEnabled) - { - _fromServerBuffer.Clear(); - return; - } - //Disabled/cannot start. - if (_startTick == uint.MaxValue) - return; - //Nothing in queue. - if (_fromServerBuffer.Count == 0) - { - _startTick = uint.MaxValue; - return; - } - //Not enough time has passed to start queue. - if (base.TimeManager.LocalTick < _startTick) - return; - - ReceivedServerData rd = _fromServerBuffer.Dequeue(); - ArraySegment segment = rd.GetArraySegment(); - ApplyParametersUpdated(ref segment); - rd.Dispose(); - } - - - /* Use post tick values are checked after - * client has an opportunity to use OnTick. */ - /// - /// Called after a tick occurs; physics would have simulated if using PhysicsMode.TimeManager. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void TimeManager_OnPostTick() - { - //One check rather than per each method. - if (!_isAnimatorEnabled) - return; - - if (base.IsClient) - CheckSendToServer(); - if (base.IsServer) - CheckSendToClients(); - } - - private void Update() - { - if (!_isAnimatorEnabled) - return; - - if (base.IsClient) - SmoothFloats(); - } - - /// - /// Initializes this script for use. - /// - private void InitializeOnce() - { - if (_animator == null) - _animator = GetComponent(); - - //Don't run the rest if not in play mode. - if (!ApplicationState.IsPlaying()) - return; - - if (!_isAnimatorEnabled) - { - //Debug.LogWarning("Animator is null or not enabled; unable to initialize for animator. Use SetAnimator if animator was changed or enable the animator."); - return; - } - - //Speed. - _speed = _animator.speed; - - //Build layer weights. - _layerWeights = new float[_animator.layerCount]; - for (int i = 0; i < _layerWeights.Length; i++) - _layerWeights[i] = _animator.GetLayerWeight(i); - - _parameterDetails.Clear(); - _bools.Clear(); - _floats.Clear(); - _ints.Clear(); - //Create a parameter detail for each parameter that can be synchronized. - foreach (AnimatorControllerParameter item in _animator.parameters) - { - bool process = !_animator.IsParameterControlledByCurve(item.name); - - if (process) - { - //Over 250 parameters; who would do this!? - if (_parameterDetails.Count == 240) - { - Debug.LogError($"Parameter {item.name} exceeds the allowed 240 parameter count and is being ignored."); - continue; - } - - int typeIndex = 0; - //Bools. - if (item.type == AnimatorControllerParameterType.Bool) - { - typeIndex = _bools.Count; - _bools.Add(_animator.GetBool(item.nameHash)); - } - //Floats. - else if (item.type == AnimatorControllerParameterType.Float) - { - typeIndex = _floats.Count; - _floats.Add(_animator.GetFloat(item.name)); - } - //Ints. - else if (item.type == AnimatorControllerParameterType.Int) - { - typeIndex = _ints.Count; - _ints.Add(_animator.GetInteger(item.nameHash)); - } - //Triggers. - else if (item.type == AnimatorControllerParameterType.Trigger) - { - /* Triggers aren't persistent so they don't use stored values - * but I do need to make a parameter detail to track the hash. */ - typeIndex = -1; - } - - _parameterDetails.Add(new ParameterDetail(item, (byte)typeIndex)); - } - } - } - - /// - /// Sets which animator to use. You must call this with the appropriate animator on all clients and server. This change is not automatically synchronized. - /// - /// - public void SetAnimator(Animator animator) - { - //No update required. - if (animator == _lastAnimator) - return; - - _animator = animator; - InitializeOnce(); - _lastAnimator = animator; - } - - /// - /// Sets which controller to use. You must call this with the appropriate controller on all clients and server. This change is not automatically synchronized. - /// - /// - public void SetController(RuntimeAnimatorController controller) - { - //No update required. - if (controller == _lastController) - return; - - _animator.runtimeAnimatorController = controller; - InitializeOnce(); - _lastController = controller; - } - - /// - /// Checks to send animator data from server to clients. - /// - private void CheckSendToServer() - { - //Cannot send to server if is server or not client. - if (base.IsServer || !base.IsClient) - return; - //Cannot send to server if not client authoritative or don't have authority. - if (!ClientAuthoritative || !base.IsOwner) - return; - ////Not enough time passed to send. - //if (Time.time < _nextClientSendTime) - // return; - //_nextClientSendTime = Time.time + _synchronizeInterval; - - /* If there are updated parameters to send. - * Don't really need to worry about mtu here - * because there's no way the sent bytes are - * ever going to come close to the mtu - * when sending a single update. */ - if (AnimatorUpdated(out ArraySegment updatedBytes, _forceAllOnTimed)) - ServerAnimatorUpdated(updatedBytes); - - _forceAllOnTimed = false; - } - - /// - /// Checks to send animator data from server to clients. - /// - private void CheckSendToClients() - { - //Cannot send to clients if not server. - if (!base.IsServer) - return; - ////Not enough time passed to send. - //if (Time.time < _nextServerSendTime) - // return; - //_nextServerSendTime = Time.time + _synchronizeInterval; - - bool sendFromServer; - //If client authoritative. - if (ClientAuthoritative) - { - //If has no owner then use latest values on server. - if (!base.Owner.IsValid) - { - sendFromServer = true; - } - //If has a owner. - else - { - //If is owner then send latest values on server. - if (base.IsOwner) - { - sendFromServer = true; - } - //Not owner. - else - { - //Haven't received any data from clients, cannot send yet. - if (_clientAuthoritativeUpdates.BufferCount == 0) - { - return; - } - //Data was received from client; check eligibility to send it. - else - { - /* If forceAll is true then the latest values on - * server must be used, rather than what was received - * from client. This can occur if the client is possibly - * trying to use an attack or if the client is - * excessively sending updates. To prevent relaying that - * same data to others the server will send it's current - * animator settings in this scenario. */ - if (_clientAuthoritativeUpdates.ForceAll) - { - sendFromServer = true; - _clientAuthoritativeUpdates.Reset(); - } - else - { - sendFromServer = false; - } - } - } - } - } - //Not client authoritative, always send from server. - else - { - sendFromServer = true; - } - - /* If client authoritative then use what was received from clients - * if data exist. */ - if (!sendFromServer) - { - byte[] buffer = null; - int bufferLength = 0; - for (int i = 0; i < _clientAuthoritativeUpdates.BufferCount; i++) - { - _clientAuthoritativeUpdates.GetBuffer(i, ref buffer, ref bufferLength); - - //If null was returned then something went wrong. - if (buffer == null || bufferLength == 0) - continue; - - ObserversAnimatorUpdated(new ArraySegment(buffer, 0, bufferLength)); - } - //Reset client auth buffer. - _clientAuthoritativeUpdates.Reset(); - } - //Sending from server, send what's changed. - else - { - if (AnimatorUpdated(out ArraySegment updatedBytes, _forceAllOnTimed)) - ObserversAnimatorUpdated(updatedBytes); - - _forceAllOnTimed = false; - } - } - - - /// - /// Smooths floats on clients. - /// - private void SmoothFloats() - { - //Don't need to smooth on authoritative client. - if (!_canSmoothFloats) - return; - //Nothing to smooth. - if (_smoothedFloats.Count == 0) - return; - - float deltaTime = Time.deltaTime; - - List finishedEntries = new List(); - - /* Cycle through each target float and move towards it. - * Once at a target float mark it to be removed from floatTargets. */ - foreach (KeyValuePair item in _smoothedFloats) - { - float current = _animator.GetFloat(item.Key); - float next = Mathf.MoveTowards(current, item.Value.Target, item.Value.Rate * deltaTime); - _animator.SetFloat(item.Key, next); - - if (next == item.Value.Target) - finishedEntries.Add(item.Key); - } - - //Remove finished entries from dictionary. - for (int i = 0; i < finishedEntries.Count; i++) - _smoothedFloats.Remove(finishedEntries[i]); - } - - /// - /// Returns if animator is updated and bytes of updated values. - /// - /// - private bool AnimatorUpdated(out ArraySegment updatedBytes, bool forceAll = false) - { - updatedBytes = default; - //Something isn't setup right. - if (_layerWeights == null) - return false; - //Reset the writer. - _writer.Reset(); - - /* Every time a parameter is updated a byte is added - * for it's index, this is why requiredBytes increases - * by 1 when a value updates. ChangedParameter contains - * the index updated and the new value. The requiresBytes - * is increased also by however many bytes are required - * for the type which has changed. Some types use special parameter - * detail indexes, such as layer weights; these can be found under const. */ - for (byte parameterIndex = 0; parameterIndex < _parameterDetails.Count; parameterIndex++) - { - ParameterDetail pd = _parameterDetails[parameterIndex]; - /* Bool. */ - if (pd.ControllerParameter.type == AnimatorControllerParameterType.Bool) - { - bool next = _animator.GetBool(pd.Hash); - //If changed. - if (forceAll || _bools[pd.TypeIndex] != next) - { - _writer.WriteByte(parameterIndex); - _writer.WriteBoolean(next); - _bools[pd.TypeIndex] = next; - } - } - /* Float. */ - else if (pd.ControllerParameter.type == AnimatorControllerParameterType.Float) - { - float next = _animator.GetFloat(pd.Hash); - //If changed. - if (forceAll || _floats[pd.TypeIndex] != next) - { - _writer.WriteByte(parameterIndex); - _writer.WriteSingle(next, AutoPackType.Packed); - _floats[pd.TypeIndex] = next; - } - } - /* Int. */ - else if (pd.ControllerParameter.type == AnimatorControllerParameterType.Int) - { - int next = _animator.GetInteger(pd.Hash); - //If changed. - if (forceAll || _ints[pd.TypeIndex] != next) - { - _writer.WriteByte(parameterIndex); - _writer.WriteInt32(next, AutoPackType.Packed); - _ints[pd.TypeIndex] = next; - } - } - } - - /* Don't need to force trigger sends since - * they're one-shots. */ - for (int i = 0; i < _triggerUpdates.Count; i++) - { - _writer.WriteByte(_triggerUpdates[i].ParameterIndex); - _writer.WriteBoolean(_triggerUpdates[i].Setting); - } - _triggerUpdates.Clear(); - - /* States. */ - if (forceAll) - { - //Add all layers to layer states. - for (int i = 0; i < _animator.layerCount; i++) - _unsynchronizedLayerStates[i] = new StateChange(); - } - - //Go through each layer which needs to be synchronized. - foreach (KeyValuePair item in _unsynchronizedLayerStates) - { - int layerIndex = item.Key; - StateChange sc = item.Value; - //If a regular state change. - if (!sc.IsCrossfade) - { - if (ReturnCurrentLayerState(out int stateHash, out float normalizedTime, layerIndex)) - { - _writer.WriteByte(STATE); - _writer.WriteByte((byte)layerIndex); - //Current hash will always be too large to compress. - _writer.WriteInt32(stateHash); - _writer.WriteSingle(normalizedTime, AutoPackType.Packed); - } - } - //When it's a crossfade then send crossfade data. - else - { - _writer.WriteByte(CROSSFADE); - _writer.WriteByte((byte)layerIndex); - //Current hash will always be too large to compress. - _writer.WriteInt32(sc.Hash); - _writer.WriteBoolean(sc.FixedTime); - //Times usually can be compressed. - _writer.WriteSingle(sc.DurationTime, AutoPackType.Packed); - _writer.WriteSingle(sc.OffsetTime, AutoPackType.Packed); - _writer.WriteSingle(sc.NormalizedTransitionTime, AutoPackType.Packed); - } - } - _unsynchronizedLayerStates.Clear(); - - /* Layer weights. */ - for (int layerIndex = 0; layerIndex < _layerWeights.Length; layerIndex++) - { - float next = _animator.GetLayerWeight(layerIndex); - if (forceAll || _layerWeights[layerIndex] != next) - { - _writer.WriteByte(LAYER_WEIGHT); - _writer.WriteByte((byte)layerIndex); - _writer.WriteSingle(next, AutoPackType.Packed); - _layerWeights[layerIndex] = next; - } - } - - /* Speed is similar to layer weights but we don't need the index, - * only the indicator and value. */ - float speedNext = _animator.speed; - if (forceAll || _speed != speedNext) - { - _writer.WriteByte(SPEED); - _writer.WriteSingle(speedNext, AutoPackType.Packed); - _speed = speedNext; - } - - //Nothing to update. - if (_writer.Position == 0) - { - return false; - } - else - { - updatedBytes = _writer.GetArraySegment(); - return true; - } - } - - /// - /// Applies changed parameters to the animator. - /// - /// - private void ApplyParametersUpdated(ref ArraySegment updatedParameters) - { - if (!_isAnimatorEnabled) - return; - if (_layerWeights == null) - return; - if (updatedParameters.Count == 0) - return; - //Exit if client authoritative and has authority. - if (ClientAuthoritative && base.IsOwner) - return; - //Exit if not client authoritative, but also not sync to owner, and is owner. - if (!ClientAuthoritative && !_sendToOwner && base.IsOwner) - return; - //Exit if trying to apply when server and not client authoritative. - if (base.IsServer && !ClientAuthoritative) - return; - - try - { - using (PooledReader reader = ReaderPool.GetReader(updatedParameters, base.NetworkManager)) - { - while (reader.Remaining > 0) - { - byte parameterIndex = reader.ReadByte(); - //Layer weight - if (parameterIndex == LAYER_WEIGHT) - { - byte layerIndex = reader.ReadByte(); - float value = reader.ReadSingle(AutoPackType.Packed); - _animator.SetLayerWeight((int)layerIndex, value); - } - //Speed. - else if (parameterIndex == SPEED) - { - float value = reader.ReadSingle(AutoPackType.Packed); - _animator.speed = value; - } - //State. - else if (parameterIndex == STATE) - { - byte layerIndex = reader.ReadByte(); - //Hashes will always be too large to compress. - int hash = reader.ReadInt32(); - float normalizedTime = reader.ReadSingle(AutoPackType.Packed); - //Play results. - _animator.Play(hash, layerIndex, normalizedTime); - } - //Crossfade. - else if (parameterIndex == CROSSFADE) - { - byte layerIndex = reader.ReadByte(); - //Hashes will always be too large to compress. - int hash = reader.ReadInt32(); - bool useFixedTime = reader.ReadBoolean(); - //Get time values. - float durationTime = reader.ReadSingle(AutoPackType.Packed); - float offsetTime = reader.ReadSingle(AutoPackType.Packed); - float normalizedTransitionTime = reader.ReadSingle(AutoPackType.Packed); - //If using fixed. - if (useFixedTime) - _animator.CrossFadeInFixedTime(hash, durationTime, layerIndex, offsetTime, normalizedTransitionTime); - else - _animator.CrossFade(hash, durationTime, layerIndex, offsetTime, normalizedTransitionTime); - } - //Not a predetermined index, is an actual parameter. - else - { - AnimatorControllerParameterType acpt = _parameterDetails[parameterIndex].ControllerParameter.type; - if (acpt == AnimatorControllerParameterType.Bool) - { - bool value = reader.ReadBoolean(); - _animator.SetBool(_parameterDetails[parameterIndex].Hash, value); - } - //Float. - else if (acpt == AnimatorControllerParameterType.Float) - { - float value = reader.ReadSingle(AutoPackType.Packed); - //If able to smooth floats. - if (_canSmoothFloats) - { - float currentValue = _animator.GetFloat(_parameterDetails[parameterIndex].Hash); - float past = (float)base.TimeManager.TickDelta; - //float past = _synchronizeInterval + INTERPOLATION; - float rate = Mathf.Abs(currentValue - value) / past; - _smoothedFloats[_parameterDetails[parameterIndex].Hash] = new SmoothedFloat(rate, value); - } - else - { - _animator.SetFloat(_parameterDetails[parameterIndex].Hash, value); - } - } - //Integer. - else if (acpt == AnimatorControllerParameterType.Int) - { - int value = reader.ReadInt32(); - _animator.SetInteger(_parameterDetails[parameterIndex].Hash, value); - } - //Trigger. - else if (acpt == AnimatorControllerParameterType.Trigger) - { - bool value = reader.ReadBoolean(); - if (value) - _animator.SetTrigger(_parameterDetails[parameterIndex].Hash); - else - _animator.ResetTrigger(_parameterDetails[parameterIndex].Hash); - } - //Unhandled. - else - { - Debug.LogWarning($"Unhandled parameter type of {acpt}."); - } - } - } - } - } - catch - { - Debug.LogWarning("An error occurred while applying updates. This may occur when malformed data is sent or when you change the animator or controller but not on all connections."); - } - } - - /// - /// Outputs the current state and time for a layer. Returns true if stateHash is not 0. - /// - /// - /// - /// - /// - /// - private bool ReturnCurrentLayerState(out int stateHash, out float normalizedTime, int layerIndex) - { - stateHash = 0; - normalizedTime = 0f; - - if (!_isAnimatorEnabled) - return false; - - AnimatorStateInfo st = _animator.GetCurrentAnimatorStateInfo(layerIndex); - stateHash = st.fullPathHash; - normalizedTime = st.normalizedTime; - - return (stateHash != 0); - } - - /// - /// Forces values to send next update regardless of time remaining. - /// Can be useful if you have a short lasting parameter that you want to ensure goes through. - /// - public void ForceSend() - { - //_nextClientSendTime = 0f; - //_nextServerSendTime = 0f; - } - - /// - /// Immediately sends all variables and states of layers. - /// This is a very bandwidth intensive operation. - /// - public void SendAll() - { - _forceAllOnTimed = true; - ForceSend(); - } - - #region Play. - /// - /// Plays a state. - /// - public void Play(string name) - { - Play(Animator.StringToHash(name)); - } - /// - /// Plays a state. - /// - public void Play(int hash) - { - for (int i = 0; i < _animator.layerCount; i++) - Play(hash, i, 0f); - } - /// - /// Plays a state. - /// - public void Play(string name, int layer) - { - Play(Animator.StringToHash(name), layer); - } - /// - /// Plays a state. - /// - public void Play(int hash, int layer) - { - Play(hash, layer, 0f); - } - /// - /// Plays a state. - /// - public void Play(string name, int layer, float normalizedTime) - { - Play(Animator.StringToHash(name), layer, normalizedTime); - } - /// - /// Plays a state. - /// - public void Play(int hash, int layer, float normalizedTime) - { - if (!_isAnimatorEnabled) - return; - if (_animator.HasState(layer, hash)) - { - _animator.Play(hash, layer, normalizedTime); - _unsynchronizedLayerStates[layer] = new StateChange(); - } - } - /// - /// Plays a state. - /// - public void PlayInFixedTime(string name, float fixedTime) - { - PlayInFixedTime(Animator.StringToHash(name), fixedTime); - } - /// - /// Plays a state. - /// - public void PlayInFixedTime(int hash, float fixedTime) - { - for (int i = 0; i < _animator.layerCount; i++) - PlayInFixedTime(hash, i, fixedTime); - } - /// - /// Plays a state. - /// - public void PlayInFixedTime(string name, int layer, float fixedTime) - { - PlayInFixedTime(Animator.StringToHash(name), layer, fixedTime); - } - /// - /// Plays a state. - /// - public void PlayInFixedTime(int hash, int layer, float fixedTime) - { - if (!_isAnimatorEnabled) - return; - if (_animator.HasState(layer, hash)) - { - _animator.PlayInFixedTime(hash, layer, fixedTime); - _unsynchronizedLayerStates[layer] = new StateChange(); - } - } - #endregion - - #region Crossfade. - /// - /// Creates a crossfade from the current state to any other state using normalized times. - /// - /// - /// - /// - /// - /// - public void CrossFade(string stateName, float normalizedTransitionDuration, int layer, float normalizedTimeOffset = float.NegativeInfinity, float normalizedTransitionTime = 0.0f) - { - CrossFade(Animator.StringToHash(stateName), normalizedTransitionDuration, layer, normalizedTimeOffset, normalizedTransitionTime); - } - /// - /// Creates a crossfade from the current state to any other state using normalized times. - /// - /// - /// - /// - /// - /// - public void CrossFade(int hash, float normalizedTransitionDuration, int layer, float normalizedTimeOffset = 0.0f, float normalizedTransitionTime = 0.0f) - { - if (!_isAnimatorEnabled) - return; - if (_animator.HasState(layer, hash)) - { - _animator.CrossFade(hash, normalizedTransitionDuration, layer, normalizedTimeOffset, normalizedTransitionTime); - _unsynchronizedLayerStates[layer] = new StateChange(hash, false, normalizedTransitionDuration, normalizedTimeOffset, normalizedTransitionTime); - } - } - /// - /// Creates a crossfade from the current state to any other state using times in seconds. - /// - /// - /// - /// - /// - /// - public void CrossFadeInFixedTime(string stateName, float fixedTransitionDuration, int layer, float fixedTimeOffset = 0.0f, float normalizedTransitionTime = 0.0f) - { - CrossFadeInFixedTime(Animator.StringToHash(stateName), fixedTransitionDuration, layer, fixedTimeOffset, normalizedTransitionTime); - } - /// - /// Creates a crossfade from the current state to any other state using times in seconds. - /// - /// - /// - /// - /// - /// - public void CrossFadeInFixedTime(int hash, float fixedTransitionDuration, int layer, float fixedTimeOffset = 0.0f, float normalizedTransitionTime = 0.0f) - { - if (!_isAnimatorEnabled) - return; - if (_animator.HasState(layer, hash)) - { - _animator.CrossFadeInFixedTime(hash, fixedTransitionDuration, layer, fixedTimeOffset, normalizedTransitionTime); - _unsynchronizedLayerStates[layer] = new StateChange(hash, true, fixedTransitionDuration, fixedTimeOffset, normalizedTransitionTime); - } - } - #endregion - - #region Triggers. - /// - /// Sets a trigger on the animator and sends it over the network. - /// - /// - public void SetTrigger(int hash) - { - if (!_isAnimatorEnabled) - return; - UpdateTrigger(hash, true); - } - /// - /// Sets a trigger on the animator and sends it over the network. - /// - /// - public void SetTrigger(string name) - { - SetTrigger(Animator.StringToHash(name)); - } - - /// - /// Resets a trigger on the animator and sends it over the network. - /// - /// - public void ResetTrigger(int hash) - { - UpdateTrigger(hash, false); - } - /// - /// Resets a trigger on the animator and sends it over the network. - /// - /// - public void ResetTrigger(string name) - { - ResetTrigger(Animator.StringToHash(name)); - } - - /// - /// Updates a trigger, sets or resets. - /// - /// - private void UpdateTrigger(int hash, bool set) - { - if (!_isAnimatorEnabled) - return; - /* Allow triggers to run on owning client if using client authority, - * as well when not using client authority but also not using synchronize to owner. - * This allows clients to run animations locally while maintaining server authority. */ - //Using client authority but not owner. - if (ClientAuthoritative && !base.IsOwner) - return; - - //Also block if not using client authority, synchronizing to owner, and not server. - if (!ClientAuthoritative && _sendToOwner && !base.IsServer) - return; - - //Update locally. - if (set) - _animator.SetTrigger(hash); - else - _animator.ResetTrigger(hash); - - /* Can send if not client auth but is server, - * or if client auth and owner. */ - bool canSend = (!ClientAuthoritative && base.IsServer) || - (ClientAuthoritative && base.IsOwner); - //Only queue a send if proper side. - if (canSend) - { - for (byte i = 0; i < _parameterDetails.Count; i++) - { - if (_parameterDetails[i].Hash == hash) - { - _triggerUpdates.Add(new TriggerUpdate(i, set)); - return; - } - } - //Fall through, hash not found. - Debug.LogWarning($"Hash {hash} not found while trying to update a trigger."); - } - } - #endregion - - #region Remote actions. - /// - /// Called on clients to receive an animator update. - /// - /// - [ObserversRpc] - private void ObserversAnimatorUpdated(ArraySegment data) - { - ServerDataReceived(ref data); - } - /// - /// Called on clients to receive an animator update. - /// - /// - [TargetRpc] - private void TargetAnimatorUpdated(NetworkConnection connection, ArraySegment data) - { - ServerDataReceived(ref data); - } - /// - /// Called on server to receive an animator update. - /// - /// - [ServerRpc] - private void ServerAnimatorUpdated(ArraySegment data) - { - if (!_isAnimatorEnabled) - return; - if (!ClientAuthoritative) - { - base.Owner.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"Connection Id {base.Owner.ClientId} has been kicked for trying to update this object without client authority."); - return; - } - - /* Server does not need to apply interpolation. - * Even as clientHost when CSP is being used the - * clientHost will always be on the latest tick. - * Spectators on the other hand will remain behind - * a little depending on their components interpolation. */ - ApplyParametersUpdated(ref data); - _clientAuthoritativeUpdates.AddToBuffer(ref data); - } - /// - /// Called on clients to receive an animator update. - /// - /// - private void ServerDataReceived(ref ArraySegment data) - { - if (!_isAnimatorEnabled) - return; - //If also server, client host, then do nothing. Animations already ran on server. - if (base.IsServer) - return; - - //If has authority. - if (base.IsOwner) - { - //No need to sync to self if client authoritative. - if (ClientAuthoritative) - return; - //Not client authoritative, but also don't sync to owner. - else if (!ClientAuthoritative && !_sendToOwner) - return; - } - - ReceivedServerData rd = new ReceivedServerData(data); - _fromServerBuffer.Enqueue(rd); - - if (_startTick == uint.MaxValue) - _startTick = (base.TimeManager.LocalTick + _interpolation); - //ApplyParametersUpdated(ref data); - } - #endregion - - #region Editor. -#if UNITY_EDITOR - protected override void Reset() - { - base.Reset(); - if (_animator == null) - SetAnimator(GetComponent()); - } -#endif - #endregion - - } -} - diff --git a/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/NetworkAnimator.cs.meta b/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/NetworkAnimator.cs.meta deleted file mode 100644 index 0d7e115..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/NetworkAnimator/NetworkAnimator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e8cac635f24954048aad3a6ff9110beb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform.meta b/Assets/FishNet/Runtime/Generated/Component/NetworkTransform.meta deleted file mode 100644 index c0513ca..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 63eb855bc9013d54d9ea73088d204790 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/Editor.meta b/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/Editor.meta deleted file mode 100644 index de2183e..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 6c1769e2b4cabd744a4b875f6849ef76 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/Editor/NetworkTransformEditor.cs b/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/Editor/NetworkTransformEditor.cs deleted file mode 100644 index 13227ae..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/Editor/NetworkTransformEditor.cs +++ /dev/null @@ -1,134 +0,0 @@ -#if UNITY_EDITOR -using FishNet.Editing; -using UnityEditor; -using UnityEngine; - -namespace FishNet.Component.Transforming.Editing -{ - - - [CustomEditor(typeof(NetworkTransform), true)] - [CanEditMultipleObjects] - public class NetworkTransformEditor : Editor - { - private SerializedProperty _componentConfiguration; - private SerializedProperty _synchronizeParent; - private SerializedProperty _packing; - private SerializedProperty _interpolation; - private SerializedProperty _extrapolation; - private SerializedProperty _enableTeleport; - private SerializedProperty _teleportThreshold; - private SerializedProperty _clientAuthoritative; - private SerializedProperty _sendToOwner; - private SerializedProperty _synchronizePosition; - private SerializedProperty _positionSnapping; - private SerializedProperty _synchronizeRotation; - private SerializedProperty _rotationSnapping; - private SerializedProperty _synchronizeScale; - private SerializedProperty _scaleSnapping; - - - protected virtual void OnEnable() - { - _componentConfiguration = serializedObject.FindProperty(nameof(_componentConfiguration)); - _synchronizeParent = serializedObject.FindProperty("_synchronizeParent"); - _packing = serializedObject.FindProperty("_packing"); - _interpolation = serializedObject.FindProperty("_interpolation"); - _extrapolation = serializedObject.FindProperty("_extrapolation"); - _enableTeleport = serializedObject.FindProperty("_enableTeleport"); - _teleportThreshold = serializedObject.FindProperty("_teleportThreshold"); - _clientAuthoritative = serializedObject.FindProperty("_clientAuthoritative"); - _sendToOwner = serializedObject.FindProperty("_sendToOwner"); - _synchronizePosition = serializedObject.FindProperty("_synchronizePosition"); - _positionSnapping = serializedObject.FindProperty("_positionSnapping"); - _synchronizeRotation = serializedObject.FindProperty("_synchronizeRotation"); - _rotationSnapping = serializedObject.FindProperty("_rotationSnapping"); - _synchronizeScale = serializedObject.FindProperty("_synchronizeScale"); - _scaleSnapping = serializedObject.FindProperty("_scaleSnapping"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - GUI.enabled = false; - EditorGUILayout.ObjectField("Script:", MonoScript.FromMonoBehaviour((NetworkTransform)target), typeof(NetworkTransform), false); - GUI.enabled = true; - - -#pragma warning disable CS0162 // Unreachable code detected - EditorGUILayout.HelpBox(EditingConstants.PRO_ASSETS_LOCKED_TEXT, MessageType.Warning); -#pragma warning restore CS0162 // Unreachable code detected - - //Misc. - EditorGUILayout.LabelField("Misc", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_componentConfiguration); - EditorGUILayout.PropertyField(_synchronizeParent, new GUIContent("* Synchronize Parent")); - EditorGUILayout.PropertyField(_packing); - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - - //Smoothing. - EditorGUILayout.LabelField("Smoothing", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_interpolation); - EditorGUILayout.PropertyField(_extrapolation, new GUIContent("* Extrapolation")); - EditorGUILayout.PropertyField(_enableTeleport); - if (_enableTeleport.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_teleportThreshold); - EditorGUI.indentLevel--; - } - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - - //Authority. - EditorGUILayout.LabelField("Authority", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_clientAuthoritative); - if (!_clientAuthoritative.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_sendToOwner); - EditorGUI.indentLevel--; - } - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - - //Synchronizing. - EditorGUILayout.LabelField("Synchronizing.", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - //Position. - EditorGUILayout.PropertyField(_synchronizePosition); - if (_synchronizePosition.boolValue) - { - EditorGUI.indentLevel += 2; - EditorGUILayout.PropertyField(_positionSnapping); - EditorGUI.indentLevel -= 2; - } - //Rotation. - EditorGUILayout.PropertyField(_synchronizeRotation); - if (_synchronizeRotation.boolValue) - { - EditorGUI.indentLevel += 2; - EditorGUILayout.PropertyField(_rotationSnapping); - EditorGUI.indentLevel -= 2; - } - //Scale. - EditorGUILayout.PropertyField(_synchronizeScale); - if (_synchronizeScale.boolValue) - { - EditorGUI.indentLevel += 2; - EditorGUILayout.PropertyField(_scaleSnapping); - EditorGUI.indentLevel -= 2; - } - EditorGUI.indentLevel--; - - serializedObject.ApplyModifiedProperties(); - } - } - -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/Editor/NetworkTransformEditor.cs.meta b/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/Editor/NetworkTransformEditor.cs.meta deleted file mode 100644 index 7c5a2ca..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/Editor/NetworkTransformEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3ed56c899b8ecf241a2bc3e40a2dabc1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/NetworkTransform.cs b/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/NetworkTransform.cs deleted file mode 100644 index aa37436..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/NetworkTransform.cs +++ /dev/null @@ -1,2042 +0,0 @@ -#if UNITY_EDITOR || DEVELOPMENT_BUILD -#define DEVELOPMENT -#endif -using FishNet.Connection; -using FishNet.Documenting; -using FishNet.Managing.Logging; -using FishNet.Managing.Server; -using FishNet.Object; -using FishNet.Serializing; -using FishNet.Transporting; -using FishNet.Utility.Extension; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Component.Transforming -{ - [DisallowMultipleComponent] - [AddComponentMenu("FishNet/Component/NetworkTransform")] - public sealed class NetworkTransform : NetworkBehaviour - { - #region Types. - [System.Serializable] - public enum ComponentConfigurationType - { - Disabled = 0, - CharacterController = 1, - Rigidbody = 2, - Rigidbody2D = 3, - } - private struct ReceivedData - { - public List HasData; - public PooledWriter Writer; - public Channel Channel; - - /// - /// Sets has data value for all LODs. - /// - public void SetHasData(bool value) - { - for (int i = 0; i < HasData.Count; i++) - HasData[i] = value; - } - /// - /// Sets the data is available for a single LOD. - /// - /// - public void SetHasData(bool value, byte index) - { - if (index >= HasData.Count) - return; - - HasData[index] = value; - } - } - - [System.Serializable] - public struct SnappedAxes - { - public bool X; - public bool Y; - public bool Z; - } - private enum ChangedDelta - { - Unset = 0, - PositionX = 1, - PositionY = 2, - PositionZ = 4, - Rotation = 8, - Extended = 16, - ScaleX = 32, - ScaleY = 64, - ScaleZ = 128, - Nested = 256 - } - private enum ChangedFull - { - Unset = 0, - Position = 1, - Rotation = 2, - Scale = 4, - Nested = 8 - } - - private enum UpdateFlagA : byte - { - Unset = 0, - X2 = 1, - X4 = 2, - Y2 = 4, - Y4 = 8, - Z2 = 16, - Z4 = 32, - Rotation = 64, - Extended = 128 - } - private enum UpdateFlagB : byte - { - Unset = 0, - X2 = 1, - X4 = 2, - Y2 = 4, - Y4 = 8, - Z2 = 16, - Z4 = 32, - Nested = 64 - } - public class GoalData - { - public uint ReceivedTick; - public RateData Rates = new RateData(); - public TransformData Transforms = new TransformData(); - - public GoalData() { } - public void Reset() - { - ReceivedTick = 0; - Transforms.Reset(); - Rates.Reset(); - } - } - public class RateData - { - /// - /// Rate for position after smart calculations. - /// - public float Position; - /// - /// Rate for rotation after smart calculations. - /// - public float Rotation; - /// - /// Rate for scale after smart calculations. - /// - public float Scale; - /// - /// Unaltered rate for position calculated through position change and tickspan. - /// - public float LastUnalteredPositionRate; - /// - /// Number of ticks the rates are calculated for. - /// If TickSpan is 2 then the rates are calculated under the assumption the transform changed over 2 ticks. - /// - public uint TickSpan; - /// - /// True if the rate is believed to be fluctuating unusually. - /// - internal bool AbnormalRateDetected; - /// - /// Time remaining until transform is expected to reach it's goal. - /// - internal float TimeRemaining; - - public RateData() { } - - public void Reset() - { - Position = 0f; - Rotation = 0f; - Scale = 0f; - LastUnalteredPositionRate = 0f; - TickSpan = 0; - AbnormalRateDetected = false; - TimeRemaining = 0f; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Update(RateData rd) - { - Update(rd.Position, rd.Rotation, rd.Scale, rd.LastUnalteredPositionRate, rd.TickSpan, rd.AbnormalRateDetected, rd.TimeRemaining); - } - - /// - /// Updates rates. - /// - public void Update(float position, float rotation, float scale, float unalteredPositionRate, uint tickSpan, bool abnormalRateDetected, float timeRemaining) - { - Position = position; - Rotation = rotation; - Scale = scale; - LastUnalteredPositionRate = unalteredPositionRate; - TickSpan = tickSpan; - AbnormalRateDetected = abnormalRateDetected; - TimeRemaining = timeRemaining; - } - } - - public class TransformData - { - public enum ExtrapolateState : byte - { - Disabled = 0, - Available = 1, - Active = 2 - } - public uint Tick; - public bool Snapped; - public Vector3 Position; - public Quaternion Rotation; - public Vector3 Scale; - public Vector3 ExtrapolatedPosition; - public ExtrapolateState ExtrapolationState; - public NetworkBehaviour ParentBehaviour; - public TransformData() { } - - internal void Reset() - { - Tick = 0; - Snapped = false; - Position = Vector3.zero; - Rotation = Quaternion.identity; - Scale = Vector3.zero; - ExtrapolatedPosition = Vector3.zero; - ExtrapolationState = ExtrapolateState.Disabled; - ParentBehaviour = null; - } - internal void Update(TransformData copy) - { - Update(copy.Tick, copy.Position, copy.Rotation, copy.Scale, copy.ExtrapolatedPosition, copy.ParentBehaviour); - } - internal void Update(uint tick, Vector3 position, Quaternion rotation, Vector3 scale, Vector3 extrapolatedPosition, NetworkBehaviour parentBehaviour) - { - Tick = tick; - Position = position; - Rotation = rotation; - Scale = scale; - ExtrapolatedPosition = extrapolatedPosition; - ParentBehaviour = parentBehaviour; - } - } - - #endregion - - #region Public. - /// - /// - /// - /// - /// - [APIExclude] - public delegate void DataReceivedChanged(TransformData prev, TransformData next); - /// - /// Called when new data is received. Previous and next data are provided. Next data may be manipulated. - /// - public event DataReceivedChanged OnDataReceived; - /// - /// Called when GoalData is updated. - /// - public event Action OnNextGoal; - /// - /// Called when the transform has reached it's goal. - /// - public event Action OnInterpolationComplete; - /// - /// True if the local client used TakeOwnership and is awaiting an ownership change. - /// - public bool TakenOwnership { get; private set; } - #endregion - - #region Serialized. - /// - /// Attached movement component to automatically configure. - /// - [Tooltip("Attached movement component to automatically configure.")] - [SerializeField] - private ComponentConfigurationType _componentConfiguration = ComponentConfigurationType.Disabled; - /// - /// True to synchronize when this transform changes parent. - /// - [Tooltip("True to synchronize when this transform changes parent.")] - [SerializeField] - private bool _synchronizeParent; - /// - /// How much to compress each transform property. - /// - [Tooltip("How much to compress each transform property.")] - [SerializeField] - private TransformPackingData _packing = new TransformPackingData() - { - Position = AutoPackType.Packed, - Rotation = AutoPackType.Packed, - Scale = AutoPackType.Unpacked - }; - /// - /// How many ticks to interpolate. - /// - [Tooltip("How many ticks to interpolate.")] - [Range(1, MAX_INTERPOLATION)] - [SerializeField] - private ushort _interpolation = 2; - /// - /// How many ticks to extrapolate. - /// - [Tooltip("How many ticks to extrapolate.")] - [Range(0, 1024)] - [SerializeField] -#pragma warning disable CS0414 //Not in use. - private ushort _extrapolation = 2; -#pragma warning restore CS0414 //Not in use. - /// - /// True to enable teleport threshhold. - /// - [Tooltip("True to enable teleport threshhold.")] - [SerializeField] - private bool _enableTeleport; - /// - /// How far the transform must travel in a single update to cause a teleport rather than smoothing. Using 0f will teleport every update. - /// - [Tooltip("How far the transform must travel in a single update to cause a teleport rather than smoothing. Using 0f will teleport every update.")] - [Range(0f, float.MaxValue)] - [SerializeField] - private float _teleportThreshold = 1f; - /// - /// True if owner controls how the object is synchronized. - /// - [Tooltip("True if owner controls how the object is synchronized.")] - [SerializeField] - private bool _clientAuthoritative = true; - /// - /// True to synchronize movements on server to owner when not using client authoritative movement. - /// - [Tooltip("True to synchronize movements on server to owner when not using client authoritative movement.")] - [SerializeField] - private bool _sendToOwner = true; - /// - /// Gets SendToOwner. - /// - public bool GetSendToOwner() => _sendToOwner; - /// - /// Sets SendToOwner. Only the server may call this method. - /// - /// New value. - public void SetSendToOwner(bool value) - { - _sendToOwner = value; - if (base.IsServer) - ObserversSetSendToOwner(value); - } - /// - /// How often in ticks to synchronize. This is default to 1 but will change depending on LOD to ensure proper smoothing calculations - /// - private byte _interval = 1; - /// - /// True to synchronize position. Even while checked only changed values are sent. - /// - [Tooltip("True to synchronize position. Even while checked only changed values are sent.")] - [SerializeField] - private bool _synchronizePosition = true; - /// - /// Sets if to synchronize position. - /// - /// New value. - public void SetSynchronizePosition(bool value) => _synchronizePosition = value; - /// - /// Axes to snap on position. - /// - [Tooltip("Axes to snap on position.")] - [SerializeField] - private SnappedAxes _positionSnapping = new SnappedAxes(); - /// - /// Sets which Position axes to snap. - /// - /// Axes to snap. - public void SetPositionSnapping(SnappedAxes axes) => _positionSnapping = axes; - /// - /// True to synchronize rotation. Even while checked only changed values are sent. - /// - [Tooltip("True to synchronize rotation. Even while checked only changed values are sent.")] - [SerializeField] - private bool _synchronizeRotation = true; - /// - /// Sets if to synchronize rotation. - /// - /// New value. - public void SetSynchronizeRotation(bool value) => _synchronizeRotation = value; - /// - /// Axes to snap on rotation. - /// - [Tooltip("Axes to snap on rotation.")] - [SerializeField] - private SnappedAxes _rotationSnapping = new SnappedAxes(); - /// - /// Sets which Scale axes to snap. - /// - /// Axes to snap. - public void SetRotationSnapping(SnappedAxes axes) => _rotationSnapping = axes; - /// - /// True to synchronize scale. Even while checked only changed values are sent. - /// - [Tooltip("True to synchronize scale. Even while checked only changed values are sent.")] - [SerializeField] - private bool _synchronizeScale = true; - /// - /// Sets if to synchronize scale. - /// - /// New value. - public void SetSynchronizeScale(bool value) => _synchronizeScale = value; - /// - /// Axes to snap on scale. - /// - [Tooltip("Axes to snap on scale.")] - [SerializeField] - private SnappedAxes _scaleSnapping = new SnappedAxes(); - /// - /// Sets which Scale axes to snap. - /// - /// Axes to snap. - public void SetScaleSnapping(SnappedAxes axes) => _scaleSnapping = axes; - #endregion - - #region Private. - /// - /// Packing data with all values set to uncompressed. - /// - private TransformPackingData _unpacked = new TransformPackingData() - { - Position = AutoPackType.Unpacked, - Rotation = AutoPackType.Unpacked, - Scale = AutoPackType.Unpacked - }; - /// - /// True if the last DataReceived was on the reliable channel. Default to true so initial values do not extrapolate. - /// - private bool _lastReceiveReliable = true; - /// - /// NetworkBehaviour this transform is a child of. - /// - private NetworkBehaviour _parentBehaviour; - /// - /// Last transform which this object was a child of. - /// - private Transform _parentTransform; - /// - /// Values changed over time that server has sent to clients since last reliable has been sent. - /// - private List _serverChangedSinceReliable = new List(); - /// - /// Values changed over time that client has sent to server since last reliable has been sent. - /// - private ChangedDelta _clientChangedSinceReliable = ChangedDelta.Unset; - /// - /// Last tick an ObserverRpc passed checks. - /// - private uint _lastObserversRpcTick; - /// - /// Last tick a ServerRpc passed checks. - /// - private uint _lastServerRpcTick; - /// - /// Last received data from an authoritative client. - /// - private ReceivedData _receivedClientData = new ReceivedData(); - /// - /// True if subscribed to TimeManager for ticks. - /// - private bool _subscribedToTicks; - /// - /// Last TransformData to be received. - /// - private TransformData _lastReceivedTransformData = new TransformData(); - /// - /// Last RateData to be calculated from LastReceivedTransformData. - /// - private RateData _lastCalculatedRateData = new RateData(); - /// - /// GoalDatas to move towards. - /// - private Queue _goalDataQueue = new Queue(); - /// - /// Current GoalData being used. - /// - private GoalData _currentGoalData = new GoalData(); - /// - /// True if queue can be read. While true objects will move to CurrentGoalData. - /// - private bool _queueReady = false; - /// - /// Cache of GoalDatas to prevent allocations. - /// - private static Stack _goalDataCache = new Stack(); - /// - /// True if the transform has changed since it started. - /// - private bool _changedSinceStart; - /// - /// Last sent transform data for every LOD. - /// - private List _lastSentTransformDatas = new List(); - /// - /// Writers for changed data for each level of detail. - /// - private List _changedWriters = new List(); - #endregion - - #region Const. - /// - /// Maximum possible interpolation value. - /// - public const ushort MAX_INTERPOLATION = 250; - #endregion - - private void Awake() - { - _interval = Math.Max(_interval, (byte)1); - } - - private void OnDestroy() - { - if (_receivedClientData.Writer != null) - { - _receivedClientData.Writer.Dispose(); - _receivedClientData.Writer = null; - } - } - - public override void OnStartServer() - { - base.OnStartServer(); - - ConfigureComponents(); - _receivedClientData.HasData = new List(); - - //Initialize for LODs. - for (int i = 0; i < base.ObserverManager.GetLevelOfDetailDistances().Count; i++) - { - _changedWriters.Add(WriterPool.GetWriter()); - _lastSentTransformDatas.Add(new TransformData()); - _receivedClientData.HasData.Add(false); - _serverChangedSinceReliable.Add(ChangedDelta.Unset); - } - - SetDefaultGoalData(); - /* Server must always subscribe. - * Server needs to relay client auth in - * ticks or send non-auth/non-owner to - * clients in tick. */ - ChangeTickSubscription(true); - } - - public override void OnSpawnServer(NetworkConnection connection) - { - base.OnSpawnServer(connection); - /* If not on the root then the initial properties may need to be synchronized - * since the spawn message only sends root information. If initial - * properties have changed update spawning connection. */ - if (base.NetworkObject.gameObject != gameObject && _changedSinceStart) - { - //Send latest. - using (PooledWriter writer = WriterPool.GetWriter()) - { - ChangedDelta fullTransform = (ChangedDelta.PositionX | ChangedDelta.PositionY | ChangedDelta.PositionZ | ChangedDelta.Extended | ChangedDelta.ScaleX | ChangedDelta.ScaleY | ChangedDelta.ScaleZ | ChangedDelta.Rotation); - SerializeChanged(fullTransform, writer); - TargetUpdateTransform(connection, writer.GetArraySegment(), Channel.Reliable); - } - } - - - } - - public override void OnStartClient() - { - base.OnStartClient(); - ConfigureComponents(); - - //Initialize for LOD if client only. - if (base.IsClientOnly) - { - for (int i = 0; i < base.ObserverManager.GetLevelOfDetailDistances().Count; i++) - { - _changedWriters.Add(WriterPool.GetWriter()); - _lastSentTransformDatas.Add(new TransformData()); - } - } - - SetDefaultGoalData(); - } - - public override void OnOwnershipServer(NetworkConnection prevOwner) - { - base.OnOwnershipServer(prevOwner); - //Reset last tick since each client sends their own ticks. - _lastServerRpcTick = 0; - } - - public override void OnOwnershipClient(NetworkConnection prevOwner) - { - base.OnOwnershipClient(prevOwner); - - /* If newOwner is self then client - * must subscribe to ticks. Client can also - * unsubscribe from ticks if not owner, - * long as the server is also not active. */ - if (base.IsOwner) - { - ChangeTickSubscription(true); - } - //Not new owner. - else - { - /* If client authoritative and ownership was lost - * then default goals must be set to force the - * object to it's last transform. */ - if (_clientAuthoritative) - SetDefaultGoalData(); - - if (!base.IsServer) - ChangeTickSubscription(false); - } - } - - public override void OnStopServer() - { - base.OnStopServer(); - //Always unsubscribe; if the server stopped so did client. - ChangeTickSubscription(false); - for (int i = 0; i < base.ObserverManager.GetLevelOfDetailDistances().Count; i++) - { - _lastSentTransformDatas[i].Reset(); - _serverChangedSinceReliable[i] = ChangedDelta.Unset; - _receivedClientData.SetHasData(false, (byte)i); - } - } - - public override void OnStopClient() - { - base.OnStopClient(); - //If not also server unsubscribe from ticks. - if (!base.IsServer) - ChangeTickSubscription(false); - } - - private void Update() - { - MoveToTarget(); - } - - /// - /// Configures components automatically. - /// - private void ConfigureComponents() - { - //Disabled. - if (_componentConfiguration == ComponentConfigurationType.Disabled) - { - return; - } - //RB. - else if (_componentConfiguration == ComponentConfigurationType.Rigidbody) - { - - if (TryGetComponent(out Rigidbody c)) - { - bool isKinematic = (!base.IsOwner || base.IsServerOnly); - c.isKinematic = isKinematic; - c.interpolation = RigidbodyInterpolation.None; - } - } - //RB2D - else if (_componentConfiguration == ComponentConfigurationType.Rigidbody2D) - { - //Only client authoritative needs to be configured. - if (!_clientAuthoritative) - return; - if (TryGetComponent(out Rigidbody2D c)) - { - bool isKinematic = (!base.IsOwner || base.IsServerOnly); - c.isKinematic = isKinematic; - c.simulated = !isKinematic; - c.interpolation = RigidbodyInterpolation2D.None; - } - } - //CC - else if (_componentConfiguration == ComponentConfigurationType.CharacterController) - { - if (TryGetComponent(out CharacterController c)) - { - //Client auth. - if (_clientAuthoritative) - { - c.enabled = base.IsOwner; - } - //Server auth. - else - { - //Not CSP. - if (_sendToOwner) - c.enabled = base.IsServer; - //Most likely CSP. - else - c.enabled = (base.IsServer || base.IsOwner); - - } - } - } - } - - /// - /// Called when a tick occurs. - /// - private void TimeManager_OnPostTick() - { - - if (base.IsServer) - { - byte lodIndex = base.ObserverManager.LevelOfDetailIndex; - SendToClients(lodIndex); - } - - if (base.IsClient) - SendToServer(_lastSentTransformDatas[0]); - } - - /// - /// Tries to subscribe to TimeManager ticks. - /// - private void ChangeTickSubscription(bool subscribe) - { - if (subscribe == _subscribedToTicks) - return; - - _subscribedToTicks = subscribe; - if (subscribe) - base.NetworkManager.TimeManager.OnPostTick += TimeManager_OnPostTick; - else - base.NetworkManager.TimeManager.OnPostTick -= TimeManager_OnPostTick; - } - - /// - /// Sets SendToOwner value. - /// - /// - [ObserversRpc(BufferLast = true, ExcludeServer = true)] - private void ObserversSetSendToOwner(bool value) - { - _sendToOwner = value; - } - - /// - /// Resets last sent information to force a resend of current values. - /// - public void ForceSend() - { - for (int i = 0; i < _lastSentTransformDatas.Count; i++) - _lastSentTransformDatas[i].Reset(); - if (_receivedClientData.Writer != null) - _receivedClientData.SetHasData(true); - } - - /// - /// Updates the interval value over the network. - /// - /// New interval. - public void SetInterval(byte value) - { - bool canSet = (base.IsServer && !_clientAuthoritative) - || (base.IsServer && _clientAuthoritative && !base.Owner.IsValid) - || (_clientAuthoritative && base.IsOwner); - - if (!canSet) - return; - - if (base.IsServer) - ObserversSetInterval(value); - else - ServerSetInterval(value); - } - - /// - /// Updates the interval value. - /// - /// - private void SetIntervalInternal(byte value) - { - value = (byte)Mathf.Max(value, 1); - _interval = value; - } - - /// - /// Sets interval over the network. - /// - [ServerRpc(RunLocally = true)] - private void ServerSetInterval(byte value) - { - if (!_clientAuthoritative) - { - - base.Owner.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"Connection Id {base.Owner.ClientId} has been kicked for trying to update this object without client authority."); - return; - } - - SetIntervalInternal(value); - } - /// - /// Sets interval over the network. - /// - [ObserversRpc(RunLocally = true)] - private void ObserversSetInterval(byte value) - { - SetIntervalInternal(value); - } - - - /// - /// Creates goal data using current position. - /// - private void SetDefaultGoalData() - { - Transform t = transform; - NetworkBehaviour parentBehaviour = null; - //If there is a parent try to output the behaviour on it. - if (_synchronizeParent && transform.parent != null) - { - transform.parent.TryGetComponent(out parentBehaviour); - if (parentBehaviour == null) - { - LogInvalidParent(); - } - else - { - _parentTransform = transform.parent; - _parentBehaviour = parentBehaviour; - } - } - - _lastReceivedTransformData.Update(0, t.localPosition, t.localRotation, t.localScale, t.localPosition, parentBehaviour); - SetInstantRates(_currentGoalData.Rates); - } - - /// - /// Prints an invalid parent debug. - /// - private void LogInvalidParent() - { - Debug.LogWarning($"{gameObject.name} [Id {base.ObjectId}] is nested but the parent {transform.parent.name} does not contain a NetworkBehaviour component. To synchronize parents the parent object must have a NetworkBehaviour component, even if empty."); - } - - /// - /// Serializes only changed data into writer. - /// - /// - /// - private void SerializeChanged(ChangedDelta changed, PooledWriter writer) - { - UpdateFlagA flagsA = UpdateFlagA.Unset; - UpdateFlagB flagsB = UpdateFlagB.Unset; - /* Do not use compression when nested. Depending - * on the scale of the parent compression may - * not be accurate enough. */ - TransformPackingData packing = (ChangedContains(changed, ChangedDelta.Nested)) ? - _unpacked : _packing; - - int startIndexA = writer.Position; - writer.Reserve(1); - //Original axis value. - float original; - //Compressed axis value. - float compressed; - //Multiplier for compression. - float multiplier = 100f; - /* Maximum value compressed may be - * to send as compressed. */ - float maxValue = (short.MaxValue - 1); - - Transform t = transform; - /* Position. */ - if (_synchronizePosition) - { - AutoPackType localPacking = packing.Position; - //PositionX - if (ChangedContains(changed, ChangedDelta.PositionX)) - { - original = t.localPosition.x; - compressed = original * multiplier; - if (localPacking != AutoPackType.Unpacked && Math.Abs(compressed) <= maxValue) - { - flagsA |= UpdateFlagA.X2; - writer.WriteInt16((short)compressed); - } - else - { - flagsA |= UpdateFlagA.X4; - writer.WriteSingle(original); - } - } - //PositionY - if (ChangedContains(changed, ChangedDelta.PositionY)) - { - original = t.localPosition.y; - compressed = original * multiplier; - if (localPacking != AutoPackType.Unpacked && Math.Abs(compressed) <= maxValue) - { - flagsA |= UpdateFlagA.Y2; - writer.WriteInt16((short)compressed); - } - else - { - flagsA |= UpdateFlagA.Y4; - writer.WriteSingle(original); - } - } - //PositionZ - if (ChangedContains(changed, ChangedDelta.PositionZ)) - { - original = t.localPosition.z; - compressed = original * multiplier; - if (localPacking != AutoPackType.Unpacked && Math.Abs(compressed) <= maxValue) - { - flagsA |= UpdateFlagA.Z2; - writer.WriteInt16((short)compressed); - } - else - { - flagsA |= UpdateFlagA.Z4; - writer.WriteSingle(original); - } - } - } - - /* Rotation. */ - if (_synchronizeRotation) - { - if (ChangedContains(changed, ChangedDelta.Rotation)) - { - flagsA |= UpdateFlagA.Rotation; - /* Rotation can always use pack settings even - * if nested. Unsual transform scale shouldn't affect rotation. */ - writer.WriteQuaternion(t.localRotation, _packing.Rotation); - } - } - - if (ChangedContains(changed, ChangedDelta.Extended)) - { - AutoPackType localPacking = packing.Scale; - flagsA |= UpdateFlagA.Extended; - int startIndexB = writer.Position; - writer.Reserve(1); - - /* Scale. */ - if (_synchronizeScale) - { - //ScaleX - if (ChangedContains(changed, ChangedDelta.ScaleX)) - { - original = t.localScale.x; - compressed = original * multiplier; - if (localPacking != AutoPackType.Unpacked && Math.Abs(compressed) <= maxValue) - { - flagsB |= UpdateFlagB.X2; - writer.WriteInt16((short)compressed); - } - else - { - flagsB |= UpdateFlagB.X4; - writer.WriteSingle(original); - } - } - //ScaleY - if (ChangedContains(changed, ChangedDelta.ScaleY)) - { - original = t.localScale.y; - compressed = original * multiplier; - if (localPacking != AutoPackType.Unpacked && Math.Abs(compressed) <= maxValue) - { - flagsB |= UpdateFlagB.Y2; - writer.WriteInt16((short)compressed); - } - else - { - flagsB |= UpdateFlagB.Y4; - writer.WriteSingle(original); - } - } - //ScaleZ - if (ChangedContains(changed, ChangedDelta.ScaleZ)) - { - original = t.localScale.z; - compressed = original * multiplier; - if (localPacking != AutoPackType.Unpacked && Math.Abs(compressed) <= maxValue) - { - flagsB |= UpdateFlagB.Z2; - writer.WriteInt16((short)compressed); - } - else - { - flagsB |= UpdateFlagB.Z4; - writer.WriteSingle(original); - } - } - } - - //Nested. - if (ChangedContains(changed, ChangedDelta.Nested) && _parentBehaviour != null) - { - flagsB |= UpdateFlagB.Nested; - writer.WriteNetworkBehaviour(_parentBehaviour); - } - - writer.FastInsertByte((byte)flagsB, startIndexB); - } - - //Insert flags. - writer.FastInsertByte((byte)flagsA, startIndexA); - bool ChangedContains(ChangedDelta whole, ChangedDelta part) - { - return (whole & part) == part; - } - } - - /// - /// Deerializes a received packet. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DeserializePacket(ArraySegment data, TransformData prevTransformData, TransformData nextTransformData, ref ChangedFull changedFull) - { - using (PooledReader r = ReaderPool.GetReader(data, base.NetworkManager)) - { - UpdateFlagA flagsA = (UpdateFlagA)r.ReadByte(); - - int readerRemaining; - readerRemaining = r.Remaining; - //X - if (UpdateFlagAContains(flagsA, UpdateFlagA.X2)) - nextTransformData.Position.x = r.ReadInt16() / 100f; - else if (UpdateFlagAContains(flagsA, UpdateFlagA.X4)) - nextTransformData.Position.x = r.ReadSingle(); - else - nextTransformData.Position.x = prevTransformData.Position.x; - //Y - if (UpdateFlagAContains(flagsA, UpdateFlagA.Y2)) - nextTransformData.Position.y = r.ReadInt16() / 100f; - else if (UpdateFlagAContains(flagsA, UpdateFlagA.Y4)) - nextTransformData.Position.y = r.ReadSingle(); - else - nextTransformData.Position.y = prevTransformData.Position.y; - //Z - if (UpdateFlagAContains(flagsA, UpdateFlagA.Z2)) - nextTransformData.Position.z = r.ReadInt16() / 100f; - else if (UpdateFlagAContains(flagsA, UpdateFlagA.Z4)) - nextTransformData.Position.z = r.ReadSingle(); - else - nextTransformData.Position.z = prevTransformData.Position.z; - //If remaining has changed then a position was read. - if (readerRemaining != r.Remaining) - changedFull |= ChangedFull.Position; - - //Rotation. - if (UpdateFlagAContains(flagsA, UpdateFlagA.Rotation)) - { - //Always use _packing value even if nested. - nextTransformData.Rotation = r.ReadQuaternion(_packing.Rotation); - changedFull |= ChangedFull.Rotation; - } - else - { - nextTransformData.Rotation = prevTransformData.Rotation; - } - - //Extended settings. - if (UpdateFlagAContains(flagsA, UpdateFlagA.Extended)) - { - UpdateFlagB flagsB = (UpdateFlagB)r.ReadByte(); - readerRemaining = r.Remaining; - - //X - if (UpdateFlagBContains(flagsB, UpdateFlagB.X2)) - nextTransformData.Scale.x = r.ReadInt16() / 100f; - else if (UpdateFlagBContains(flagsB, UpdateFlagB.X4)) - nextTransformData.Scale.x = r.ReadSingle(); - else - nextTransformData.Scale.x = prevTransformData.Scale.x; - //Y - if (UpdateFlagBContains(flagsB, UpdateFlagB.Y2)) - nextTransformData.Scale.y = r.ReadInt16() / 100f; - else if (UpdateFlagBContains(flagsB, UpdateFlagB.Y4)) - nextTransformData.Scale.y = r.ReadSingle(); - else - nextTransformData.Scale.y = prevTransformData.Scale.y; - //X - if (UpdateFlagBContains(flagsB, UpdateFlagB.Z2)) - nextTransformData.Scale.z = r.ReadInt16() / 100f; - else if (UpdateFlagBContains(flagsB, UpdateFlagB.Z4)) - nextTransformData.Scale.z = r.ReadSingle(); - else - nextTransformData.Scale.z = prevTransformData.Scale.z; - - if (r.Remaining != readerRemaining) - changedFull |= ChangedFull.Scale; - else - nextTransformData.Scale = prevTransformData.Scale; - - if (UpdateFlagBContains(flagsB, UpdateFlagB.Nested)) - { - nextTransformData.ParentBehaviour = r.ReadNetworkBehaviour(); - changedFull |= ChangedFull.Nested; - } - else - { - Unnest(); - } - } - //No extended settings. - else - { - nextTransformData.Scale = prevTransformData.Scale; - Unnest(); - } - } - - void Unnest() - { - nextTransformData.ParentBehaviour = null; - } - - //Returns if whole contains part. - bool UpdateFlagAContains(UpdateFlagA whole, UpdateFlagA part) - { - return (whole & part) == part; - } - //Returns if whole contains part. - bool UpdateFlagBContains(UpdateFlagB whole, UpdateFlagB part) - { - return (whole & part) == part; - } - } - - - - /// - /// Moves to a GoalData. Automatically determins if to use data from server or client. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void MoveToTarget(float deltaOverride = -1f) - { - if (!_queueReady) - return; - //Cannot move if neither is active. - if (!base.IsServer && !base.IsClient) - return; - //If client auth and the owner don't move towards target. - if (_clientAuthoritative) - { - if (base.IsOwner || TakenOwnership) - return; - } - else - { - //If not client authoritative, is owner, and don't sync to owner. - if (base.IsOwner && !_sendToOwner) - return; - } - - //True if not client controlled. - bool controlledByClient = (_clientAuthoritative && base.Owner.IsActive); - //If not controlled by client and is server then no reason to move. - if (!controlledByClient && base.IsServer) - return; - - float delta = (deltaOverride != -1f) ? deltaOverride : Time.deltaTime; - /* Once here it's safe to assume the object will be moving. - * Any checks which would stop it from moving be it client - * auth and owner, or server controlled and server, ect, - * would have already been run. */ - TransformData td = _currentGoalData.Transforms; - RateData rd = _currentGoalData.Rates; - - - - float multiplier = 1f; - int queueCount = _goalDataQueue.Count; - //For every entry past interpolation increase move rate. - if (queueCount > (_interpolation + 1)) - multiplier += (0.05f * queueCount); - - //Rate to update. Changes per property. - float rate; - Transform t = transform; - - //Snap any positions that should be. - SnapProperties(td); - - //Position. - if (_synchronizePosition) - { - rate = rd.Position; - Vector3 posGoal = (td.ExtrapolationState == TransformData.ExtrapolateState.Active && !_lastReceiveReliable) ? td.ExtrapolatedPosition : td.Position; - if (rate == -1f) - t.localPosition = td.Position; - else - t.localPosition = Vector3.MoveTowards(t.localPosition, posGoal, rate * delta * multiplier); - } - - //Rotation. - if (_synchronizeRotation) - { - rate = rd.Rotation; - if (rate == -1f) - t.localRotation = td.Rotation; - else - t.localRotation = Quaternion.RotateTowards(t.localRotation, td.Rotation, rate * delta); - } - - //Scale. - if (_synchronizeScale) - { - rate = rd.Scale; - if (rate == -1f) - t.localScale = td.Scale; - else - t.localScale = Vector3.MoveTowards(t.localScale, td.Scale, rate * delta); - } - - float timeRemaining = rd.TimeRemaining - (delta * multiplier); - if (timeRemaining < -delta) - timeRemaining = -delta; - rd.TimeRemaining = timeRemaining; - - if (rd.TimeRemaining <= 0f) - { - float leftOver = Mathf.Abs(rd.TimeRemaining); - //If more in buffer then run next buffer. - if (queueCount > 0) - { - _currentGoalData.Reset(); - _goalDataCache.Push(_currentGoalData); - SetCurrentGoalData(_goalDataQueue.Dequeue()); - if (leftOver > 0f) - MoveToTarget(leftOver); - } - //No more in buffer, see if can extrapolate. - else - { - - /* If everything matches up then end queue. - * Otherwise let it play out until stuff - * aligns. Generally the time remaining is enough - * but every once in awhile something goes funky - * and it's thrown off. */ - if (!HasChanged(td)) - _queueReady = false; - OnInterpolationComplete?.Invoke(); - - } - } - - } - - /// - /// Sends transform data to clients if needed. - /// - private void SendToClients(byte lodIndex) - { - //True if clientAuthoritative and there is an owner. - bool clientAuthoritativeWithOwner = (_clientAuthoritative && base.Owner.IsValid && !base.Owner.IsLocalClient); - //Channel to send rpc on. - Channel channel = Channel.Unreliable; - //If relaying from client. - if (clientAuthoritativeWithOwner) - { - if (_receivedClientData.HasData[lodIndex]) - { - _changedSinceStart = true; - //Resend data from clients. - ObserversUpdateTransform(_receivedClientData.Writer.GetArraySegment(), _receivedClientData.Channel); - _receivedClientData.SetHasData(false, lodIndex); - } - } - //Sending server transform state. - else - { - //Becomes true when any lod changes. - bool dataChanged = false; - //Check changes for every lod at and below passed in index. - for (int i = lodIndex; i >= 0; i--) - { - /* Reset writer. If does not have value - * after these checks then we know - * there's nothing to send for this lod. */ - PooledWriter writer = _changedWriters[i]; - writer.Reset(); - - TransformData lastSentData = _lastSentTransformDatas[i]; - ChangedDelta changed = GetChanged(lastSentData); - //If no change. - if (changed == ChangedDelta.Unset) - { - //No changes since last reliable; transform is up to date. - if (_serverChangedSinceReliable[i] == ChangedDelta.Unset) - continue; - - //Set changed to all changes over time and unset changes over time. - changed = _serverChangedSinceReliable[lodIndex]; - _serverChangedSinceReliable[i] = ChangedDelta.Unset; - channel = Channel.Reliable; - } - //There is change. - else - { - _serverChangedSinceReliable[i] |= changed; - } - - dataChanged = true; - _changedSinceStart = true; - Transform t = transform; - /* If here a send for transform values will occur. Update last values. - * Tick doesn't need to be set for whoever controls transform. */ - lastSentData.Update(0, t.localPosition, t.localRotation, t.localScale, t.localPosition, _parentBehaviour); - - SerializeChanged(changed, writer); - } - - //Send out changes. - if (dataChanged) - { - foreach (NetworkConnection nc in base.Observers) - { - //If to not send to owner. - if (!_sendToOwner && nc == base.Owner) - continue; - - byte lod; - if (!nc.LevelOfDetails.TryGetValue(base.NetworkObject, out lod)) - lod = 0; - //Not high enough index to send to conn. - if (lod > lodIndex) - continue; - //No need for server to send to local client (clientHost). - //Still send if development for stat tracking. -#if !DEVELOPMENT - if (!nc.IsLocalClient) -#endif - TargetUpdateTransform(nc, _changedWriters[lodIndex].GetArraySegment(), channel); - } - } - } - - } - - /// - /// Sends transform data to server if needed. - /// - private void SendToServer(TransformData lastSentTransformData) - { - /* ClientHost does not need to send to the server. - * Ideally this would still occur and the data be ignored - * for statistics tracking but to keep the code more simple - * we won't be doing that. Server out however still is tracked, - * which is generally considered more important data. */ - if (base.IsServer) - return; - - //Not client auth or not owner. - if (!_clientAuthoritative || !base.IsOwner) - return; - - //Channel to send on. - Channel channel = Channel.Unreliable; - //Values changed since last check. - ChangedDelta changed = GetChanged(lastSentTransformData); - - //If no change. - if (changed == ChangedDelta.Unset) - { - //No changes since last reliable; transform is up to date. - if (_clientChangedSinceReliable == ChangedDelta.Unset) - return; - - //Set changed to all changes over time and unset changes over time. - changed = _clientChangedSinceReliable; - _clientChangedSinceReliable = ChangedDelta.Unset; - channel = Channel.Reliable; - } - //There is change. - else - { - _clientChangedSinceReliable |= changed; - } - - /* If here a send for transform values will occur. Update last values. - * Tick doesn't need to be set for whoever controls transform. */ - Transform t = transform; - lastSentTransformData.Update(0, t.localPosition, t.localRotation, t.localScale, t.localPosition, _parentBehaviour); - - //Send latest. - using (PooledWriter writer = WriterPool.GetWriter()) - { - SerializeChanged(changed, writer); - ServerUpdateTransform(writer.GetArraySegment(), channel); - } - } - - - #region GetChanged. - /// - /// Returns if the transform differs from td. - /// - private bool HasChanged(TransformData td) - { - bool changed = (td.Position != transform.localPosition || - td.Rotation != transform.localRotation || - td.Scale != transform.localScale); - - return changed; - } - /// - /// Returns if there is any change between two datas. - /// - private bool HasChanged(TransformData a, TransformData b) - { - return (a.Position != b.Position) || - (a.Rotation != b.Rotation) || - (a.Scale != b.Scale) || - (a.ParentBehaviour != b.ParentBehaviour); - } - /// - /// Returns if there is any change between two datas and outputs what has changed. - /// - private bool HasChanged(TransformData a, TransformData b, ref ChangedFull changedFull) - { - bool hasChanged = false; - - if (a.Position != b.Position) - { - hasChanged = true; - changedFull |= ChangedFull.Position; - } - if (a.Rotation != b.Rotation) - { - hasChanged = true; - changedFull |= ChangedFull.Rotation; - } - if (a.Scale != b.Scale) - { - hasChanged = true; - changedFull |= ChangedFull.Scale; - } - if (a.ParentBehaviour != b.ParentBehaviour) - { - hasChanged = true; - changedFull |= ChangedFull.Nested; - } - - return hasChanged; - } - /// - /// Gets transform values that have changed against goalData. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private ChangedDelta GetChanged(TransformData transformData) - { - /* If parent behaviour exist. - * Parent isn't sent as a delta so - * if it exist always send regardless - * of the previously sent transform - * data. */ - return GetChanged(ref transformData.Position, ref transformData.Rotation, ref transformData.Scale, transformData.ParentBehaviour); - } - /// - /// Gets transform values that have changed against specified proprties. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private ChangedDelta GetChanged(ref Vector3 lastPosition, ref Quaternion lastRotation, ref Vector3 lastScale, NetworkBehaviour lastParentBehaviour) - { - ChangedDelta changed = ChangedDelta.Unset; - Transform t = transform; - - Vector3 position = t.localPosition; - if (position.x != lastPosition.x) - changed |= ChangedDelta.PositionX; - if (position.y != lastPosition.y) - changed |= ChangedDelta.PositionY; - if (position.z != lastPosition.z) - changed |= ChangedDelta.PositionZ; - - Quaternion rotation = t.localRotation; - if (!rotation.Matches(lastRotation, true)) - changed |= ChangedDelta.Rotation; - - ChangedDelta startChanged; - startChanged = changed; - - Vector3 scale = t.localScale; - if (scale.x != lastScale.x) - changed |= ChangedDelta.ScaleX; - if (scale.y != lastScale.y) - changed |= ChangedDelta.ScaleY; - if (scale.z != lastScale.z) - changed |= ChangedDelta.ScaleZ; - - //Only include parent if there is additional data to send. - bool sendParent = (_parentBehaviour == null && lastParentBehaviour != null) || (changed != ChangedDelta.Unset && _parentBehaviour != null); - if (sendParent) - changed |= ChangedDelta.Nested; - - //If added scale or nested then also add extended. - if (startChanged != changed) - changed |= ChangedDelta.Extended; - - return changed; - } - #endregion - - #region Rates. - /// - /// Snaps transform properties using snapping settings. - /// - private void SnapProperties(TransformData transformData, bool force = false) - { - //Already snapped. - if (transformData.Snapped) - return; - - transformData.Snapped = true; - Transform t = transform; - - //Position. - if (_synchronizePosition) - { - Vector3 position; - position.x = (force || _positionSnapping.X) ? transformData.Position.x : t.localPosition.x; - position.y = (force || _positionSnapping.Y) ? transformData.Position.y : t.localPosition.y; - position.z = (force || _positionSnapping.Z) ? transformData.Position.z : t.localPosition.z; - t.localPosition = position; - } - - //Rotation. - if (_synchronizeRotation) - { - Vector3 eulers; - Vector3 goalEulers = transformData.Rotation.eulerAngles; - eulers.x = (force || _rotationSnapping.X) ? goalEulers.x : t.localEulerAngles.x; - eulers.y = (force || _rotationSnapping.Y) ? goalEulers.y : t.localEulerAngles.y; - eulers.z = (force || _rotationSnapping.Z) ? goalEulers.z : t.localEulerAngles.z; - t.localEulerAngles = eulers; - } - - //Scale. - if (_synchronizeScale) - { - Vector3 scale; - scale.x = (force || _scaleSnapping.X) ? transformData.Scale.x : t.localScale.x; - scale.y = (force || _scaleSnapping.Y) ? transformData.Scale.y : t.localScale.y; - scale.z = (force || _scaleSnapping.Z) ? transformData.Scale.z : t.localScale.z; - t.localScale = scale; - } - } - - /// - /// Sets move rates which will occur instantly. - /// - private void SetInstantRates(RateData rd) - { - rd.Update(-1f, -1f, -1f, -1f, 1, false, -1f); - } - - /// - /// Sets move rates which will occur over time. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void SetCalculatedRates(uint lastTick, RateData prevRd, TransformData prevTd, GoalData nextGd, ChangedFull changedFull, bool hasChanged, Channel channel) - { - /* Only update rates if data has changed. - * When data comes in reliably for eventual consistency - * it's possible that it will be the same as the last - * unreliable packet. When this happens no change has occurred - * and the distance of change woudl also be 0; this prevents - * the NT from moving. Only need to compare data if channel is reliable. */ - TransformData td = nextGd.Transforms; - if (channel == Channel.Reliable && !hasChanged) - { - nextGd.Rates.Update(prevRd); - return; - } - - /* How much time has passed between last update and current. - * If set to 0 then that means the transform has - * settled. */ - if (lastTick == 0) - lastTick = (nextGd.Transforms.Tick - _interval); - - uint tickDifference = (td.Tick - lastTick); - float timePassed = (float)base.NetworkManager.TimeManager.TicksToTime(tickDifference); - - //Distance between properties. - float distance; - float positionRate = 0f; - float rotationRate = 0f; - float scaleRate = 0f; - - RateData rd = nextGd.Rates; - //Correction to apply towards rates when a rate change is detected as abnormal. - float abnormalCorrection = 1f; - bool abnormalRateDetected = false; - float unalteredPositionRate = rd.LastUnalteredPositionRate; - - //Position. - if (ChangedFullContains(changedFull, ChangedFull.Position)) - { - Vector3 lastPosition = prevTd.Position; - distance = Vector3.Distance(lastPosition, td.Position); - //If distance teleports assume rest do. - if (_enableTeleport && distance >= _teleportThreshold) - { - SetInstantRates(rd); - return; - } - - //Position distance already calculated. - unalteredPositionRate = distance / timePassed; - /* Try to detect abnormal rate changes. - * - * This won't occur if the user - * is moving using the tick system but will likely happen when the transform - * is being moved in update. - * - * Update will iterate a varying amount of times per tick, - * which will result in distances being slightly different. This is - * rarely an issue when the frame rate is high and the distance - * variance is very little, but for games which are running at about - * the same frame rate as the tick it's possible the object will - * move twice the distance every few ticks. EG: if running 60 fps/50 tick. - * Execution may look like this.. - * frame, tick, frame, tick, frame, frame, tick. The frame, frame would - * result in double movement distance. */ - - //If last position rate is known then compare against it. - if (unalteredPositionRate > 0f && rd.LastUnalteredPositionRate > 0f) - { - float percentage = Mathf.Abs(1f - (unalteredPositionRate / rd.LastUnalteredPositionRate)); - /* If percentage change is more than 25% then speed is considered - * to have changed drastically. */ - if (percentage > 0.25f) - { - float c = (rd.LastUnalteredPositionRate / unalteredPositionRate); - /* Sometimes stop and goes can incorrectly trigger - * an abnormal detection. Fortunately abnornalties tend - * to either skip a tick or send twice in one tick. - * Because of this it's fairly safe to assume that if the calculated - * correction is not ~0.5f or ~2f then it's a false detection. */ - float allowedDifference = 0.1f; - if ( - (c < 1f && Mathf.Abs(0.5f - c) < allowedDifference) || - (c > 1f && Mathf.Abs(2f - c) < allowedDifference)) - { - abnormalCorrection = c; - abnormalRateDetected = true; - } - /* If an abnormality has been marked then assume new rate - * is proper. When an abnormal rate occurs unintentionally - * the values will fix themselves next tick, therefor when - * rate changes drastically twice assume its intentional or - * that the rate had simply fixed itself, both which would unset - * abnormal rate detected. */ - } - } - - //abnormalCorrection = 1f; - positionRate = (unalteredPositionRate * abnormalCorrection); - if (positionRate <= 0f) - positionRate = -1f; - } - - //Rotation. - if (ChangedFullContains(changedFull, ChangedFull.Rotation)) - { - Quaternion lastRotation = prevTd.Rotation; - distance = lastRotation.Angle(td.Rotation, true); - rotationRate = (distance / timePassed) * abnormalCorrection; - if (rotationRate <= 0f) - rotationRate = -1f; - } - - //Scale. - if (ChangedFullContains(changedFull, ChangedFull.Scale)) - { - Vector3 lastScale = prevTd.Scale; - distance = Vector3.Distance(lastScale, td.Scale); - scaleRate = (distance / timePassed) * abnormalCorrection; - if (scaleRate <= 0f) - scaleRate = -1f; - } - - rd.Update(positionRate, rotationRate, scaleRate, unalteredPositionRate, tickDifference, abnormalRateDetected, timePassed); - - //Returns if whole contains part. - bool ChangedFullContains(ChangedFull whole, ChangedFull part) - { - return (whole & part) == part; - } - } - #endregion - - /// - /// Sets extrapolation data on next. - /// - /// - /// - /// - private void SetExtrapolation(TransformData prev, TransformData next, Channel channel) - { - //Default value. - next.ExtrapolationState = TransformData.ExtrapolateState.Disabled; - - - } - - - /// - /// Updates a client with transform data. - /// - [TargetRpc(ValidateTarget = false)] - private void TargetUpdateTransform(NetworkConnection conn, ArraySegment data, Channel channel) - { -#if DEVELOPMENT - //If receiver is client host then do nothing, clientHost need not process. - if (base.IsServer && conn.IsLocalClient) - return; -#endif - - byte lod; - /* Get cached LOD for connection receiving this. It will of course - * always be the local client for conn. */ - if (!conn.LevelOfDetails.TryGetValue(base.NetworkObject, out lod)) - lod = 0; - - //Update the interval so speed calculations are proper. - _interval = base.ObserverManager.GetLevelOfDetailInterval(lod); - DataReceived(data, channel, false); - } - - /// - /// Updates clients with transform data. - /// - [ObserversRpc] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ObserversUpdateTransform(ArraySegment data, Channel channel) - { - if (!_clientAuthoritative && base.IsOwner && !_sendToOwner) - return; - if (_clientAuthoritative && base.IsOwner) - return; - if (base.IsServer) - return; - - //Not new data. - uint lastPacketTick = base.TimeManager.LastPacketTick; - if (lastPacketTick <= _lastObserversRpcTick) - return; - _lastObserversRpcTick = lastPacketTick; - - DataReceived(data, channel, false); - } - - ///// - ///// Updates clients with transform data. - ///// - //[TargetRpc(ValidateTarget = false)] - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //private void TargetUpdateTransform(NetworkConnection conn, ArraySegment data, Channel channel) - //{ - // if (!_clientAuthoritative && base.IsOwner && !_sendToOwner) - // return; - // if (_clientAuthoritative && base.IsOwner) - // return; - // if (base.IsServer) - // return; - - // //Not new data. - // uint lastPacketTick = base.TimeManager.LastPacketTick; - // if (lastPacketTick <= _lastObserversRpcTick) - // return; - // _lastObserversRpcTick = lastPacketTick; - - // DataReceived(data, channel, false); - //} - - /// - /// Updates the transform on the server. - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ServerRpc] - private void ServerUpdateTransform(ArraySegment data, Channel channel) - { - if (!_clientAuthoritative) - { - base.Owner.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"Connection Id {base.Owner.ClientId} has been kicked for trying to update this object without client authority."); - return; - } - - //Not new data. - uint lastPacketTick = base.TimeManager.LastPacketTick; - if (lastPacketTick <= _lastServerRpcTick) - return; - _lastServerRpcTick = lastPacketTick; - - //Populate writer if it doesn't exist. - if (_receivedClientData.Writer == null) - _receivedClientData.Writer = WriterPool.GetWriter(); - _receivedClientData.Channel = channel; - _receivedClientData.Writer.Reset(); - _receivedClientData.Writer.WriteArraySegment(data); - _receivedClientData.SetHasData(true); - - DataReceived(data, channel, true); - } - - /// - /// Processes received data for lcients and server. - /// - private void DataReceived(ArraySegment data, Channel channel, bool asServer) - { - TransformData prevTd = _lastReceivedTransformData; - RateData prevRd = _lastCalculatedRateData; - ChangedFull changedFull = new ChangedFull(); - - GoalData nextGd = GetCachedGoalData(); - TransformData nextTd = nextGd.Transforms; - UpdateTransformData(data, prevTd, nextTd, ref changedFull); - OnDataReceived?.Invoke(prevTd, nextTd); - SetExtrapolation(prevTd, nextTd, channel); - - bool hasChanged = HasChanged(prevTd, nextTd); - //If server only teleport. - if (asServer && !base.IsClient) - SetInstantRates(nextGd.Rates); - //Otherwise use timed. - else - SetCalculatedRates(prevTd.Tick, prevRd, prevTd, nextGd, changedFull, hasChanged, channel); - - _lastReceivedTransformData.Update(nextTd); - - _lastReceiveReliable = (channel == Channel.Reliable); - /* If channel is reliable then this is a settled packet. - * Reset last received tick so next starting move eases - * in. */ - if (channel == Channel.Reliable) - nextTd.Tick = 0; - - prevTd.Update(nextTd); - prevRd.Update(nextGd.Rates); - - nextGd.ReceivedTick = base.TimeManager.LocalTick; - - /* If extrapolating then immediately break the extrapolation - * in favor of newest results. This will keep the buffer - * at 0 until the transform settles but the only other option is - * to stop the movement, which would defeat purpose of extrapolation, - * or slow down the transform while buffer rebuilds. Neither choice - * is great but later on I might try slowing down the transform slightly - * to give the buffer a chance to rebuild. */ - if (_currentGoalData.Transforms.ExtrapolationState == TransformData.ExtrapolateState.Active) - { - _queueReady = true; - SetCurrentGoalData(nextGd); - } - /* If queue isn't started and its buffered enough - * to satisfy interpolation then set ready - * and set current data. - * - * Also if reliable then begin moving. */ - else if (!_queueReady && _goalDataQueue.Count >= _interpolation - || channel == Channel.Reliable) - { - _queueReady = true; - if (_goalDataQueue.Count > 0) - { - SetCurrentGoalData(_goalDataQueue.Dequeue()); - /* If is reliable and has changed then also - * enqueue latest. */ - if (hasChanged) - _goalDataQueue.Enqueue(nextGd); - - } - else - { - SetCurrentGoalData(nextGd); - } - } - /* If here then there's not enough in buffer to begin - * so add onto the buffer. */ - else - { - _goalDataQueue.Enqueue(nextGd); - } - - /* If the queue is excessive beyond interpolation then - * dequeue extras to prevent from dropping behind too - * quickly. This shouldn't be an issue with normal movement - * as the NT speeds up if the buffer unexpectedly grows, but - * when connections are unstable results may come in chunks - * and for a better experience the older parts of the chunks - * will be dropped. */ - if (_goalDataQueue.Count > (_interpolation + 3)) - { - while (_goalDataQueue.Count > _interpolation) - { - GoalData tmpGd = _goalDataQueue.Dequeue(); - _goalDataCache.Push(tmpGd); - } - //Snap to the next data to fix any smoothing timings. - SetCurrentGoalData(_goalDataQueue.Dequeue()); - SetInstantRates(_currentGoalData.Rates); - SnapProperties(_currentGoalData.Transforms, true); - } - } - - /// - /// Sets CurrentGoalData value. - /// - /// - private void SetCurrentGoalData(GoalData data) - { - _currentGoalData = data; - OnNextGoal?.Invoke(data); - } - - /// - /// Immediately sets the parent of this NetworkTransform for a single connection. - /// - [TargetRpc] - private void TargetSetParent(NetworkConnection conn, NetworkBehaviour parent) - { - - } - - /// - /// Updates a TransformData from packetData. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void UpdateTransformData(ArraySegment packetData, TransformData prevTransformData, TransformData nextTransformData, ref ChangedFull changedFull) - { - DeserializePacket(packetData, prevTransformData, nextTransformData, ref changedFull); - nextTransformData.Tick = base.TimeManager.LastPacketTick; - } - - /// - /// Returns a GoalData from the cache. - /// - /// - private GoalData GetCachedGoalData() - { - GoalData result = (_goalDataCache.Count > 0) ? _goalDataCache.Pop() : new GoalData(); - result.Reset(); - return result; - } - - /// - /// Configures this NetworkTransform for CSP. - /// - internal void ConfigureForCSP() - { - _clientAuthoritative = false; - if (base.IsServer) - _sendToOwner = false; - - /* If other or CC then needs to be configured. - * When CC it will be configured properly, if there - * is no CC then no action will be taken. */ - _componentConfiguration = ComponentConfigurationType.CharacterController; - ConfigureComponents(); - } - - /// - /// Updates which properties are synchronized. - /// - /// Properties to synchronize. - public void SetSynchronizedProperties(SynchronizedProperty value) - { - /* Make sure permissions are proper to change values. - * Let the server override client auth. - * - * Can send if server. - * Or owner + client auth. - */ - bool canSend = ( - base.IsServer || - (_clientAuthoritative && base.IsOwner) - ); - - if (!canSend) - return; - - //If server send out observerRpc. - if (base.IsServer) - ObserversSetSynchronizedProperties(value); - //Otherwise send to the server. - else - ServerSetSynchronizedProperties(value); - } - - /// - /// Sets synchronized values based on value. - /// - [ServerRpc] - private void ServerSetSynchronizedProperties(SynchronizedProperty value) - { - if (!_clientAuthoritative) - { - base.Owner.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"Connection Id {base.Owner.ClientId} has been kicked for trying to update this object without client authority."); - return; - } - - SetSynchronizedPropertiesInternal(value); - ObserversSetSynchronizedProperties(value); - } - - /// - /// Sets synchronized values based on value. - /// - [ObserversRpc(BufferLast = true)] - private void ObserversSetSynchronizedProperties(SynchronizedProperty value) - { - //Would have already run on server if host. - if (base.IsServer) - return; - - SetSynchronizedPropertiesInternal(value); - } - - /// - /// Sets synchronized values based on value. - /// - private void SetSynchronizedPropertiesInternal(SynchronizedProperty value) - { - _synchronizeParent = SynchronizedPropertyContains(value, SynchronizedProperty.Parent); - _synchronizePosition = SynchronizedPropertyContains(value, SynchronizedProperty.Position); - _synchronizeRotation = SynchronizedPropertyContains(value, SynchronizedProperty.Rotation); - _synchronizeScale = SynchronizedPropertyContains(value, SynchronizedProperty.Scale); - - bool SynchronizedPropertyContains(SynchronizedProperty whole, SynchronizedProperty part) - { - return (whole & part) == part; - } - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/NetworkTransform.cs.meta b/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/NetworkTransform.cs.meta deleted file mode 100644 index 76f2fc8..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/NetworkTransform.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a2836e36774ca1c4bbbee976e17b649c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/SynchronizedProperty.cs b/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/SynchronizedProperty.cs deleted file mode 100644 index a154521..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/SynchronizedProperty.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace FishNet.Component.Transforming -{ - - public enum SynchronizedProperty : byte - { - None = 0, - Parent = 1, - Position = 2, - Rotation = 4, - Scale = 8 - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/SynchronizedProperty.cs.meta b/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/SynchronizedProperty.cs.meta deleted file mode 100644 index 28fe681..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/NetworkTransform/SynchronizedProperty.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3e6005ee9abfdd542ad27023114bbe04 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction.meta b/Assets/FishNet/Runtime/Generated/Component/Prediction.meta deleted file mode 100644 index aabf13e..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e4f8fbf54adbf5d4781d2c88c0aaebd8 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/Editor.meta b/Assets/FishNet/Runtime/Generated/Component/Prediction/Editor.meta deleted file mode 100644 index 9e480d2..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: a6b05a47941365c4097d74bca5e47017 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/Editor/PredictedObjectEditor.cs b/Assets/FishNet/Runtime/Generated/Component/Prediction/Editor/PredictedObjectEditor.cs deleted file mode 100644 index a75df56..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/Editor/PredictedObjectEditor.cs +++ /dev/null @@ -1,152 +0,0 @@ -#if UNITY_EDITOR -using UnityEditor; -using UnityEngine; -using static FishNet.Component.Prediction.PredictedObject; - -namespace FishNet.Component.Prediction -{ - - - [CustomEditor(typeof(PredictedObject), true)] - [CanEditMultipleObjects] - public class PredictedObjectEditor : Editor - { - private SerializedProperty _implementsPredictionMethods; - private SerializedProperty _graphicalObject; - private SerializedProperty _ownerSmoothPosition; - private SerializedProperty _ownerSmoothRotation; - private SerializedProperty _ownerInterpolation; - private SerializedProperty _enableTeleport; - private SerializedProperty _teleportThreshold; - private SerializedProperty _predictionType; - - private SerializedProperty _rigidbody; - private SerializedProperty _rigidbody2d; - private SerializedProperty _spectatorSmoothPosition; - private SerializedProperty _spectatorSmoothRotation; - private SerializedProperty _spectatorSmoothingType; - private SerializedProperty _customSmoothingData; - private SerializedProperty _preconfiguredSmoothingDataPreview; - private SerializedProperty _maintainedVelocity; - private SerializedProperty _resendType; - private SerializedProperty _resendInterval; - - private SerializedProperty _networkTransform; - - protected virtual void OnEnable() - { - _implementsPredictionMethods = serializedObject.FindProperty(nameof(_implementsPredictionMethods)); - _graphicalObject = serializedObject.FindProperty(nameof(_graphicalObject)); - _ownerSmoothPosition = serializedObject.FindProperty(nameof(_ownerSmoothPosition)); - _ownerSmoothRotation = serializedObject.FindProperty(nameof(_ownerSmoothRotation)); - _ownerInterpolation = serializedObject.FindProperty(nameof(_ownerInterpolation)); - _enableTeleport = serializedObject.FindProperty(nameof(_enableTeleport)); - _teleportThreshold = serializedObject.FindProperty(nameof(_teleportThreshold)); - _predictionType = serializedObject.FindProperty(nameof(_predictionType)); - - _rigidbody = serializedObject.FindProperty(nameof(_rigidbody)); - _rigidbody2d = serializedObject.FindProperty(nameof(_rigidbody2d)); - _spectatorSmoothPosition = serializedObject.FindProperty(nameof(_spectatorSmoothPosition)); - _spectatorSmoothRotation = serializedObject.FindProperty(nameof(_spectatorSmoothRotation)); - _spectatorSmoothingType = serializedObject.FindProperty(nameof(_spectatorSmoothingType)); - _customSmoothingData = serializedObject.FindProperty(nameof(_customSmoothingData)); - _preconfiguredSmoothingDataPreview = serializedObject.FindProperty(nameof(_preconfiguredSmoothingDataPreview)); - - _maintainedVelocity = serializedObject.FindProperty(nameof(_maintainedVelocity)); - _resendType = serializedObject.FindProperty(nameof(_resendType)); - _resendInterval = serializedObject.FindProperty(nameof(_resendInterval)); - - _networkTransform = serializedObject.FindProperty(nameof(_networkTransform)); - - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - GUI.enabled = false; - EditorGUILayout.ObjectField("Script:", MonoScript.FromMonoBehaviour((PredictedObject)target), typeof(PredictedObject), false); - GUI.enabled = true; - - EditorGUILayout.PropertyField(_implementsPredictionMethods); - EditorGUILayout.PropertyField(_graphicalObject); - EditorGUILayout.PropertyField(_enableTeleport); - if (_enableTeleport.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_teleportThreshold); - EditorGUI.indentLevel--; - } - - EditorGUILayout.LabelField("Owner Settings"); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_ownerSmoothPosition, new GUIContent("Smooth Position")); - EditorGUILayout.PropertyField(_ownerSmoothRotation, new GUIContent("Smooth Rotation")); - EditorGUILayout.PropertyField(_ownerInterpolation, new GUIContent("Interpolation")); - EditorGUI.indentLevel--; - - EditorGUILayout.PropertyField(_predictionType); - PredictedObject.PredictionType movementType = (PredictedObject.PredictionType)_predictionType.intValue; - if (movementType != PredictedObject.PredictionType.Other) - { - EditorGUI.indentLevel++; - EditorGUILayout.HelpBox("When using physics prediction do not include a NetworkTransform; this component will synchronize instead.", MessageType.Info); - if (movementType == PredictedObject.PredictionType.Rigidbody) - EditorGUILayout.PropertyField(_rigidbody); - else - EditorGUILayout.PropertyField(_rigidbody2d, new GUIContent("Rigidbody2D", "Rigidbody2D to predict.")); - - EditorGUILayout.LabelField("Spectator Settings"); - EditorGUI.indentLevel++; - EditorGUILayout.LabelField("Smoothing"); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_spectatorSmoothPosition, new GUIContent("Smooth Position")); - EditorGUILayout.PropertyField(_spectatorSmoothRotation, new GUIContent("Smooth Rotation")); - EditorGUILayout.PropertyField(_spectatorSmoothingType, new GUIContent("Smoothing Type")); - //Custom. - if ((SpectatorSmoothingType)_spectatorSmoothingType.intValue == SpectatorSmoothingType.Custom) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_customSmoothingData); - EditorGUI.indentLevel--; - } - //Preconfigured. - else - { - EditorGUI.indentLevel++; - GUI.enabled = false; - EditorGUILayout.PropertyField(_preconfiguredSmoothingDataPreview); - GUI.enabled = true; - EditorGUI.indentLevel--; - } - EditorGUI.indentLevel--; - EditorGUILayout.PropertyField(_maintainedVelocity); - - EditorGUILayout.PropertyField(_resendType); - PredictedObject.ResendType resendType = (PredictedObject.ResendType)_resendType.intValue; - if (resendType == PredictedObject.ResendType.Interval) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_resendInterval, new GUIContent("Interval")); - EditorGUI.indentLevel--; - } - EditorGUI.indentLevel--; - - EditorGUI.indentLevel--; - } - else - { - EditorGUI.indentLevel++; - EditorGUILayout.HelpBox("When other is selected another component, such as NetworkTransform, must be used to synchronize.", MessageType.Info); - EditorGUILayout.PropertyField(_networkTransform); - EditorGUI.indentLevel--; - } - - EditorGUILayout.Space(); - serializedObject.ApplyModifiedProperties(); - } - - } -} -#endif - diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/Editor/PredictedObjectEditor.cs.meta b/Assets/FishNet/Runtime/Generated/Component/Prediction/Editor/PredictedObjectEditor.cs.meta deleted file mode 100644 index 2a45c05..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/Editor/PredictedObjectEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e0b8595657415764e9d83b6d974043af -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/OfflineRigidbody.cs b/Assets/FishNet/Runtime/Generated/Component/Prediction/OfflineRigidbody.cs deleted file mode 100644 index b691a76..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/OfflineRigidbody.cs +++ /dev/null @@ -1,130 +0,0 @@ -using FishNet.Managing.Predicting; -using FishNet.Managing.Timing; -using FishNet.Object; -using UnityEngine; - -namespace FishNet.Component.Prediction -{ - public partial class OfflineRigidbody : MonoBehaviour - { - - #region Serialized. - /// - /// Type of prediction movement which is being used. - /// - [Tooltip("Type of prediction movement which is being used.")] - [SerializeField] - private RigidbodyType _rigidbodyType; - /// - /// GraphicalObject to unparent when pausing. - /// - private Transform _graphicalObject; - /// - /// Sets GraphicalObject. - /// - /// - public void SetGraphicalObject(Transform value) - { - _graphicalObject = value; - UpdateRigidbodies(); - } - /// - /// True to also get rigidbody components within children. - /// - [Tooltip("True to also get rigidbody components within children.")] - [SerializeField] - private bool _getInChildren; - #endregion - - #region Private. - /// - /// Pauser for rigidbodies. - /// - private RigidbodyPauser _rigidbodyPauser = new RigidbodyPauser(); - /// - /// TimeManager subscribed to. - /// - private PredictionManager _predictionManager; - #endregion - - - private void Awake() - { - InitializeOnce(); - } - - - private void OnDestroy() - { - ChangeSubscription(false); - } - - /// - /// Initializes this script for use. - /// - private void InitializeOnce() - { - _predictionManager = InstanceFinder.PredictionManager; - UpdateRigidbodies(); - ChangeSubscription(true); - } - - /// - /// Sets a new TimeManager to use. - /// - /// - public void SetPredictionManager(PredictionManager pm) - { - if (pm == _predictionManager) - return; - - //Unsub from current. - ChangeSubscription(false); - //Sub to newest. - _predictionManager = pm; - ChangeSubscription(true); - } - - /// - /// Finds and assigns rigidbodie using configured settings. - /// - public void UpdateRigidbodies() - { - _rigidbodyPauser.UpdateRigidbodies(transform, _rigidbodyType, _getInChildren, _graphicalObject); - } - - /// - /// Changes the subscription to the TimeManager. - /// - private void ChangeSubscription(bool subscribe) - { - if (_predictionManager == null) - return; - - if (subscribe) - { - _predictionManager.OnPreReconcile += _predictionManager_OnPreReconcile; - _predictionManager.OnPostReconcile += _predictionManager_OnPostReconcile; - } - else - { - _predictionManager.OnPreReconcile -= _predictionManager_OnPreReconcile; - _predictionManager.OnPostReconcile -= _predictionManager_OnPostReconcile; - } - } - - private void _predictionManager_OnPreReconcile(NetworkBehaviour obj) - { - //Make rbs all kinematic/!simulated before reconciling, which would also result in replays. - _rigidbodyPauser.Pause(); - } - - private void _predictionManager_OnPostReconcile(NetworkBehaviour obj) - { - _rigidbodyPauser.Unpause(); - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/OfflineRigidbody.cs.meta b/Assets/FishNet/Runtime/Generated/Component/Prediction/OfflineRigidbody.cs.meta deleted file mode 100644 index cd25d95..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/OfflineRigidbody.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b749f90d4c9961c4991179db1130fa4d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.Rigidbodies.cs b/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.Rigidbodies.cs deleted file mode 100644 index ceb2985..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.Rigidbodies.cs +++ /dev/null @@ -1,1148 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing; -using FishNet.Managing.Timing; -using FishNet.Object; -using FishNet.Transporting; -using FishNet.Utility; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Component.Prediction -{ - public partial class PredictedObject : NetworkBehaviour - { - #region Types. - [System.Serializable] - public struct SmoothingData - { - /// - /// Percentage of ping to use as interpolation. Higher values will result in more interpolation. - /// - [Tooltip("Percentage of ping to use as interpolation. Higher values will result in more interpolation.")] - [Range(0.01f, 5f)] - public float InterpolationPercent; - /// - /// Percentage of ping to use as interpolation when colliding with an object local client owns. - /// This is used to speed up local interpolation when predicted objects collide with a player as well keep graphics closer to the objects root while colliding. - /// - [Tooltip("Percentage of ping to use as interpolation when colliding with an object local client owns." + - "This is used to speed up local interpolation when predicted objects collide with a player as well keep graphics closer to the objects root while colliding.")] - [Range(0.01f, 5f)] - public float CollisionInterpolationPercent; - /// - /// How much per tick to decrease to collision interpolation when colliding with a local player object. - /// Higher values will set interpolation to collision settings faster. - /// - [Tooltip("How much per tick to decrease to collision interpolation when colliding with a local player object. Higher values will set interpolation to collision settings faster.")] - [Range(1, byte.MaxValue)] - public byte InterpolationDecreaseStep; - /// - /// How much per tick to increase to normal interpolation when not colliding with a local player object. - /// Higher values will set interpolation to normal settings faster. - /// - [Tooltip("How much per tick to increase to normal interpolation when not colliding with a local player object. Higher values will set interpolation to normal settings faster.")] - [Range(1, byte.MaxValue)] - public byte InterpolationIncreaseStep; - } - #endregion - - #region All. - #region Internal. - /// - /// True if owner and implements prediction methods. - /// - internal bool IsPredictingOwner() => (base.IsOwner && _implementsPredictionMethods); - #endregion - #region Private. - /// - /// Pauser for rigidbodies when they cannot be rolled back. - /// - private RigidbodyPauser _rigidbodyPauser = new RigidbodyPauser(); - /// - /// Next tick to resend data when resend type is set to interval. - /// - private uint _nextIntervalResend; - /// - /// Number of resends remaining when the object has not changed. - /// - private ushort _resendsRemaining; - /// - /// True if object was changed previous tick. - /// - private bool _previouslyChanged; - /// - /// Animators found on the graphical object. - /// - private Animator[] _graphicalAnimators; - /// - /// True if GraphicalAniamtors have been intialized. - /// - private bool _animatorsInitialized; - /// - /// Tick on the last received state. - /// - private uint _lastStateLocalTick; - /// - /// True if a connection is owner and prediction methods are implemented. - /// - private bool _isPredictingOwner(NetworkConnection c) => (c == base.Owner && _implementsPredictionMethods); - /// - /// Current interpolation value. - /// - private long _currentSpectatorInterpolation; - /// - /// Target interpolation when collision is exited. - /// - private uint _targetSpectatorInterpolation; - /// - /// Target interpolation when collision is entered. - /// - private uint _targetCollisionSpectatorInterpolation; - /// - /// How much per tick to decrease to collision interpolation when colliding with a local player object. - /// - private byte _interpolationDecreaseStep; - /// - /// How much per tick to increase to normal interpolation when not colliding with a local player object. - /// - private byte _interpolationIncreaseStep; - /// - /// Last local tick that collision has stayed with local client objects. - /// - private uint _collisionStayedTick; - /// - /// Local client objects this object is currently colliding with. - /// - private HashSet _localClientCollidedObjects = new HashSet(); - /// - /// True if spectator prediction is paused. - /// - private bool _spectatorPaused; - ///// - ///// Target number of ticks to ignore when replaying. - ///// - //private uint _ignoredTicks; - #region Smoothing datas. - private static SmoothingData _accurateSmoothingData = new SmoothingData() - { - InterpolationPercent = 0.5f, - CollisionInterpolationPercent = 0.05f, - InterpolationDecreaseStep = 1, - InterpolationIncreaseStep = 2, - }; - private static SmoothingData _mixedSmoothingData = new SmoothingData() - { - InterpolationPercent = 1f, - CollisionInterpolationPercent = 0.1f, - InterpolationDecreaseStep = 1, - InterpolationIncreaseStep = 3, - }; - private static SmoothingData _gradualSmoothingData = new SmoothingData() - { - InterpolationPercent = 1.5f, - CollisionInterpolationPercent = 0.2f, - InterpolationDecreaseStep = 1, - InterpolationIncreaseStep = 5, - }; - #endregion - #endregion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void Rigidbodies_OnSpawnServer(NetworkConnection c) - { - if (!IsRigidbodyPrediction) - return; - if (c == base.Owner) - return; - if (c.IsLocalClient) - return; - - uint tick = c.LastPacketTick; - if (_predictionType == PredictionType.Rigidbody) - SendRigidbodyState(tick, c, true); - else - SendRigidbody2DState(tick, c, true); - } - - /// - /// Called when the client starts. - /// - private void Rigidbodies_OnStartClient() - { - //Store up to 1 second of states. - int capacity = base.TimeManager.TickRate; - /* Only need to check one collection capacity since they both will be the same. - * If capacity does not line up then re-initialize. */ - if (capacity != _rigidbodyStates.Capacity) - { - _rigidbodyStates.Initialize(capacity); - _rigidbody2dStates.Initialize(capacity); - } - } - - /// - /// Called on client when ownership changes for this object. - /// - /// - private void Rigidbodies_OnOwnershipClient(NetworkConnection prevOwner) - { - if (!IsRigidbodyPrediction) - return; - //If owner no need to fix for animators. - if (base.IsOwner) - return; - //Would have already fixed if animators are set. - if (_animatorsInitialized) - return; - - _animatorsInitialized = true; - _graphicalAnimators = _graphicalObject.GetComponentsInChildren(true); - - if (_graphicalAnimators.Length > 0) - { - for (int i = 0; i < _graphicalAnimators.Length; i++) - _graphicalAnimators[i].keepAnimatorStateOnDisable = true; - - /* True if at least one animator is on the graphical root. - * Unity gets components in order so it's safe to assume - * 0 would be the topmost animator. This has to be done - * to prevent animation jitter when pausing the rbs. */ - if (_graphicalAnimators[0].transform == _graphicalObject) - { - Transform graphicalHolder = new GameObject().transform; - graphicalHolder.name = "GraphicalObjectHolder"; - graphicalHolder.SetParent(transform); - graphicalHolder.localPosition = _graphicalInstantiatedOffsetPosition; - graphicalHolder.localRotation = _graphicalInstantiatedOffsetRotation; - graphicalHolder.localScale = _graphicalObject.localScale; - _graphicalObject.SetParent(graphicalHolder); - _graphicalObject.localPosition = Vector3.zero; - _graphicalObject.localRotation = Quaternion.identity; - _graphicalObject.localScale = Vector3.one; - SetGraphicalObject(graphicalHolder); - } - } - } - - /// - /// Called after a tick occurs; physics would have simulated if using PhysicsMode.TimeManager. - /// - private void Rigidbodies_TimeManager_OnPostTick() - { - if (!IsRigidbodyPrediction) - return; - if (base.IsServer) - return; - - bool is2D = (_predictionType == PredictionType.Rigidbody2D); - TrySetCollisionExited(is2D); - - /* Can check either one. They may not be initialized yet if host. */ - if (_rigidbodyStates.Initialized) - { - if (_localTick == 0) - _localTick = base.TimeManager.LocalTick; - - if (!is2D) - _rigidbodyStates.Add(new RigidbodyState(_rigidbody, _localTick)); - else - _rigidbody2dStates.Add(new Rigidbody2DState(_rigidbody2d, _localTick)); - } - - if (CanPredict()) - { - UpdateSpectatorSmoothing(); - if (!is2D) - PredictVelocity(gameObject.scene.GetPhysicsScene()); - else - PredictVelocity(gameObject.scene.GetPhysicsScene2D()); - } - } - - /// - /// Unsets collision values if collision was known to be entered but there are no longer any contact points. - /// - private void TrySetCollisionExited(bool is2d) - { - /* If this object is no longer - * colliding with local client objects - * then unset collision. - * This is done here instead of using - * OnCollisionExit because often collisionexit - * will be missed due to ignored ticks. - * While not ignoring ticks is always an option - * its not ideal because ignoring ticks helps - * prevent over predicting. */ - if (_collisionStayedTick != 0 && (base.TimeManager.LocalTick != _collisionStayedTick)) - CollisionExited(); - } - - /// - /// Called before performing a reconcile on NetworkBehaviour. - /// - private void Rigidbodies_TimeManager_OnPreReconcile(NetworkBehaviour nb) - { - /* Exit if owner and implements prediction methods - * because csp would be handled by prediction methods - * rather than predicted object. */ - if (IsPredictingOwner()) - return; - if (nb.gameObject == gameObject) - return; - if (!IsRigidbodyPrediction) - return; - - bool is2D = (_predictionType == PredictionType.Rigidbody2D); - uint lastNbTick = nb.GetLastReconcileTick(); - int stateIndex = GetCachedStateIndex(lastNbTick, is2D); - - /* If running again on the same reconcile or state is for a different - * tick then do make RBs kinematic. Resetting to a different state - * could cause a desync and there's no reason to run the same - * tick twice. */ - if (stateIndex == -1) - { - _spectatorSmoother?.SetLocalReconcileTick(-1); - _rigidbodyPauser.Pause(); - } - //If state was found then reset to it. - else - { - _spectatorSmoother?.SetLocalReconcileTick(lastNbTick); - if (is2D) - { - _rigidbody2dStates.RemoveRange(true, stateIndex); - ResetRigidbody2DToData(_rigidbody2dStates[0]); - } - else - { - _rigidbodyStates.RemoveRange(true, stateIndex); - ResetRigidbodyToData(_rigidbodyStates[0]); - } - } - } - - /// - /// Called after performing a reconcile on NetworkBehaviour. - /// - private void Rigidbodies_TimeManager_OnPostReconcile(NetworkBehaviour nb) - { - _rigidbodyPauser.Unpause(); - } - - /// - /// Called before physics is simulated when replaying a replicate method. - /// Contains the PhysicsScene and PhysicsScene2D which was simulated. - /// - private void Rigidbodies_PredictionManager_OnPreReplicateReplay(uint tick, PhysicsScene ps, PhysicsScene2D ps2d) - { - if (!CanPredict()) - return; - - //if (_localTick - tick < _ignoredTicks) - // _rigidbodyPauser.Pause(); - - if (_predictionType == PredictionType.Rigidbody) - { - _preReplicateReplayCacheIndex = GetCachedStateIndex(tick, false); - if (_preReplicateReplayCacheIndex != -1) - { - bool prevKinematic = _rigidbodyStates[_preReplicateReplayCacheIndex].IsKinematic; - _rigidbody.isKinematic = prevKinematic; - } - PredictVelocity(ps); - } - else if (_predictionType == PredictionType.Rigidbody2D) - { - _preReplicateReplayCacheIndex = GetCachedStateIndex(tick, true); - if (_preReplicateReplayCacheIndex != -1) - { - bool prevSimulated = _rigidbody2dStates[_preReplicateReplayCacheIndex].Simulated; - _rigidbody2d.simulated = prevSimulated; - _rigidbody2d.isKinematic = !prevSimulated; - } - PredictVelocity(ps2d); - } - } - - /// - /// Called before physics is simulated when replaying a replicate method. - /// Contains the PhysicsScene and PhysicsScene2D which was simulated. - /// - private void Rigidbodies_PredictionManager_OnPostReplicateReplay(uint tick, PhysicsScene ps, PhysicsScene2D ps2d) - { - if (!CanPredict()) - return; - if (_rigidbodyPauser.Paused) - return; - - if (_predictionType == PredictionType.Rigidbody) - { - int index = _preReplicateReplayCacheIndex; - if (index != -1) - { - bool prevKinematic = _rigidbodyStates[index].IsKinematic; - _rigidbodyStates[index] = new RigidbodyState(_rigidbody, prevKinematic, tick); - } - } - if (_predictionType == PredictionType.Rigidbody2D) - { - int index = GetCachedStateIndex(tick, true); - if (index != -1) - { - bool prevSimulated = _rigidbody2dStates[index].Simulated; - _rigidbody2dStates[index] = new Rigidbody2DState(_rigidbody2d, prevSimulated, tick); - } - } - } - - /// - /// Pauses corrections as a spectator object. - /// - public void SetPauseSpectatorCorrections_Experimental(bool pause) - { - _spectatorPaused = pause; - if (pause) - { - _rigidbodyStates.Clear(); - _rigidbody2dStates.Clear(); - } - } - - /// - /// Called when ping updates for the local client. - /// - private void Rigidbodies_OnRoundTripTimeUpdated(long ping) - { - /* Only update periodically when ping changes. - * This is to prevent excessive interpolation - * changes. */ - ulong difference = (ulong)Mathf.Abs(ping - _lastPing); - //Allow update if ping jump is large enough. - if (difference < 50) - { - uint tickInterval = base.TimeManager.TimeToTicks(5f, Managing.Timing.TickRounding.RoundUp); - if (base.TimeManager.LocalTick - _lastPingUpdateTick < tickInterval) - return; - } - SetTargetSmoothing(ping, false); - } - /// - /// Sets target smoothing values. - /// - /// True to set current values to targets immediately. - private void SetTargetSmoothing(long ping, bool setImmediately) - { - if (_spectatorSmoother == null) - return; - - _lastPingUpdateTick = base.TimeManager.LocalTick; - _lastPing = ping; - SetValues(); - //Ignored ticks will be less for predicted spawner. - //if (base.NetworkObject.PredictedSpawner.IsLocalClient) - // _ignoredTicks /= 2; - - //_igtt = _ignoredTicks; - //_ignoredTicks = 0; - //if (base.Owner.IsValid && (base.Owner != base.NetworkObject.PredictedSpawner)) - //{ - // _ignoredTicks *= 4; - // if (gameObject.name.Contains("Bullet")) - // Debug.Log("Setting to " + _ignoredTicks); - //} - //if (base.Owner.IsValid && (base.Owner == base.NetworkObject.PredictedSpawner))// base.IsOwner) - // _ignoredTicks = 0; - - //_spectatorSmoother.SetIgnoredTicks(_ignoredTicks); - - //If to apply values to targets immediately. - if (setImmediately) - { - _currentSpectatorInterpolation = (CollidingWithLocalClient()) ? _targetCollisionSpectatorInterpolation : _targetSpectatorInterpolation; - _spectatorSmoother.SetInterpolation((uint)_currentSpectatorInterpolation); - } - - //Sets ranges to use based on smoothing type. - void SetValues() - { - SmoothingData data; - if (_spectatorSmoothingType == SpectatorSmoothingType.Accuracy) - data = _accurateSmoothingData; - else if (_spectatorSmoothingType == SpectatorSmoothingType.Mixed) - data = _mixedSmoothingData; - else if (_spectatorSmoothingType == SpectatorSmoothingType.Gradual) - data = _gradualSmoothingData; - else - data = _customSmoothingData; - - TimeManager tm = base.TimeManager; - double interpolationTime = (ping / 1000d) * data.InterpolationPercent; - _targetSpectatorInterpolation = tm.TimeToTicks(interpolationTime, TickRounding.RoundUp); - double collisionInterpolationTime = (ping / 1000d) * data.CollisionInterpolationPercent; - _targetCollisionSpectatorInterpolation = tm.TimeToTicks(collisionInterpolationTime, TickRounding.RoundUp); - - _interpolationDecreaseStep = data.InterpolationDecreaseStep; - _interpolationIncreaseStep = data.InterpolationIncreaseStep; - } - } - - /// - /// Returns if this object is colliding with any local client objects. - /// - /// - private bool CollidingWithLocalClient() - { - /* If it's been more than 1 tick since collision stayed - * then do not consider as collided. */ - return (base.TimeManager.LocalTick - _collisionStayedTick) < 1; - } - - private uint _igtt; - /// - /// Updates spectator smoothing values to move towards their targets. - /// - private void UpdateSpectatorSmoothing() - { - bool colliding = CollidingWithLocalClient(); - if (colliding) - _currentSpectatorInterpolation -= _interpolationDecreaseStep; - else - _currentSpectatorInterpolation += _interpolationIncreaseStep; - - _currentSpectatorInterpolation = (long)Mathf.Clamp(_currentSpectatorInterpolation, _targetCollisionSpectatorInterpolation, _targetSpectatorInterpolation); - _spectatorSmoother.SetInterpolation((uint)_currentSpectatorInterpolation); - } - - /// - /// Called when a collision occurs and the smoothing type must perform operations. - /// - private bool CollisionEnteredLocalClientObject(GameObject go) - { - if (go.TryGetComponent(out NetworkObject nob)) - return nob.Owner.IsLocalClient; - - //Fall through. - return false; - } - - /// - /// Sends the rigidbodies state to Observers of a NetworkBehaviour. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void SendRigidbodyState(NetworkBehaviour nb) - { - NetworkConnection owner = nb.Owner; - if (!owner.IsActive) - return; - NetworkManager nm = nb.NetworkManager; - if (nm == null) - return; - - uint tick = nb.GetLastReplicateTick(); - TrySendRigidbodyState(nb, tick); - } - - /// - /// Send current state to a connection. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void TrySendRigidbodyState(NetworkBehaviour nb, uint tick) - { - if (!IsRigidbodyPrediction) - return; - NetworkConnection nbOwner = nb.Owner; - //No need to send to self unless doesnt implement prediction methods. - if (_isPredictingOwner(nbOwner)) - return; - //If clientHost. - if (nbOwner.IsLocalClient) - return; - /* Not an observer. SendTargetRpc normally - * already checks this when ValidateTarget - * is true but we want to save perf by exiting - * early before checks and serialization when - * we know the conn is not an observer. */ - if (!base.Observers.Contains(nbOwner)) - return; - - bool hasChanged = base.TransformMayChange(); - if (!hasChanged) - { - //Not changed but was previous tick. Reset resends. - if (_previouslyChanged) - _resendsRemaining = base.TimeManager.TickRate; - - uint currentTick = base.TimeManager.Tick; - //Resends remain. - if (_resendsRemaining > 0) - { - _resendsRemaining--; - //If now 0 then update next send interval. - if (_resendsRemaining == 0) - UpdateNextIntervalResend(); - } - //No more resends. - else - { - //No resend interval. - if (_resendType == ResendType.Disabled) - return; - //Interval not yet met. - if (currentTick < _nextIntervalResend) - return; - - UpdateNextIntervalResend(); - } - - //Updates the next tick when a resend should occur. - void UpdateNextIntervalResend() - { - _nextIntervalResend = (currentTick + _resendInterval); - } - - } - _previouslyChanged = hasChanged; - - if (_predictionType == PredictionType.Rigidbody) - SendRigidbodyState(tick, nbOwner, false); - else - SendRigidbody2DState(tick, nbOwner, false); - } - - /// - /// Gets a cached state index in actual array position. - /// - /// - private int GetCachedStateIndex(uint tick, bool is2d) - { - int count; - uint firstTick; - //3d. - if (!is2d) - { - count = _rigidbodyStates.Count; - if (count == 0) - return -1; - firstTick = _rigidbodyStates[0].LocalTick; - } - //2d. - else - { - count = _rigidbody2dStates.Count; - if (count == 0) - return -1; - firstTick = _rigidbody2dStates[0].LocalTick; - } - - //First tick is higher than current, no match is possibloe. - if (firstTick > tick) - return -1; - - long difference = (tick - firstTick); - //Desired tick would be out of bounds. This should never happen. - if (difference >= count) - return -1; - - return (int)difference; - } - - - /// - /// Tries to predict velocity for a Vector3. - /// - protected bool PredictVector3Velocity(ref float? velocityBaseline, ref Vector3 lastVelocity, Vector3 velocity, out Vector3 result) - { - float velocityDifference; - float directionDifference; - - /* Velocity. */ - directionDifference = (velocityBaseline != null) ? - Vector3.SqrMagnitude(lastVelocity.normalized - velocity.normalized) : - 0f; - //If direction has changed too much then reset the baseline. - if (directionDifference > 0.01f) - { - velocityBaseline = null; - } - //Direction hasn't changed enough to reset baseline. - else - { - //Difference in velocity since last simulation. - velocityDifference = Vector3.Magnitude(lastVelocity - velocity); - //If there is no baseline. - if (velocityBaseline == null) - { - if (velocityDifference > 0) - velocityBaseline = velocityDifference; - } - //If there is a baseline. - else - { - //If the difference exceeds the baseline by 10% then reset baseline so another will be calculated. - if (velocityDifference > (velocityBaseline.Value * 1.1f) || velocityDifference < (velocityBaseline.Value * 0.9f)) - { - velocityBaseline = null; - } - //Velocity difference is close enough to the baseline to where it doesn't need to be reset, so use prediction. - else - { - Vector3 changeMultiplied = (velocity - lastVelocity) * _maintainedVelocity; - //Retaining velocity. - if (_maintainedVelocity > 0f) - { - result = (velocity + changeMultiplied); - } - //Reducing velocity. - else - { - result = (velocity + changeMultiplied); - /* When reducing velocity make sure the direction - * did not change. When this occurs it means the velocity - * was reduced into the opposite direction. To prevent - * this from happening just zero out velocity instead. */ - if (velocity.normalized != result.normalized) - result = Vector3.zero; - } - return true; - } - } - } - - //Fall through. - result = Vector3.zero; - return false; - } - - - /// - /// Tries to predict velocity for a float. - /// - private bool PredictFloatVelocity(ref float? velocityBaseline, ref float lastVelocity, float velocity, out float result) - { - float velocityDifference; - float directionDifference; - - /* Velocity. */ - directionDifference = (velocityBaseline != null) ? (velocity - lastVelocity) : 0f; - - //If direction has changed too much then reset the baseline. - if (directionDifference > 0.01f) - { - velocityBaseline = null; - } - //Direction hasn't changed enough to reset baseline. - else - { - //Difference in velocity since last simulation. - velocityDifference = Mathf.Abs(lastVelocity - velocity); - //If there is no baseline. - if (velocityBaseline == null) - { - if (velocityDifference > 0) - velocityBaseline = velocityDifference; - } - //If there is a baseline. - else - { - //If the difference exceeds the baseline by 10% then reset baseline so another will be calculated. - if (velocityDifference > (velocityBaseline.Value * 1.1f) || velocityDifference < (velocityBaseline.Value * 0.9f)) - { - velocityBaseline = null; - } - //Velocity difference is close enough to the baseline to where it doesn't need to be reset, so use prediction. - else - { - float changeMultiplied = (velocity - lastVelocity) * _maintainedVelocity; - //Retaining velocity. - if (_maintainedVelocity > 0f) - { - result = (velocity + changeMultiplied); - } - //Reducing velocity. - else - { - result = (velocity + changeMultiplied); - /* When reducing velocity make sure the direction - * did not change. When this occurs it means the velocity - * was reduced into the opposite direction. To prevent - * this from happening just zero out velocity instead. */ - if (Mathf.Abs(velocity) != Mathf.Abs(result)) - result = 0f; - } - return true; - } - } - } - - //Fall through. - result = 0f; - return false; - } - - /// - /// Returns if prediction can be used on this rigidbody. - /// - /// - private bool CanPredict() - { - if (!IsRigidbodyPrediction) - return false; - if (base.IsServer || IsPredictingOwner()) - return false; - if (_spectatorPaused) - return false; - - return true; - } - #endregion - - #region Rigidbody. - #region Private. - /// - /// Past RigidbodyStates. - /// - private RingBuffer _rigidbodyStates = new RingBuffer(); - /// - /// Velocity from previous simulation. - /// - private Vector3 _lastVelocity; - /// - /// Angular velocity from previous simulation. - /// - private Vector3 _lastAngularVelocity; - /// - /// Baseline for velocity magnitude. - /// - private float? _velocityBaseline; - /// - /// Baseline for angular velocity magnitude. - /// - private float? _angularVelocityBaseline; - /// - /// PhysicsScene for this object when OnPreReconcile is called. - /// - private PhysicsScene _physicsScene; - #endregion - - private void OnCollisionEnter(Collision collision) - { - if (_predictionType != PredictionType.Rigidbody) - return; - - GameObject go = collision.gameObject; - if (CollisionEnteredLocalClientObject(go)) - CollisionEntered(go); - } - - - private void OnCollisionStay(Collision collision) - { - if (_predictionType != PredictionType.Rigidbody) - return; - - if (_localClientCollidedObjects.Contains(collision.gameObject)) - _collisionStayedTick = base.TimeManager.LocalTick; - } - - /// - /// Resets the rigidbody to a state. - /// - private void ResetRigidbodyToData(RigidbodyState state) - { - //Update transform and rigidbody. - _rigidbody.transform.position = state.Position; - _rigidbody.transform.rotation = state.Rotation; - bool isKinematic = state.IsKinematic; - _rigidbody.isKinematic = isKinematic; - if (!isKinematic) - { - _rigidbody.velocity = state.Velocity; - _rigidbody.angularVelocity = state.AngularVelocity; - } - - /* Do not need to sync transforms because it's done internally by the reconcile method. - * That is, so long as this is called using OnPreReconcile. */ - - //Set prediction defaults. - _velocityBaseline = null; - _angularVelocityBaseline = null; - _lastVelocity = _rigidbody.velocity; - _lastAngularVelocity = _rigidbody.angularVelocity; - } - - /// - /// Sets the next predicted velocity on the rigidbody. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void PredictVelocity(PhysicsScene ps) - { - if (_maintainedVelocity == 0f) - return; - if (ps != _physicsScene) - return; - - Vector3 result; - if (PredictVector3Velocity(ref _velocityBaseline, ref _lastVelocity, _rigidbody.velocity, out result)) - _rigidbody.velocity = result; - if (PredictVector3Velocity(ref _angularVelocityBaseline, ref _lastAngularVelocity, _rigidbody.angularVelocity, out result)) - _rigidbody.angularVelocity = result; - - _lastVelocity = _rigidbody.velocity; - _lastAngularVelocity = _rigidbody.angularVelocity; - } - - - /// - /// Sends current states of this object to client. - /// - private void SendRigidbodyState(uint reconcileTick, NetworkConnection conn, bool applyImmediately) - { - //No need to send to owner if they implement prediction methods. - if (_isPredictingOwner(conn)) - return; - reconcileTick = (conn == base.NetworkObject.PredictedSpawner) ? conn.LastPacketTick : reconcileTick; - RigidbodyState state = new RigidbodyState(_rigidbody, reconcileTick); - TargetSendRigidbodyState(conn, state, applyImmediately); - } - - /// - /// Sends transform and rigidbody state to spectators. - /// - [TargetRpc(ValidateTarget = false)] - private void TargetSendRigidbodyState(NetworkConnection c, RigidbodyState state, bool applyImmediately, Channel channel = Channel.Unreliable) - { - if (!CanPredict()) - return; - - uint localTick = state.LocalTick; - if (applyImmediately) - { - /* If PredictedSpawner is self then this client - * was the one to predicted spawn this object. When that is - * the case do not apply initial velocities, but so allow - * regular updates/corrections. */ - if (base.NetworkObject.PredictedSpawner.IsLocalClient) - return; - } - else - { - if (!CanProcessReceivedState(localTick)) - return; - } - - if (applyImmediately) - { - _rigidbodyStates.Clear(); - ResetRigidbodyToData(state); - } - else - { - int index = GetCachedStateIndex(localTick, false); - if (index != -1) - _rigidbodyStates[index] = state; - else - _rigidbodyStates.Add(state); - } - } - #endregion - - #region Rigidbody2D. - #region Private. - /// - /// Past RigidbodyStates. - /// - private RingBuffer _rigidbody2dStates = new RingBuffer(); - /// - /// Velocity from previous simulation. - /// - private Vector3 _lastVelocity2D; - /// - /// Angular velocity from previous simulation. - /// - private float _lastAngularVelocity2D; - /// - /// Baseline for velocity magnitude. - /// - private float? _velocityBaseline2D; - /// - /// Baseline for angular velocity magnitude. - /// - private float? _angularVelocityBaseline2D; - /// - /// PhysicsScene for this object when OnPreReconcile is called. - /// - private PhysicsScene2D _physicsScene2D; - /// - /// Last found cacheIndex during PreReplay. - /// - private int _preReplicateReplayCacheIndex; - /// - /// Last tick a ping update was received. - /// - private uint _lastPingUpdateTick; - /// - /// Last ping during a ping update. - /// - private long _lastPing; - #endregion - - private void OnCollisionEnter2D(Collision2D collision) - { - if (_predictionType != PredictionType.Rigidbody2D) - return; - - GameObject go = collision.gameObject; - if (CollisionEnteredLocalClientObject(go)) - CollisionEntered(go); - } - - private void OnCollisionStay2D(Collision2D collision) - { - if (_predictionType != PredictionType.Rigidbody2D) - return; - - if (_localClientCollidedObjects.Contains(collision.gameObject)) - _collisionStayedTick = base.TimeManager.LocalTick; - } - - /// - /// Called when collision has entered a local clients object. - /// - private void CollisionEntered(GameObject go) - { - _collisionStayedTick = base.TimeManager.LocalTick; - _localClientCollidedObjects.Add(go); - } - - /// - /// Called when collision has exited a local clients object. - /// - private void CollisionExited() - { - _localClientCollidedObjects.Clear(); - _collisionStayedTick = 0; - } - - /// - /// Resets the Rigidbody2D to last received data. - /// - private void ResetRigidbody2DToData(Rigidbody2DState state) - { - //Update transform and rigidbody. - _rigidbody2d.transform.position = state.Position; - _rigidbody2d.transform.rotation = state.Rotation; - bool simulated = state.Simulated; - _rigidbody2d.simulated = simulated; - _rigidbody2d.isKinematic = !simulated; - if (simulated) - { - _rigidbody2d.velocity = state.Velocity; - _rigidbody2d.angularVelocity = state.AngularVelocity; - } - - /* Do not need to sync transforms because it's done internally by the reconcile method. - * That is, so long as this is called using OnPreReconcile. */ - - //Set prediction defaults. - _velocityBaseline2D = null; - _angularVelocityBaseline2D = null; - _lastVelocity2D = _rigidbody2d.velocity; - _lastAngularVelocity2D = _rigidbody2d.angularVelocity; - } - - /// - /// Sets the next predicted velocity on the rigidbody. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void PredictVelocity(PhysicsScene2D ps) - { - if (_maintainedVelocity == 0f) - return; - if (ps != _physicsScene2D) - return; - - Vector3 v3Result; - if (PredictVector3Velocity(ref _velocityBaseline2D, ref _lastVelocity2D, _rigidbody2d.velocity, out v3Result)) - _rigidbody2d.velocity = v3Result; - float floatResult; - if (PredictFloatVelocity(ref _angularVelocityBaseline2D, ref _lastAngularVelocity2D, _rigidbody2d.angularVelocity, out floatResult)) - _rigidbody2d.angularVelocity = floatResult; - - _lastVelocity2D = _rigidbody2d.velocity; - _lastAngularVelocity2D = _rigidbody2d.angularVelocity; - } - - - /// - /// Sends current Rigidbody2D state to a connection. - /// - private void SendRigidbody2DState(uint reconcileTick, NetworkConnection conn, bool applyImmediately) - { - Rigidbody2DState state = new Rigidbody2DState(_rigidbody2d, reconcileTick); - TargetSendRigidbody2DState(conn, state, applyImmediately); - } - - /// - /// Sends transform and rigidbody state to spectators. - /// - [TargetRpc(ValidateTarget = false)] - private void TargetSendRigidbody2DState(NetworkConnection c, Rigidbody2DState state, bool applyImmediately, Channel channel = Channel.Unreliable) - { - if (!CanPredict()) - return; - - uint localTick = state.LocalTick; - if (applyImmediately) - { - /* If PredictedSpawner is self then this client - * was the one to predicted spawn this object. When that is - * the case do not apply initial velocities, but so allow - * regular updates/corrections. */ - if (base.NetworkObject.PredictedSpawner.IsLocalClient) - return; - } - else - { - if (!CanProcessReceivedState(localTick)) - return; - } - - if (applyImmediately) - { - _rigidbody2dStates.Clear(); - ResetRigidbody2DToData(state); - } - else - { - int index = GetCachedStateIndex(localTick, true); - if (index != -1) - _rigidbody2dStates[index] = state; - else - _rigidbody2dStates.Add(state); - } - - - } - - /// - /// Returns if a received state can be processed based on it's tick. - /// - /// - /// - private bool CanProcessReceivedState(uint stateTick) - { - //Older than another received value. - if (stateTick <= _lastStateLocalTick) - return false; - _lastStateLocalTick = stateTick; - - return true; - } - #endregion - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.Rigidbodies.cs.meta b/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.Rigidbodies.cs.meta deleted file mode 100644 index 0d5f06d..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.Rigidbodies.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6bd787cd0da2e9e4ab4bd30794ff0082 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.cs b/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.cs deleted file mode 100644 index bdf3ff5..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.cs +++ /dev/null @@ -1,605 +0,0 @@ -using FishNet.Component.Transforming; -using FishNet.Utility.Extension; -using FishNet.Connection; -using FishNet.Managing; -using FishNet.Object; -using System; -using UnityEngine; - -namespace FishNet.Component.Prediction -{ - [AddComponentMenu("FishNet/Component/PredictedObject")] - public partial class PredictedObject : NetworkBehaviour - { - #region Types. - /// - /// How to favor smoothing for predicted objects. - /// - public enum SpectatorSmoothingType - { - /// - /// Favor accurate collisions. With fast moving objects this may result in some jitter with higher latencies. - /// - Accuracy = 0, - /// - /// A mix between Accuracy and Smoothness. - /// - Mixed = 1, - /// - /// Prefer smooth movement and corrections. Fast moving objects may collide before the graphical representation catches up. - /// - Gradual = 2, - /// - /// Configure values to your preference. - /// - Custom = 3, - } - /// - /// State of this object in a collision. - /// - private enum CollectionState : byte - { - Unset = 0, - Added = 1, - Removed = 2, - } - /// - /// Type of prediction movement being used. - /// - internal enum PredictionType : byte - { - Other = 0, - Rigidbody = 1, - Rigidbody2D = 2 - } - internal enum ResendType : byte - { - Disabled = 0, - Interval = 1, - } - #endregion - - #region Public. - /// - /// True if the prediction type is for a rigidbody. - /// - public bool IsRigidbodyPrediction => (_predictionType == PredictionType.Rigidbody || _predictionType == PredictionType.Rigidbody2D); - #endregion - - #region Serialized. - /// - /// True if this object implements replicate and reconcile methods. - /// - [Tooltip("True if this object implements replicate and reconcile methods.")] - [SerializeField] - private bool _implementsPredictionMethods = true; - /// - /// Transform which holds the graphical features of this object. This transform will be smoothed when desynchronizations occur. - /// - [Tooltip("Transform which holds the graphical features of this object. This transform will be smoothed when desynchronizations occur.")] - [SerializeField] - private Transform _graphicalObject; - /// - /// Gets GraphicalObject. - /// - public Transform GetGraphicalObject() => _graphicalObject; - /// - /// Sets GraphicalObject. - /// - /// - public void SetGraphicalObject(Transform value) - { - _graphicalObject = value; - SetInstantiatedOffsetValues(); - _spectatorSmoother?.SetGraphicalObject(value); - _ownerSmoother?.SetGraphicalObject(value); - } - /// - /// True to enable teleport threshhold. - /// - [Tooltip("True to enable teleport threshhold.")] - [SerializeField] - private bool _enableTeleport; - /// - /// How far the transform must travel in a single update to cause a teleport rather than smoothing. Using 0f will teleport every update. - /// - [Tooltip("How far the transform must travel in a single update to cause a teleport rather than smoothing. Using 0f will teleport every update.")] - [Range(0f, 200f)] //Unity bug? Values ~over 200f lose decimal display within inspector. - [SerializeField] - private float _teleportThreshold = 1f; - /// - /// Gets the value for SmoothTicks. - /// - /// - [Obsolete("No longer used. This setting has been replaced by Smoothing Type.")]//Remove on 2023/06/01 - public bool GetSmoothTicks() => true; - /// - /// Sets the value for SmoothTicks. - /// - /// - /// - [Obsolete("No longer used. This setting has been replaced by Smoothing Type.")] //Remove on 2023/06/01 - public void SetSmoothTicks(bool value) { } - /// - /// True to smooth position on owner objects. - /// - [Tooltip("True to smooth position on owner objects.")] - [SerializeField] - private bool _ownerSmoothPosition = true; - /// - /// True to smooth rotation on owner objects. - /// - [Tooltip("True to smooth rotation on owner objects.")] - [SerializeField] - private bool _ownerSmoothRotation = true; - /// - /// How far in the past to keep the graphical object when owner. Using a value of 0 will disable interpolation. - /// - [Tooltip("How far in the past to keep the graphical object when owner. Using a value of 0 will disable interpolation.")] - [Range(0, 255)] - [SerializeField] - private byte _ownerInterpolation = 1; - /// - /// Gets the iterpolation value to use when the owner of this object. - /// - /// True to get the interpolation for when owner, false to get the interpolation for when a spectator. - [Obsolete("No longer used. This setting has been replaced by Smoothing Type.")]//Remove on 2023/06/01 - public byte GetInterpolation(bool asOwner) => 0; - /// - /// Sets the interpolation value to use when the owner of this object. - /// - /// - /// True to set the interpolation for when owner, false to set interpolation for when a spectator. - [Obsolete("No longer used. This setting has been replaced by Smoothing Type.")]//Remove on 2023/06/01 - public void SetInterpolation(byte value, bool asOwner) - { - //if (asOwner) - //{ - // _ownerInterpolation = value; - // _ownerSmoother?.SetInterpolation(value); - //} - //else - //{ - // _spectatorInterpolation = value; - // _spectatorSmoother?.SetInterpolation(value); - //} - } - /// - /// Type of prediction movement which is being used. - /// - [Tooltip("Type of prediction movement which is being used.")] - [SerializeField] - private PredictionType _predictionType; - /// - /// Rigidbody to predict. - /// - [Tooltip("Rigidbody to predict.")] - [SerializeField] - private Rigidbody _rigidbody; - /// - /// Rigidbody2D to predict. - /// - [Tooltip("Rigidbody2D to predict.")] - [SerializeField] - private Rigidbody2D _rigidbody2d; - /// - /// True to smooth position on spectated objects. - /// - [Tooltip("True to smooth position on spectated objects.")] - [SerializeField] - private bool _spectatorSmoothPosition = true; - /// - /// True to smooth rotation on spectated objects. - /// - [Tooltip("True to smooth rotation on spectated objects.")] - [SerializeField] - private bool _spectatorSmoothRotation = true; - /// - /// How to favor smoothing for predicted objects. - /// - [Tooltip("How to favor smoothing for predicted objects.")] - [SerializeField] - private SpectatorSmoothingType _spectatorSmoothingType = SpectatorSmoothingType.Mixed; - /// - /// Custom settings for smoothing data. - /// - [Tooltip("Custom settings for smoothing data.")] - [SerializeField] - private SmoothingData _customSmoothingData = _mixedSmoothingData; - /// - /// Preview of selected preconfigured smoothing data. This is only used for the inspector. - /// - [SerializeField] - private SmoothingData _preconfiguredSmoothingDataPreview = _mixedSmoothingData; - /// - /// Sets SpectactorSmoothingType value. - /// - /// Value to use. - public void SetSpectatorSmoothingType(SpectatorSmoothingType value) - { - if (base.IsSpawned) - base.NetworkManager.LogWarning($"Spectator smoothing type may only be set before the object is spawned, such as after instantiating but before spawning."); - else - _spectatorSmoothingType = value; - } - - ///// - ///// How far in the past to keep the graphical object when not owner. Using a value of 0 will disable interpolation. - ///// - //[Tooltip("How far in the past to keep the graphical object when not owner. Using a value of 0 will disable interpolation.")] - //[Range(0, 255)] - //[SerializeField] - //private byte _spectatorInterpolation = 4; - ///// - ///// Multiplier to apply to movement speed when buffer is over interpolation. - ///// - //[Tooltip("Multiplier to apply to movement speed when buffer is over interpolation.")] - //[Range(0f, 5f)] - //[SerializeField] - //private float _overflowMultiplier = 0.1f; - /// - /// Multiplier applied to difference in velocity between ticks. - /// Positive values will result in more velocity while lowers will result in less. - /// A value of 1f will prevent any velocity from being lost between ticks, unless indicated by the server. - /// - [Tooltip("Multiplier applied to difference in velocity between ticks. Positive values will result in more velocity while lowers will result in less. A value of 1f will prevent any velocity from being lost between ticks, unless indicated by the server.")] - [Range(-10f, 10f)] - [SerializeField] - private float _maintainedVelocity = 0f; - /// - /// How often to resend current values regardless if the state has changed. Using this value will consume more bandwidth but may be preferred if you want to force synchronization the object move on the client but not on the server. - /// - [Tooltip("How often to resend current values regardless if the state has changed. Using this value will consume more bandwidth but may be preferred if you want to force synchronization the object move on the client but not on the server.")] - [SerializeField] - private ResendType _resendType = ResendType.Disabled; - /// - /// How often in ticks to resend values. - /// - [Tooltip("How often in ticks to resend values.")] - [SerializeField] - private ushort _resendInterval = 30; - /// - /// NetworkTransform to configure. - /// - [Tooltip("NetworkTransform to configure.")] - [SerializeField] - private NetworkTransform _networkTransform; - #endregion - - #region Private. - /// - /// True if client subscribed to events. - /// - private bool _clientSubscribed; - /// - /// True if this PredictedObject has been registered with the PredictionManager. - /// - private bool _registered; - /// - /// GraphicalObject position difference from this object when this is instantiated. - /// - private Vector3 _graphicalInstantiatedOffsetPosition; - /// - /// GraphicalObject rotation difference from this object when this is instantiated. - /// - private Quaternion _graphicalInstantiatedOffsetRotation; - /// - /// Cached localtick for performance. - /// - private uint _localTick; - /// - /// Smoothing component for this object when not owner. - /// - private PredictedObjectSpectatorSmoother _spectatorSmoother; - /// - /// Smoothing component for this object when owner. - /// This component is also used for non-owned objects when as server. - /// - private PredictedObjectOwnerSmoother _ownerSmoother; - #endregion - - private void Awake() - { - SetInstantiatedOffsetValues(); - } - - public override void OnStartNetwork() - { - base.OnStartNetwork(); - - /* If host then initialize owner smoother. - * Host will use owner smoothing settings for more - * accurate results. */ - if (base.IsHost) - InitializeSmoother(true); - - UpdateRigidbodiesCount(true); - ConfigureRigidbodies(); - ConfigureNetworkTransform(); - base.TimeManager.OnPostTick += TimeManager_OnPostTick; - } - - public override void OnSpawnServer(NetworkConnection connection) - { - base.OnSpawnServer(connection); - Rigidbodies_OnSpawnServer(connection); - } - - public override void OnStartClient() - { - base.OnStartClient(); - ChangeSubscriptions(true); - Rigidbodies_OnStartClient(); - } - - public override void OnOwnershipClient(NetworkConnection prevOwner) - { - base.OnOwnershipClient(prevOwner); - /* If owner or host then use the - * owner smoother. The owner smoother - * is not predictive and is preferred - * for more real time graphical results. */ - if (base.IsOwner && !base.IsServer) - { - /* If has prediction methods implement for owner, - * otherwise implement for spectator. */ - InitializeSmoother(_implementsPredictionMethods); - /* Also set spectator smoothing if does not implement - * prediction methods as the spectator smoother is used - * for these scenarios. */ - if (!_implementsPredictionMethods) - SetTargetSmoothing(base.TimeManager.RoundTripTime, true); - } - //Not owner nor server, initialize spectator smoother if using rigidbodies. - else if (_predictionType != PredictionType.Other) - { - InitializeSmoother(false); - SetTargetSmoothing(base.TimeManager.RoundTripTime, true); - } - - Rigidbodies_OnOwnershipClient(prevOwner); - } - - public override void OnStopNetwork() - { - base.OnStopNetwork(); - - ChangeSubscriptions(false); - UpdateRigidbodiesCount(false); - base.TimeManager.OnPostTick -= TimeManager_OnPostTick; - } - - /// - /// Updates Rigidbodies count on the PredictionManager. - /// - /// - private void UpdateRigidbodiesCount(bool add) - { - if (_registered == add) - return; - if (_predictionType == PredictionType.Other) - return; - - NetworkManager nm = base.NetworkManager; - if (nm == null) - return; - - _registered = add; - - if (add) - { - nm.PredictionManager.AddRigidbodyCount(this); - nm.PredictionManager.OnPreServerReconcile += PredictionManager_OnPreServerReconcile; - } - else - { - nm.PredictionManager.RemoveRigidbodyCount(this); - nm.PredictionManager.OnPreServerReconcile -= PredictionManager_OnPreServerReconcile; - } - } - - /// - /// Sets instantiated offset values for the graphical object. - /// - private void SetInstantiatedOffsetValues() - { - transform.SetTransformOffsets(_graphicalObject, ref _graphicalInstantiatedOffsetPosition, ref _graphicalInstantiatedOffsetRotation); - } - - private void TimeManager_OnUpdate() - { - _spectatorSmoother?.ManualUpdate(); - _ownerSmoother?.ManualUpdate(); - } - - private void TimeManager_OnPreTick() - { - _localTick = base.TimeManager.LocalTick; - _spectatorSmoother?.OnPreTick(); - _ownerSmoother?.OnPreTick(); - } - - protected void TimeManager_OnPostTick() - { - _spectatorSmoother?.OnPostTick(); - _ownerSmoother?.OnPostTick(); - Rigidbodies_TimeManager_OnPostTick(); - } - - - /// - /// Subscribes to events needed to function. - /// - /// - private void ChangeSubscriptions(bool subscribe) - { - if (base.TimeManager == null) - return; - if (subscribe == _clientSubscribed) - return; - - if (subscribe) - { - base.TimeManager.OnUpdate += TimeManager_OnUpdate; - base.TimeManager.OnPreTick += TimeManager_OnPreTick; - //Only client will use these events. - if (!base.IsServer) - { - base.PredictionManager.OnPreReplicateReplay += PredictionManager_OnPreReplicateReplay; - base.PredictionManager.OnPostReplicateReplay += PredictionManager_OnPostReplicateReplay; - base.PredictionManager.OnPreReconcile += PredictionManager_OnPreReconcile; - base.PredictionManager.OnPostReconcile += PredictionManager_OnPostReconcile; - base.TimeManager.OnRoundTripTimeUpdated += TimeManager_OnRoundTripTimeUpdated; - } - } - else - { - base.TimeManager.OnUpdate -= TimeManager_OnUpdate; - base.TimeManager.OnPreTick -= TimeManager_OnPreTick; - //Only client will use these events. - if (!base.IsServer) - { - base.PredictionManager.OnPreReplicateReplay -= PredictionManager_OnPreReplicateReplay; - base.PredictionManager.OnPostReplicateReplay -= PredictionManager_OnPostReplicateReplay; - base.PredictionManager.OnPreReconcile -= PredictionManager_OnPreReconcile; - base.PredictionManager.OnPostReconcile -= PredictionManager_OnPostReconcile; - base.TimeManager.OnRoundTripTimeUpdated -= TimeManager_OnRoundTripTimeUpdated; - } - - //Also some resets - _lastStateLocalTick = 0; - _rigidbodyStates.Clear(); - _rigidbody2dStates.Clear(); - } - - _clientSubscribed = subscribe; - } - - private void TimeManager_OnRoundTripTimeUpdated(long obj) - { - Rigidbodies_OnRoundTripTimeUpdated(obj); - } - - private void PredictionManager_OnPreServerReconcile(NetworkBehaviour obj) - { - SendRigidbodyState(obj); - } - - /// - /// Called before physics is simulated when replaying a replicate method. - /// Contains the PhysicsScene and PhysicsScene2D which was simulated. - /// - protected virtual void PredictionManager_OnPreReplicateReplay(uint tick, PhysicsScene ps, PhysicsScene2D ps2d) - { - _spectatorSmoother?.OnPreReplay(tick); - Rigidbodies_PredictionManager_OnPreReplicateReplay(tick, ps, ps2d); - } - - /// - /// Called after physics is simulated when replaying a replicate method. - /// Contains the PhysicsScene and PhysicsScene2D which was simulated. - /// - private void PredictionManager_OnPostReplicateReplay(uint tick, PhysicsScene ps, PhysicsScene2D ps2d) - { - _spectatorSmoother?.OnPostReplay(tick); - Rigidbodies_PredictionManager_OnPostReplicateReplay(tick, ps, ps2d); - } - - /// - /// Called before performing a reconcile on NetworkBehaviour. - /// - private void PredictionManager_OnPreReconcile(NetworkBehaviour nb) - { - Rigidbodies_TimeManager_OnPreReconcile(nb); - } - - /// - /// Called after performing a reconcile on NetworkBehaviour. - /// - private void PredictionManager_OnPostReconcile(NetworkBehaviour nb) - { - Rigidbodies_TimeManager_OnPostReconcile(nb); - } - - /// - /// Initializes a smoother with configured values. - /// - private void InitializeSmoother(bool ownerSmoother) - { - ResetGraphicalTransform(); - - if (ownerSmoother) - { - _ownerSmoother = new PredictedObjectOwnerSmoother(); - float teleportThreshold = (_enableTeleport) ? _teleportThreshold : -1f; - _ownerSmoother.Initialize(this, _graphicalInstantiatedOffsetPosition, _graphicalInstantiatedOffsetRotation, _graphicalObject, _ownerSmoothPosition, _ownerSmoothRotation, _ownerInterpolation, teleportThreshold); - } - else - { - _spectatorSmoother = new PredictedObjectSpectatorSmoother(); - RigidbodyType rbType = (_predictionType == PredictionType.Rigidbody) ? - RigidbodyType.Rigidbody : RigidbodyType.Rigidbody2D; - float teleportThreshold = (_enableTeleport) ? _teleportThreshold : -1f; - _spectatorSmoother.Initialize(this, rbType, _rigidbody, _rigidbody2d, _graphicalObject, _spectatorSmoothPosition, _spectatorSmoothRotation, teleportThreshold); - } - - void ResetGraphicalTransform() - { - _graphicalObject.position = (transform.position + _graphicalInstantiatedOffsetPosition); - _graphicalObject.rotation = (_graphicalInstantiatedOffsetRotation * transform.rotation); - } - } - - /// - /// Configures RigidbodyPauser with settings. - /// - private void ConfigureRigidbodies() - { - if (!IsRigidbodyPrediction) - return; - - _rigidbodyPauser = new RigidbodyPauser(); - if (_predictionType == PredictionType.Rigidbody) - { - _rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous; - _rigidbodyPauser.UpdateRigidbodies(transform, RigidbodyType.Rigidbody, true, _graphicalObject); - } - else - { - _rigidbody2d.collisionDetectionMode = CollisionDetectionMode2D.Continuous; - _rigidbodyPauser.UpdateRigidbodies(transform, RigidbodyType.Rigidbody2D, true, _graphicalObject); - } - } - - /// - /// Configures NetworkTransform for prediction. - /// - private void ConfigureNetworkTransform() - { - if (!IsRigidbodyPrediction) - _networkTransform?.ConfigureForCSP(); - } - - -#if UNITY_EDITOR - protected override void OnValidate() - { - if (Application.isPlaying) - { - InitializeSmoother(true); - } - else - { - if (_spectatorSmoothingType == SpectatorSmoothingType.Accuracy) - _preconfiguredSmoothingDataPreview = _accurateSmoothingData; - else if (_spectatorSmoothingType == SpectatorSmoothingType.Mixed) - _preconfiguredSmoothingDataPreview = _mixedSmoothingData; - else if (_spectatorSmoothingType == SpectatorSmoothingType.Gradual) - _preconfiguredSmoothingDataPreview = _gradualSmoothingData; - } - } -#endif - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.cs.meta b/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.cs.meta deleted file mode 100644 index 82837b8..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObject.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 402926ef33e0a894d9fec352693988ac -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectOwnerSmoother.cs b/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectOwnerSmoother.cs deleted file mode 100644 index dca6196..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectOwnerSmoother.cs +++ /dev/null @@ -1,299 +0,0 @@ -using FishNet.Utility.Extension; -using FishNet.Object; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Component.Prediction -{ - internal class PredictedObjectOwnerSmoother - { - #region Serialized. - /// - /// Transform which holds the graphical features of this object. This transform will be smoothed when desynchronizations occur. - /// - private Transform _graphicalObject; - /// - /// Sets GraphicalObject. - /// - /// - public void SetGraphicalObject(Transform value) - { - _graphicalObject = value; - _networkBehaviour.transform.SetTransformOffsets(value, ref _graphicalInstantiatedOffsetPosition, ref _graphicalInstantiatedOffsetRotation); - } - /// - /// NetworkBehaviour which is using this object. - /// - private NetworkBehaviour _networkBehaviour; - /// - /// How far the transform must travel in a single update to cause a teleport rather than smoothing. Using 0f will teleport every update. - /// - private float _teleportThreshold = 1f; - /// - /// How far in the past to keep the graphical object when owner. - /// - private byte _interpolation = 1; - /// - /// Sets the interpolation value to use when the owner of this object. - /// - /// - public void SetInterpolation(byte value) => _interpolation = value; - #endregion - - #region Private. - /// - /// World position before transform was predicted or reset. - /// - private Vector3 _graphicalStartPosition; - /// - /// World rotation before transform was predicted or reset. - /// - private Quaternion _graphicalStartRotation; - /// - /// GraphicalObject position difference from the PredictedObject when this is initialized. - /// - private Vector3 _graphicalInstantiatedOffsetPosition; - /// - /// How quickly to move towards TargetPosition. - /// - private float _positionMoveRate = -2; - /// - /// GraphicalObject rotation difference from the PredictedObject when this is initialized. - /// - private Quaternion _graphicalInstantiatedOffsetRotation; - /// - /// How quickly to move towards TargetRotation. - /// - private float _rotationMoveRate = -2; - /// - /// True if OnPreTick was received this frame. - /// - private bool _preTickReceived; - /// - /// True to move towards position goals. - /// - private bool _smoothPosition; - /// - /// True to move towards rotation goals. - /// - private bool _smoothRotation; - #endregion - - /// - /// Initializes this script for use. - /// - public void Initialize(NetworkBehaviour nb, Vector3 instantiatedOffsetPosition, Quaternion instantiatedOffsetRotation, Transform graphicalObject - , bool smoothPosition, bool smoothRotation, byte interpolation, float teleportThreshold) - { - _networkBehaviour = nb; - _graphicalInstantiatedOffsetPosition = instantiatedOffsetPosition; - _graphicalInstantiatedOffsetRotation = instantiatedOffsetRotation; - _graphicalObject = graphicalObject; - - _smoothPosition = smoothPosition; - _smoothRotation = smoothRotation; - - _interpolation = interpolation; - _teleportThreshold = teleportThreshold; - } - - /// - /// Called every frame. - /// - public void ManualUpdate() - { - MoveToTarget(); - } - - /// - /// Called when the TimeManager invokes OnPreTick. - /// - public void OnPreTick() - { - if (CanSmooth()) - { - _preTickReceived = true; - /* Only snap to destination if interpolation is 1. - * This ensures the graphics will be at the proper location - * before the next movement rates are calculated. */ - if (_interpolation == 1) - ResetGraphicalToInstantiatedProperties(true, true); - - SetGraphicalPreviousProperties(); - } - } - - public void OnPostTick() - { - if (CanSmooth() && _preTickReceived) - { - _preTickReceived = false; - ResetGraphicalToPreviousProperties(); - SetGraphicalMoveRates(); - } - } - - /// - /// Returns if prediction can be used on this rigidbody. - /// - /// - private bool CanSmooth() - { - if (_interpolation == 0) - return false; - //Only owner needs smoothing. - if (!_networkBehaviour.IsOwner && !_networkBehaviour.IsHost) - return false; - - return true; - } - - /// - /// Moves transform to target values. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void MoveToTarget() - { - //Not set, meaning movement doesnt need to happen or completed. - if (_positionMoveRate == -2f && _rotationMoveRate == -2f) - return; - - Vector3 posGoal = GetGraphicalGoalPosition(); - Quaternion rotGoal = GetGraphicalGoalRotation(); - - /* Only try to update properties if they have a valid move rate. - * Properties may have 0f move rate if they did not change. */ - Transform t = _graphicalObject; - float delta = Time.deltaTime; - - //Position. - if (SmoothPosition()) - { - if (_positionMoveRate == -1f) - ResetGraphicalToInstantiatedProperties(true, false); - else if (_positionMoveRate > 0f) - t.position = Vector3.MoveTowards(t.position, posGoal, _positionMoveRate * delta); - } - - //Rotation. - if (SmoothRotation()) - { - if (_rotationMoveRate == -1f) - ResetGraphicalToInstantiatedProperties(false, true); - else if (_rotationMoveRate > 0f) - t.rotation = Quaternion.RotateTowards(t.rotation, rotGoal, _rotationMoveRate * delta); - } - - if (GraphicalObjectMatches(posGoal, rotGoal)) - { - _positionMoveRate = -2f; - _rotationMoveRate = -2f; - } - } - - /// - /// Returns if this transform matches arguments. - /// - /// - private bool GraphicalObjectMatches(Vector3 position, Quaternion rotation) - { - bool positionMatches = (!_smoothPosition || (_graphicalObject.position == position)); - bool rotationMatches = (!_smoothRotation || (_graphicalObject.rotation == rotation)); - return (positionMatches && rotationMatches); - } - - /// - /// True to smooth position. When false the graphicalObjects property will not be updated. - /// - /// - private bool SmoothPosition() => (_smoothPosition && (_networkBehaviour.IsOwner || _networkBehaviour.IsHost)); - /// - /// True to smooth rotation. When false the graphicalObjects property will not be updated. - /// - /// - private bool SmoothRotation() => (_smoothRotation && (_networkBehaviour.IsOwner || _networkBehaviour.IsHost)); - - /// - /// Sets Position and Rotation move rates to reach Target datas. - /// - private void SetGraphicalMoveRates() - { - float delta = ((float)_networkBehaviour.TimeManager.TickDelta * _interpolation); - - float distance; - distance = Vector3.Distance(_graphicalObject.position, GetGraphicalGoalPosition()); - //If qualifies for teleporting. - if (_teleportThreshold != -1f && distance >= _teleportThreshold) - { - _positionMoveRate = -1f; - _rotationMoveRate = -1f; - } - //Smoothing. - else - { - _positionMoveRate = (distance / delta); - distance = Quaternion.Angle(_graphicalObject.rotation, GetGraphicalGoalRotation()); - if (distance > 0f) - _rotationMoveRate = (distance / delta); - } - } - - /// - /// Gets a goal position for the graphical object. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Vector3 GetGraphicalGoalPosition() - { - if (SmoothPosition()) - return (_networkBehaviour.transform.position + _graphicalInstantiatedOffsetPosition); - else - return _graphicalObject.position; - } - - /// - /// Gets a goal rotation for the graphical object. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Quaternion GetGraphicalGoalRotation() - { - if (SmoothRotation()) - return (_graphicalInstantiatedOffsetRotation * _networkBehaviour.transform.rotation); - else - return _graphicalObject.rotation; - } - /// - /// Caches the graphical object' current position and rotation. - /// - private void SetGraphicalPreviousProperties() - { - _graphicalStartPosition = _graphicalObject.position; - _graphicalStartRotation = _graphicalObject.rotation; - } - - /// - /// Resets the graphical object to cached position and rotation of the transform. - /// - private void ResetGraphicalToPreviousProperties() - { - _graphicalObject.SetPositionAndRotation(_graphicalStartPosition, _graphicalStartRotation); - } - - /// - /// Resets the graphical object to it's transform offsets during instantiation. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ResetGraphicalToInstantiatedProperties(bool position, bool rotation) - { - if (position) - _graphicalObject.position = GetGraphicalGoalPosition(); - if (rotation) - _graphicalObject.rotation = GetGraphicalGoalRotation(); - } - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectOwnerSmoother.cs.meta b/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectOwnerSmoother.cs.meta deleted file mode 100644 index b24552a..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectOwnerSmoother.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8b3bc1d8919cdf749971d3d4d44b198f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectSpectatorSmoother.cs b/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectSpectatorSmoother.cs deleted file mode 100644 index cbe0ab7..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectSpectatorSmoother.cs +++ /dev/null @@ -1,884 +0,0 @@ -using FishNet.Object; -using FishNet.Transporting; -using FishNet.Utility.Extension; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - - -namespace FishNet.Component.Prediction -{ - internal class PredictedObjectSpectatorSmoother - { - #region Types. - /// - /// Data on a goal to move towards. - /// - private class GoalData - { - public bool IsActive; - /// - /// LocalTick this data is for. - /// - public uint LocalTick; - /// - /// Data on how fast to move to transform values. - /// - public RateData Rates = new RateData(); - /// - /// Transform values to move towards. - /// - public TransformData Transforms = new TransformData(); - - public GoalData() { } - /// - /// Resets values for re-use. - /// - public void Reset() - { - LocalTick = 0; - Transforms.Reset(); - Rates.Reset(); - IsActive = false; - } - - /// - /// Updates values using a GoalData. - /// - public void Update(GoalData gd) - { - LocalTick = gd.LocalTick; - Rates.Update(gd.Rates); - Transforms.Update(gd.Transforms); - IsActive = true; - } - - public void Update(uint localTick, RateData rd, TransformData td) - { - LocalTick = localTick; - Rates = rd; - Transforms = td; - IsActive = true; - } - } - /// - /// How fast to move to values. - /// - private class RateData - { - /// - /// Rate for position after smart calculations. - /// - public float Position; - /// - /// Rate for rotation after smart calculations. - /// - public float Rotation; - /// - /// Number of ticks the rates are calculated for. - /// If TickSpan is 2 then the rates are calculated under the assumption the transform changed over 2 ticks. - /// - public uint TickSpan; - /// - /// Time remaining until transform is expected to reach it's goal. - /// - internal float TimeRemaining; - - public RateData() { } - - /// - /// Resets values for re-use. - /// - public void Reset() - { - Position = 0f; - Rotation = 0f; - TickSpan = 0; - TimeRemaining = 0f; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Update(RateData rd) - { - Update(rd.Position, rd.Rotation, rd.TickSpan, rd.TimeRemaining); - } - - /// - /// Updates rates. - /// - public void Update(float position, float rotation, uint tickSpan, float timeRemaining) - { - Position = position; - Rotation = rotation; - TickSpan = tickSpan; - TimeRemaining = timeRemaining; - } - } - /// - /// Data about where a transform should move towards. - /// - private class TransformData - { - /// - /// Position of the transform. - /// - public Vector3 Position; - /// - /// Rotation of the transform. - /// - public Quaternion Rotation; - - public void Reset() - { - Position = Vector3.zero; - Rotation = Quaternion.identity; - } - /// - /// Updates this data. - /// - public void Update(TransformData copy) - { - Update(copy.Position, copy.Rotation); - } - /// - /// Updates this data. - /// - public void Update(Vector3 position, Quaternion rotation) - { - Position = position; - Rotation = rotation; - } - /// - /// Updates this data. - /// - public void Update(Rigidbody rigidbody) - { - Position = rigidbody.transform.position; - Rotation = rigidbody.transform.rotation; - } - /// - /// Updates this data. - /// - public void Update(Rigidbody2D rigidbody) - { - Position = rigidbody.transform.position; - Rotation = rigidbody.transform.rotation; - } - } - #endregion - - #region Private. - /// - /// Current GoalData being used. - /// - private GoalData _currentGoalData = new GoalData(); - /// - /// Object to smooth. - /// - private Transform _graphicalObject; - /// - /// Sets GraphicalObject. - /// - /// - public void SetGraphicalObject(Transform value) => _graphicalObject = value; - /// - /// True to move towards position goals. - /// - private bool _smoothPosition; - /// - /// True to move towards rotation goals. - /// - private bool _smoothRotation; - /// - /// How far in the past to keep the graphical object. - /// - private uint _interpolation = 4; - /// - /// Sets the interpolation value to use when the owner of this object. - /// - /// - public void SetInterpolation(uint value) => _interpolation = value; - /// - /// GoalDatas to move towards. - /// - private List _goalDatas = new List(); - /// - /// Rigidbody to use. - /// - private Rigidbody _rigidbody; - /// - /// Rigidbody2D to use. - /// - private Rigidbody2D _rigidbody2d; - /// - /// Transform state during PreTick. - /// - private TransformData _preTickTransformdata = new TransformData(); - /// - /// Type of rigidbody being used. - /// - private RigidbodyType _rigidbodyType; - /// - /// Last tick which a reconcile occured. This is reset at the end of a tick. - /// - private long _reconcileLocalTick = -1; - /// - /// Called when this frame receives OnPreTick. - /// - private bool _preTickReceived; - /// - /// Start position for graphicalObject at the beginning of the tick. - /// - private Vector3 _graphicalStartPosition; - /// - /// Start rotation for graphicalObject at the beginning of the tick. - /// - private Quaternion _graphicalStartRotation; - /// - /// How far a distance change must exceed to teleport the graphical object. -1f indicates teleport is not enabled. - /// - private float _teleportThreshold; - /// - /// PredictedObject which is using this object. - /// - private PredictedObject _predictedObject; - /// - /// Cache of GoalDatas to prevent allocations. - /// - private static Stack _goalDataCache = new Stack(); - /// - /// Cached localtick for performance. - /// - private uint _localTick; - /// - /// Number of ticks to ignore when replaying. - /// - private uint _ignoredTicks; - /// - /// Start position of the graphical object in world space. - /// - private Vector3 _startWorldPosition; - #endregion - - #region Const. - /// - /// Multiplier to apply to movement speed when buffer is over interpolation. - /// - private const float OVERFLOW_MULTIPLIER = 0.1f; - /// - /// Multiplier to apply to movement speed when buffer is under interpolation. - /// - private const float UNDERFLOW_MULTIPLIER = 0.02f; - #endregion - - public void SetIgnoredTicks(uint value) => _ignoredTicks = value; - /// - /// Initializes this for use. - /// - internal void Initialize(PredictedObject po, RigidbodyType rbType, Rigidbody rb, Rigidbody2D rb2d, Transform graphicalObject - , bool smoothPosition, bool smoothRotation, float teleportThreshold) - { - _predictedObject = po; - _rigidbodyType = rbType; - - _rigidbody = rb; - _rigidbody2d = rb2d; - _graphicalObject = graphicalObject; - _startWorldPosition = _graphicalObject.position; - _smoothPosition = smoothPosition; - _smoothRotation = smoothRotation; - _teleportThreshold = teleportThreshold; - } - - /// - /// - /// Called every frame. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ManualUpdate() - { - if (CanSmooth()) - MoveToTarget(); - } - - /// - /// Called when the TimeManager invokes OnPreTick. - /// - public void OnPreTick() - { - if (CanSmooth()) - { - _localTick = _predictedObject.TimeManager.LocalTick; - if (!_preTickReceived) - { - uint tick = _predictedObject.TimeManager.LocalTick - 1; - CreateGoalData(tick, false); - } - _preTickReceived = true; - - if (_rigidbodyType == RigidbodyType.Rigidbody) - _preTickTransformdata.Update(_rigidbody); - else - _preTickTransformdata.Update(_rigidbody2d); - - _graphicalStartPosition = _graphicalObject.position; - _graphicalStartRotation = _graphicalObject.rotation; - } - } - - /// - /// Called when the TimeManager invokes OnPostTick. - /// - public void OnPostTick() - { - if (CanSmooth()) - { - if (!_preTickReceived) - { - /* During test the Z value for applyImmediately is 5.9. - * Then increased 1 unit per tick: 6.9, 7.9. - * - * When the spectator smoother initializes 5.9 is shown. - * Before first starting smoothing the transform needs to be set - * back to that. - * - * The second issue is the first addition to goal datas seems - * to occur at 7.9. This would need to be 6.9 to move from the - * proper 5.9 starting point. It's probably because pretick is not received - * when OnPostTick is called at the 6.9 position. - * - * Have not validated the above yet but that's the most likely situation since - * we know this was initialized at 5.9, which means it would be assumed pretick would - * call at 6.9. Perhaps the following is happening.... - * - * - Pretick. - * - Client gets spawn+applyImmediately. - * - This also initializes this script at 5.9. - * - Simulation moves object to 6.9. - * - PostTick. - * - This script does not run because _preTickReceived is not set yet. - * - * - Pretick. Sets _preTickReceived. - * - Simulation moves object to 7.9. - * - PostTick. - * - The first goalData is created for 7.9. - * - * In writing the theory checks out. - * Perhaps the solution could be simple as creating a goal - * during pretick if _preTickReceived is being set for - * the first time. Might need to reduce tick by 1 - * when setting goalData for this; not sure yet. - */ - _graphicalObject.SetPositionAndRotation(_startWorldPosition, Quaternion.identity); - return; - } - - _graphicalObject.SetPositionAndRotation(_graphicalStartPosition, _graphicalStartRotation); - CreateGoalData(_predictedObject.TimeManager.LocalTick, true); - } - } - - public void OnPreReplay(uint tick) - { - if (!_preTickReceived) - { - if (CanSmooth()) - { - //if (_localTick - tick < _ignoredTicks) - // return; - - CreateGoalData(tick, false); - } - } - } - - /// - /// Called after a reconcile runs a replay. - /// - public void OnPostReplay(uint tick) - { - if (CanSmooth()) - { - if (_reconcileLocalTick == -1) - return; - - CreateGoalData(tick, false); - } - } - - /// - /// Returns if the graphics can be smoothed. - /// - /// - private bool CanSmooth() - { - if (_interpolation == 0) - return false; - if (_predictedObject.IsPredictingOwner() || _predictedObject.IsServer) - return false; - - return true; - } - - - /// - /// Sets the last tick a reconcile occurred. - /// - /// - public void SetLocalReconcileTick(long value) - { - _reconcileLocalTick = value; - } - - /// - /// Caches a GoalData. - /// - /// - private void StoreGoalData(GoalData gd) - { - gd.Reset(); - _goalDataCache.Push(gd); - } - - /// - /// Returns if this transform matches arguments. - /// - /// - private bool GraphicalObjectMatches(Vector3 localPosition, Quaternion localRotation) - { - bool positionMatches = (!_smoothPosition || _graphicalObject.position == localPosition); - bool rotationMatches = (!_smoothRotation || _graphicalObject.rotation == localRotation); - return (positionMatches && rotationMatches); - } - - /// - /// Returns if there is any change between two datas. - /// - private bool HasChanged(TransformData a, TransformData b) - { - return (a.Position != b.Position) || - (a.Rotation != b.Rotation); - } - - /// - /// Returns if the transform differs from td. - /// - private bool HasChanged(TransformData td) - { - Transform rigidbodyTransform; - - if (_rigidbodyType == RigidbodyType.Rigidbody) - rigidbodyTransform = _rigidbody.transform; - else - rigidbodyTransform = _rigidbody2d.transform; - - bool changed = (td.Position != rigidbodyTransform.position) || (td.Rotation != rigidbodyTransform.rotation); - - return changed; - } - - /// - /// Sets CurrentGoalData to the next in queue. - /// - private void SetCurrentGoalData(bool afterMove) - { - if (_goalDatas.Count == 0) - { - _currentGoalData.IsActive = false; - } - else - { - //if (!afterMove && _goalDatas.Count < _interpolation) - // return; - - //Update current to next. - _currentGoalData.Update(_goalDatas[0]); - //Store old and remove it. - StoreGoalData(_goalDatas[0]); - _goalDatas.RemoveAt(0); - } - } - - /// - /// Moves to a GoalData. Automatically determins if to use data from server or client. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void MoveToTarget(float deltaOverride = -1f) - { - /* If the current goal data is not active then - * try to set a new one. If none are available - * it will remain inactive. */ - if (!_currentGoalData.IsActive) - { - SetCurrentGoalData(false); - //If still inactive then it could not be updated. - if (!_currentGoalData.IsActive) - return; - } - - float delta = (deltaOverride != -1f) ? deltaOverride : Time.deltaTime; - /* Once here it's safe to assume the object will be moving. - * Any checks which would stop it from moving be it client - * auth and owner, or server controlled and server, ect, - * would have already been run. */ - TransformData td = _currentGoalData.Transforms; - RateData rd = _currentGoalData.Rates; - - int queueCount = _goalDatas.Count; - /* Begin moving even if interpolation buffer isn't - * met to provide more real-time interactions but - * speed up when buffer is too large. This should - * provide a good balance of accuracy. */ - - float multiplier; - int countOverInterpolation = (queueCount - (int)_interpolation); - if (countOverInterpolation > 0) - { - float overflowMultiplier = (!_predictedObject.IsOwner) ? OVERFLOW_MULTIPLIER : (OVERFLOW_MULTIPLIER * 1f); - multiplier = 1f + overflowMultiplier; - } - else if (countOverInterpolation < 0) - { - float value = (UNDERFLOW_MULTIPLIER * Mathf.Abs(countOverInterpolation)); - const float maximum = 0.9f; - if (value > maximum) - value = maximum; - multiplier = 1f - value; - } - else - { - multiplier = 1f; - } - - //Rate to update. Changes per property. - float rate; - Transform t = _graphicalObject; - - //Position. - if (_smoothPosition) - { - rate = rd.Position; - Vector3 posGoal = td.Position; - if (rate == -1f) - t.position = td.Position; - else if (rate > 0f) - t.position = Vector3.MoveTowards(t.position, posGoal, rate * delta * multiplier); - } - - //Rotation. - if (_smoothRotation) - { - rate = rd.Rotation; - if (rate == -1f) - t.rotation = td.Rotation; - else if (rate > 0f) - t.rotation = Quaternion.RotateTowards(t.rotation, td.Rotation, rate * delta); - } - - //Subtract time remaining for movement to complete. - if (rd.TimeRemaining > 0f) - { - float subtractionAmount = (delta * multiplier); - float timeRemaining = rd.TimeRemaining - subtractionAmount; - rd.TimeRemaining = timeRemaining; - } - - //If movement shoudl be complete. - if (rd.TimeRemaining <= 0f) - { - float leftOver = Mathf.Abs(rd.TimeRemaining); - //Set to next goal data if available. - SetCurrentGoalData(true); - - //New data was set. - if (_currentGoalData.IsActive) - { - if (leftOver > 0f) - MoveToTarget(leftOver); - } - //No more in buffer, see if can extrapolate. - else - { - /* Everything should line up when - * time remaining is <= 0f but incase it's not, - * such as if the user manipulated the grapihc object - * somehow, then set goaldata active again to continue - * moving it until it lines up with the goal. */ - if (!GraphicalObjectMatches(td.Position, td.Rotation)) - _currentGoalData.IsActive = true; - } - } - } - - #region Rates. - /// - /// Sets move rates which will occur instantly. - /// - private void SetInstantRates(RateData rd) - { - rd.Update(-1f, -1f, 1, -1f); - } - - /// - /// Sets move rates which will occur over time. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void SetCalculatedRates(GoalData prevGoalData, GoalData nextGoalData, Channel channel) - { - /* Only update rates if data has changed. - * When data comes in reliably for eventual consistency - * it's possible that it will be the same as the last - * unreliable packet. When this happens no change has occurred - * and the distance of change woudl also be 0; this prevents - * the NT from moving. Only need to compare data if channel is reliable. */ - TransformData nextTd = nextGoalData.Transforms; - if (channel == Channel.Reliable && HasChanged(prevGoalData.Transforms, nextTd)) - { - nextGoalData.Rates.Update(prevGoalData.Rates); - return; - } - - uint lastTick = prevGoalData.LocalTick; - /* How much time has passed between last update and current. - * If set to 0 then that means the transform has - * settled. */ - if (lastTick == 0) - lastTick = (nextGoalData.LocalTick - 1); - - uint tickDifference = (nextGoalData.LocalTick - lastTick); - float timePassed = (float)_predictedObject.TimeManager.TicksToTime(tickDifference); - RateData nextRd = nextGoalData.Rates; - - //Distance between properties. - float distance; - //Position. - Vector3 lastPosition = prevGoalData.Transforms.Position; - distance = Vector3.Distance(lastPosition, nextTd.Position); - //If distance teleports assume rest do. - if (_teleportThreshold >= 0f && distance >= _teleportThreshold) - { - SetInstantRates(nextRd); - return; - } - - //Position distance already calculated. - float positionRate = (distance / timePassed); - //Rotation. - distance = prevGoalData.Transforms.Rotation.Angle(nextTd.Rotation, true); - float rotationRate = (distance / timePassed); - - /* If no speed then snap just in case. - * 0f could be from floating errors. */ - if (positionRate == 0f) - positionRate = -1f; - if (rotationRate == 0f) - rotationRate = -1f; - - nextRd.Update(positionRate, rotationRate, tickDifference, timePassed); - } - #endregion - - /// - /// Creates a new goal data for tick. The result will be placed into the goalDatas queue at it's proper position. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void CreateGoalData(uint tick, bool postTick) - { - /* It's possible a removed entry would void further - * logic so remove excess entires first. */ - - /* Remove entries which are excessive to the buffer. - * This could create a starting jitter but it will ensure - * the buffer does not fill too much. The buffer next should - * actually get unreasonably high but rather safe than sorry. */ - int maximumBufferAllowance = ((int)_interpolation * 8); - int removedBufferCount = (_goalDatas.Count - maximumBufferAllowance); - //If there are some to remove. - if (removedBufferCount > 0) - { - for (int i = 0; i < removedBufferCount; i++) - StoreGoalData(_goalDatas[0 + i]); - _goalDatas.RemoveRange(0, removedBufferCount); - } - - uint currentGoalDataTick = _currentGoalData.LocalTick; - //Tick has already been interpolated past, no reason to process it. - if (tick <= currentGoalDataTick) - return; - - //GoalData from previous calculation. - GoalData prevGoalData; - int datasCount = _goalDatas.Count; - /* Where to insert next data. This could have value - * somewhere in the middle of goalDatas if the tick - * is a replay rather than post tick. */ - int injectionIndex = datasCount + 1; - //If being added at the end of a tick rather than from replay. - if (postTick) - { - //Becomes true if transform differs from previous data. - bool changed; - - //If there is no goal data then create one using pretick data. - if (datasCount == 0) - { - prevGoalData = MakeGoalDataFromPreTickTransform(); - changed = HasChanged(prevGoalData.Transforms); - } - //If there's goal datas grab the last, it will always be the tick before. - else - { - prevGoalData = _goalDatas[datasCount - 1]; - /* If the tick is not exactly 1 past the last - * then there's gaps in the saved values. This can - * occur if the transform went idle and the buffer - * hasn't emptied out yet. When this occurs use the - * preTick data to calculate differences. */ - if (tick - prevGoalData.LocalTick != 1) - prevGoalData = MakeGoalDataFromPreTickTransform(); - - changed = HasChanged(prevGoalData.Transforms); - } - - //Nothing has changed so no further action is required. - if (!changed) - { - if (datasCount > 0 && prevGoalData != _goalDatas[datasCount - 1]) - StoreGoalData(prevGoalData); - return; - } - } - //Not post tick so it's from a replay. - else - { - int prevIndex = -1; - /* If the tick is 1 past current goalData - * then it's the next in line for smoothing - * from the current. - * When this occurs use currentGoalData as - * the previous. */ - if (tick == (currentGoalDataTick + 1)) - { - prevGoalData = _currentGoalData; - injectionIndex = 0; - } - //When not the next in line find out where to place data. - else - { - if (tick > 0) - prevGoalData = GetGoalData(tick - 1, out prevIndex); - //Cannot find prevGoalData if tick is 0. - else - prevGoalData = null; - } - - //If previous goalData was found then inject just past the previous value. - if (prevIndex != -1) - injectionIndex = prevIndex + 1; - - /* Should previous goalData be null then it could not be found. - * Create a new previous goal data based on rigidbody state - * during pretick. */ - if (prevGoalData == null) - { - //Create a goaldata based on information. If it differs from pretick then throw. - GoalData gd = RetrieveGoalData(); - gd.Transforms.Update(_preTickTransformdata); - - if (HasChanged(gd.Transforms)) - { - prevGoalData = gd; - } - else - { - StoreGoalData(gd); - return; - } - } - /* Previous goal data is not active. - * This should not be possible but this - * is here as a sanity check anyway. */ - else if (!prevGoalData.IsActive) - { - return; - } - } - - //Begin building next goal data. - GoalData nextGoalData = RetrieveGoalData(); - nextGoalData.LocalTick = tick; - //Set next transform data. - TransformData nextTd = nextGoalData.Transforms; - if (_rigidbodyType == RigidbodyType.Rigidbody) - nextTd.Update(_rigidbody); - else - nextTd.Update(_rigidbody2d); - - /* Reset properties if smoothing is not enabled - * for them. It's less checks and easier to do it - * after the nextGoalData is populated. */ - if (!_smoothPosition) - nextTd.Position = _graphicalStartPosition; - if (!_smoothRotation) - nextTd.Rotation = _graphicalStartRotation; - - //Calculate rates for prev vs next data. - SetCalculatedRates(prevGoalData, nextGoalData, Channel.Unreliable); - /* If injectionIndex would place at the end - * then add. to goalDatas. */ - if (injectionIndex >= _goalDatas.Count) - _goalDatas.Add(nextGoalData); - //Otherwise insert into the proper location. - else - _goalDatas[injectionIndex].Update(nextGoalData); - - //Makes previous goal data from transforms pretick values. - GoalData MakeGoalDataFromPreTickTransform() - { - GoalData gd = RetrieveGoalData(); - //RigidbodyData contains the data from preTick. - gd.Transforms.Update(_preTickTransformdata); - //No need to update rates because this is just a starting point reference for interpolation. - return gd; - } - } - - /// - /// Returns the GoalData at tick. - /// - /// - private GoalData GetGoalData(uint tick, out int index) - { - index = -1; - if (tick == 0) - return null; - - for (int i = 0; i < _goalDatas.Count; i++) - { - if (_goalDatas[i].LocalTick == tick) - { - index = i; - return _goalDatas[i]; - } - } - - //Not found. - return null; - } - - - /// - /// Returns a GoalData from the cache. - /// - /// - private GoalData RetrieveGoalData() - { - GoalData result = (_goalDataCache.Count > 0) ? _goalDataCache.Pop() : new GoalData(); - result.IsActive = true; - return result; - } - - } - - -} diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectSpectatorSmoother.cs.meta b/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectSpectatorSmoother.cs.meta deleted file mode 100644 index 63c200f..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/PredictedObjectSpectatorSmoother.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6bb311b5dc9602a4f8e4a8c6e64b21cb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyPauser.cs b/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyPauser.cs deleted file mode 100644 index 55098f4..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyPauser.cs +++ /dev/null @@ -1,361 +0,0 @@ -using FishNet.Managing; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.SceneManagement; - -namespace FishNet.Component.Prediction -{ - /// - /// Pauses and unpauses rigidbodies. While paused rigidbodies cannot be interacted with or simulated. - /// - public class RigidbodyPauser - { - #region Types. - /// - /// Data for a rigidbody before being set kinematic. - /// - private struct RigidbodyData - { - /// - /// Rigidbody for data. - /// - public Rigidbody Rigidbody; - /// - /// Cached velocity when being set kinematic. - /// - public Vector3 Velocity; - /// - /// Cached velocity when being set kinematic. - /// - public Vector3 AngularVelocity; - /// - /// Scene of this rigidbody when being set kinematic. - /// - public Scene SimulatedScene; - /// - /// True if the rigidbody was kinematic prior to being paused. - /// - public bool IsKinematic; - - public RigidbodyData(Rigidbody rb) - { - Rigidbody = rb; - Rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous; - Velocity = Vector3.zero; - AngularVelocity = Vector3.zero; - SimulatedScene = rb.gameObject.scene; - IsKinematic = rb.isKinematic; - } - - public void Update(Rigidbody rb) - { - Velocity = rb.velocity; - AngularVelocity = rb.angularVelocity; - SimulatedScene = rb.gameObject.scene; - IsKinematic = rb.isKinematic; - } - } - /// - /// Data for a rigidbody2d before being set kinematic. - /// - private struct Rigidbody2DData - { - /// - /// Rigidbody for data. - /// - public Rigidbody2D Rigidbody2d; - /// - /// Cached velocity when being set kinematic. - /// - public Vector2 Velocity; - /// - /// Cached velocity when being set kinematic. - /// - public float AngularVelocity; - /// - /// Scene of this rigidbody when being set kinematic. - /// - public Scene SimulatedScene; - /// - /// True if the rigidbody was simulated prior to being paused. - /// - public bool Simulated; - - public Rigidbody2DData(Rigidbody2D rb) - { - Rigidbody2d = rb; - Rigidbody2d.collisionDetectionMode = CollisionDetectionMode2D.Continuous; - Velocity = Vector2.zero; - AngularVelocity = 0f; - SimulatedScene = rb.gameObject.scene; - Simulated = rb.simulated; - } - - public void Update(Rigidbody2D rb) - { - Velocity = rb.velocity; - AngularVelocity = rb.angularVelocity; - SimulatedScene = rb.gameObject.scene; - Simulated = rb.simulated; - } - } - #endregion - - #region Public. - /// - /// True if the rigidbodies are considered paused. - /// - public bool Paused { get; private set; } - #endregion - - #region Private. - /// - /// Rigidbody datas for found rigidbodies. - /// - private List _rigidbodyDatas = new List(); - /// - /// Rigidbody2D datas for found rigidbodies; - /// - private List _rigidbody2dDatas = new List(); - /// - /// Type of prediction movement which is being used. - /// - private RigidbodyType _rigidbodyType; - /// - /// - /// - private static Scene _kinematicSceneCache; - /// - /// Scene used to simulate kinematic rigidbodies. - /// - private static Scene _kinematicScene - { - get - { - if (!_kinematicSceneCache.IsValid()) - _kinematicSceneCache = SceneManager.CreateScene("RigidbodyPauser_Kinematic", new CreateSceneParameters(LocalPhysicsMode.Physics2D | LocalPhysicsMode.Physics3D)); - return _kinematicSceneCache; - } - } - /// - /// Parent of GraphicalObject prior to unparenting. - /// - private Transform _graphicalParent; - /// - /// GraphicalObject to unparent when pausing. - /// - private Transform _graphicalObject; - #endregion - - /// - /// Assigns rigidbodies. - /// - /// Rigidbodies2D to use. - public void UpdateRigidbodies(Transform t, RigidbodyType rbType, bool getInChildren, Transform graphicalObject) - { - _rigidbodyType = rbType; - _rigidbodyDatas.Clear(); - _rigidbody2dDatas.Clear(); - - //3D. - if (rbType == RigidbodyType.Rigidbody) - { - if (getInChildren) - { - Rigidbody[] rbs = t.GetComponentsInChildren(); - for (int i = 0; i < rbs.Length; i++) - _rigidbodyDatas.Add(new RigidbodyData(rbs[i])); - } - else - { - Rigidbody rb = t.GetComponent(); - if (rb != null) - _rigidbodyDatas.Add(new RigidbodyData(rb)); - } - - //Make sure all added datas are not the graphical object. - for (int i = 0; i < _rigidbodyDatas.Count; i++) - { - if (_rigidbodyDatas[i].Rigidbody.transform == graphicalObject) - { - NetworkManager.StaticLogError($"GameObject {t.name} has it's GraphicalObject as a child or on the same object as a Rigidbody object. The GraphicalObject must be a child of root, and not sit beneath or on any rigidbodies."); - graphicalObject = null; - } - } - } - //2D. - else - { - if (getInChildren) - { - Rigidbody2D[] rbs = t.GetComponentsInChildren(); - for (int i = 0; i < rbs.Length; i++) - _rigidbody2dDatas.Add(new Rigidbody2DData(rbs[i])); - } - else - { - Rigidbody2D rb = t.GetComponent(); - if (rb != null) - _rigidbody2dDatas.Add(new Rigidbody2DData(rb)); - } - - //Make sure all added datas are not the graphical object. - for (int i = 0; i < _rigidbody2dDatas.Count; i++) - { - if (_rigidbody2dDatas[i].Rigidbody2d.transform == graphicalObject) - { - NetworkManager.StaticLogError($"GameObject {t.name} has it's GraphicalObject as a child or on the same object as a Rigidbody object. The GraphicalObject must be a child of root, and not sit beneath or on any rigidbodies."); - graphicalObject = null; - } - } - } - - if (graphicalObject != null) - { - _graphicalObject = graphicalObject; - _graphicalParent = graphicalObject.parent; - } - } - - /// - /// Unpauses rigidbodies allowing them to interact normally. - /// - public void Unpause() - { - if (!Paused) - return; - Paused = false; - - //3D. - if (_rigidbodyType == RigidbodyType.Rigidbody) - { - for (int i = 0; i < _rigidbodyDatas.Count; i++) - { - if (!UnpauseRigidbody(i)) - { - _rigidbodyDatas.RemoveAt(i); - i--; - } - } - - //Sets isKinematic status and returns if successful. - bool UnpauseRigidbody(int index) - { - RigidbodyData rbData = _rigidbodyDatas[index]; - Rigidbody rb = rbData.Rigidbody; - if (rb == null) - return false; - - rb.velocity = rbData.Velocity; - rb.angularVelocity = rbData.AngularVelocity; - rb.isKinematic = rbData.IsKinematic; - SceneManager.MoveGameObjectToScene(rb.transform.root.gameObject, rbData.SimulatedScene); - return true; - } - } - //2D. - else - { - for (int i = 0; i < _rigidbody2dDatas.Count; i++) - { - if (!UnpauseRigidbody(i)) - { - _rigidbody2dDatas.RemoveAt(i); - i--; - } - } - - //Sets isKinematic status and returns if successful. - bool UnpauseRigidbody(int index) - { - Rigidbody2DData rbData = _rigidbody2dDatas[index]; - Rigidbody2D rb = rbData.Rigidbody2d; - if (rb == null) - return false; - - rb.velocity = rbData.Velocity; - rb.angularVelocity = rbData.AngularVelocity; - rb.simulated = rbData.Simulated; - rb.isKinematic = !rbData.Simulated; - SceneManager.MoveGameObjectToScene(rb.transform.root.gameObject, rbData.SimulatedScene); - return true; - } - } - - //Parent went null, then graphicalObject needs to be destroyed. - if (_graphicalParent == null && _graphicalObject != null) - MonoBehaviour.Destroy(_graphicalObject.gameObject); - else - _graphicalObject?.SetParent(_graphicalParent); - - } - - /// - /// Pauses rigidbodies preventing them from interacting. - /// - public void Pause() - { - if (Paused) - return; - Paused = true; - - _graphicalObject?.SetParent(null); - Scene kinematicScene = _kinematicScene; - - //3D. - if (_rigidbodyType == RigidbodyType.Rigidbody) - { - for (int i = 0; i < _rigidbodyDatas.Count; i++) - { - if (!PauseRigidbody(i)) - { - _rigidbodyDatas.RemoveAt(i); - i--; - } - } - - //Sets isKinematic status and returns if successful. - bool PauseRigidbody(int index) - { - RigidbodyData rbData = _rigidbodyDatas[index]; - Rigidbody rb = rbData.Rigidbody; - if (rb == null) - return false; - - rbData.Update(rb); - _rigidbodyDatas[index] = rbData; - SceneManager.MoveGameObjectToScene(rb.transform.root.gameObject, kinematicScene); - return true; - } - } - //2D. - else - { - for (int i = 0; i < _rigidbody2dDatas.Count; i++) - { - if (!PauseRigidbody(i)) - { - _rigidbody2dDatas.RemoveAt(i); - i--; - } - } - - //Sets isKinematic status and returns if successful. - bool PauseRigidbody(int index) - { - Rigidbody2DData rbData = _rigidbody2dDatas[index]; - Rigidbody2D rb = rbData.Rigidbody2d; - if (rb == null) - return false; - - rbData.Update(rb); - _rigidbody2dDatas[index] = rbData; - SceneManager.MoveGameObjectToScene(rb.transform.root.gameObject, kinematicScene); - return true; - } - } - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyPauser.cs.meta b/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyPauser.cs.meta deleted file mode 100644 index 4b7e11a..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyPauser.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9536377524ca5db43aae431f983ab21f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyState.cs b/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyState.cs deleted file mode 100644 index f61286f..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyState.cs +++ /dev/null @@ -1,140 +0,0 @@ -using FishNet.Component.Prediction; -using FishNet.Serializing; -using UnityEngine; - -namespace FishNet.Component.Prediction -{ - public struct RigidbodyState - { - public uint LocalTick; - public Vector3 Position; - public Quaternion Rotation; - public bool IsKinematic; - public Vector3 Velocity; - public Vector3 AngularVelocity; - - public RigidbodyState(Rigidbody rb, bool isKinematic, uint tick) : this(rb, tick) - { - Position = rb.transform.position; - Rotation = rb.transform.rotation; - IsKinematic = isKinematic; - Velocity = rb.velocity; - AngularVelocity = rb.angularVelocity; - LocalTick = tick; - - } - - public RigidbodyState(Rigidbody rb, uint tick) - { - Position = rb.transform.position; - Rotation = rb.transform.rotation; - IsKinematic = rb.isKinematic; - Velocity = rb.velocity; - AngularVelocity = rb.angularVelocity; - LocalTick = tick; - } - } - - public struct Rigidbody2DState - { - public uint LocalTick; - public Vector3 Position; - public Quaternion Rotation; - public bool Simulated; - public Vector2 Velocity; - public float AngularVelocity; - - public Rigidbody2DState(Rigidbody2D rb, bool simulated, uint tick) - { - Simulated = simulated; - Position = rb.transform.position; - Rotation = rb.transform.rotation; - Velocity = rb.velocity; - AngularVelocity = rb.angularVelocity; - LocalTick = tick; - } - - public Rigidbody2DState(Rigidbody2D rb, uint tick) - { - Simulated = rb.simulated; - Position = rb.transform.position; - Rotation = rb.transform.rotation; - Velocity = rb.velocity; - AngularVelocity = rb.angularVelocity; - LocalTick = tick; - } - } -} - -public static class RigidbodyStateSerializers -{ - - public static void WriteRigidbodyState(this Writer writer, RigidbodyState value) - { - writer.WriteUInt32(value.LocalTick, AutoPackType.Unpacked); - writer.WriteVector3(value.Position); - writer.WriteQuaternion(value.Rotation); - writer.WriteBoolean(value.IsKinematic); - if (!value.IsKinematic) - { - writer.WriteVector3(value.Velocity); - writer.WriteVector3(value.AngularVelocity); - } - } - - public static RigidbodyState ReadRigidbodyState(this Reader reader) - { - RigidbodyState state = new RigidbodyState() - { - LocalTick = reader.ReadUInt32(AutoPackType.Unpacked), - Position = reader.ReadVector3(), - Rotation = reader.ReadQuaternion(), - IsKinematic = reader.ReadBoolean() - }; - - if (!state.IsKinematic) - { - state.Velocity = reader.ReadVector3(); - state.AngularVelocity = reader.ReadVector3(); - } - - return state; - } - - - public static void WriteRigidbody2DState(this Writer writer, Rigidbody2DState value) - { - writer.WriteUInt32(value.LocalTick, AutoPackType.Unpacked); - writer.WriteVector3(value.Position); - writer.WriteQuaternion(value.Rotation); - writer.WriteBoolean(value.Simulated); - - if (value.Simulated) - { - writer.WriteVector2(value.Velocity); - writer.WriteSingle(value.AngularVelocity); - } - } - - public static Rigidbody2DState ReadRigidbody2DState(this Reader reader) - { - Rigidbody2DState state = new Rigidbody2DState() - { - LocalTick = reader.ReadUInt32(AutoPackType.Unpacked), - Position = reader.ReadVector3(), - Rotation = reader.ReadQuaternion(), - Simulated = reader.ReadBoolean(), - }; - - if (state.Simulated) - { - state.Velocity = reader.ReadVector2(); - state.AngularVelocity = reader.ReadSingle(); - } - - return state; - } - - -} - diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyState.cs.meta b/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyState.cs.meta deleted file mode 100644 index b3f5928..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyState.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 05dbb585c2bc6bf4dbbc592bea73d2fe -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyType.cs b/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyType.cs deleted file mode 100644 index a265b55..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyType.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace FishNet.Component.Prediction -{ - /// - /// Type of prediction movement being used. - /// - public enum RigidbodyType : byte - { - Rigidbody = 0, - Rigidbody2D = 1 - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyType.cs.meta b/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyType.cs.meta deleted file mode 100644 index 95cfe46..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Prediction/RigidbodyType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7cf2d3fc2ff7a9042b4b7618db15b482 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Spawning.meta b/Assets/FishNet/Runtime/Generated/Component/Spawning.meta deleted file mode 100644 index 1e253fc..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Spawning.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: c4ff15ab60e92f14499393c8b415ea2f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Spawning/PlayerSpawner.cs b/Assets/FishNet/Runtime/Generated/Component/Spawning/PlayerSpawner.cs deleted file mode 100644 index f5cefff..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Spawning/PlayerSpawner.cs +++ /dev/null @@ -1,159 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing; -using FishNet.Object; -using System; -using UnityEngine; -using UnityEngine.Serialization; - -namespace FishNet.Component.Spawning -{ - - /// - /// Spawns a player object for clients when they connect. - /// Must be placed on or beneath the NetworkManager object. - /// - [AddComponentMenu("FishNet/Component/PlayerSpawner")] - public class PlayerSpawner : MonoBehaviour - { - #region Public. - /// - /// Called on the server when a player is spawned. - /// - public event Action OnSpawned; - #endregion - - #region Serialized. - /// - /// Prefab to spawn for the player. - /// - [Tooltip("Prefab to spawn for the player.")] - [SerializeField] - private NetworkObject _playerPrefab; - /// - /// True to add player to the active scene when no global scenes are specified through the SceneManager. - /// - [Tooltip("True to add player to the active scene when no global scenes are specified through the SceneManager.")] - [SerializeField] - private bool _addToDefaultScene = true; - /// - /// Areas in which players may spawn. - /// - [Tooltip("Areas in which players may spawn.")] - [FormerlySerializedAs("_spawns")] - public Transform[] Spawns = new Transform[0]; - #endregion - - #region Private. - /// - /// NetworkManager on this object or within this objects parents. - /// - private NetworkManager _networkManager; - /// - /// Next spawns to use. - /// - private int _nextSpawn; - #endregion - - private void Start() - { - InitializeOnce(); - } - - private void OnDestroy() - { - if (_networkManager != null) - _networkManager.SceneManager.OnClientLoadedStartScenes -= SceneManager_OnClientLoadedStartScenes; - } - - - /// - /// Initializes this script for use. - /// - private void InitializeOnce() - { - _networkManager = InstanceFinder.NetworkManager; - if (_networkManager == null) - { - Debug.LogWarning($"PlayerSpawner on {gameObject.name} cannot work as NetworkManager wasn't found on this object or within parent objects."); - return; - } - - _networkManager.SceneManager.OnClientLoadedStartScenes += SceneManager_OnClientLoadedStartScenes; - } - - /// - /// Called when a client loads initial scenes after connecting. - /// - private void SceneManager_OnClientLoadedStartScenes(NetworkConnection conn, bool asServer) - { - if (!asServer) - return; - if (_playerPrefab == null) - { - Debug.LogWarning($"Player prefab is empty and cannot be spawned for connection {conn.ClientId}."); - return; - } - - Vector3 position; - Quaternion rotation; - SetSpawn(_playerPrefab.transform, out position, out rotation); - - NetworkObject nob = _networkManager.GetPooledInstantiated(_playerPrefab, true); - nob.transform.SetPositionAndRotation(position, rotation); - _networkManager.ServerManager.Spawn(nob, conn); - - //If there are no global scenes - if (_addToDefaultScene) - _networkManager.SceneManager.AddOwnerToDefaultScene(nob); - - OnSpawned?.Invoke(nob); - } - - - /// - /// Sets a spawn position and rotation. - /// - /// - /// - private void SetSpawn(Transform prefab, out Vector3 pos, out Quaternion rot) - { - //No spawns specified. - if (Spawns.Length == 0) - { - SetSpawnUsingPrefab(prefab, out pos, out rot); - return; - } - - Transform result = Spawns[_nextSpawn]; - if (result == null) - { - SetSpawnUsingPrefab(prefab, out pos, out rot); - } - else - { - pos = result.position; - rot = result.rotation; - } - - //Increase next spawn and reset if needed. - _nextSpawn++; - if (_nextSpawn >= Spawns.Length) - _nextSpawn = 0; - } - - /// - /// Sets spawn using values from prefab. - /// - /// - /// - /// - private void SetSpawnUsingPrefab(Transform prefab, out Vector3 pos, out Quaternion rot) - { - pos = prefab.position; - rot = prefab.rotation; - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/Spawning/PlayerSpawner.cs.meta b/Assets/FishNet/Runtime/Generated/Component/Spawning/PlayerSpawner.cs.meta deleted file mode 100644 index 64930b9..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Spawning/PlayerSpawner.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 211a9f6ec51ddc14f908f5acc0cd0423 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/TakeOwnership.meta b/Assets/FishNet/Runtime/Generated/Component/TakeOwnership.meta deleted file mode 100644 index aef58f6..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/TakeOwnership.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: f4c64a37139b4b946b6f5daf3a7ae3da -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedOwner.cs b/Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedOwner.cs deleted file mode 100644 index 7fc3e74..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedOwner.cs +++ /dev/null @@ -1,121 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing; -using FishNet.Managing.Logging; -using FishNet.Managing.Server; -using FishNet.Object; -using FishNet.Object.Synchronizing; -using UnityEngine; - -namespace FishNet.Component.Ownership -{ - /// - /// Adding this component allows any client to take ownership of the object and begin modifying it immediately. - /// - public class PredictedOwner : NetworkBehaviour - { - #region Public. - /// - /// True if the local client used TakeOwnership and is awaiting an ownership change. - /// - public bool TakingOwnership { get; private set; } - /// - /// Owner on client prior to taking ownership. This can be used to reverse a failed ownership attempt. - /// - public NetworkConnection PreviousOwner { get; private set; } = NetworkManager.EmptyConnection; - #endregion - - #region Serialized. - /// - /// True if to enable this component. - /// - [Tooltip("True if to enable this component.")] - [SyncVar(SendRate = 0f)] - [SerializeField] - private bool _allowTakeOwnership = true; - /// - /// Sets the next value for AllowTakeOwnership and synchronizes it. - /// Only the server may use this method. - /// - /// Next value to use. - [Server] - public void SetAllowTakeOwnership(bool value) => _allowTakeOwnership = value; - #endregion - - /// - /// Called on the client after gaining or losing ownership. - /// - /// Previous owner of this object. - public override void OnOwnershipClient(NetworkConnection prevOwner) - { - base.OnOwnershipClient(prevOwner); - /* Unset taken ownership either way. - * If the new owner it won't be used, - * if no longer owner then another client - * took it. */ - TakingOwnership = false; - PreviousOwner = base.Owner; - } - - /// - /// Takes ownership of this object to the local client and allows immediate control. - /// - [Client] - public virtual void TakeOwnership() - { - if (!_allowTakeOwnership) - return; - //Already owner. - if (base.IsOwner) - return; - - NetworkConnection c = base.ClientManager.Connection; - TakingOwnership = true; - //If not server go through the server. - if (!base.IsServer) - { - base.NetworkObject.SetLocalOwnership(c); - ServerTakeOwnership(); - } - //Otherwise take directly without rpcs. - else - { - OnTakeOwnership(c); - } - } - - - /// - /// Takes ownership of this object. - /// - [ServerRpc(RequireOwnership = false)] - private void ServerTakeOwnership(NetworkConnection caller = null) - { - OnTakeOwnership(caller); - } - - /// - /// Called on the server when a client tries to take ownership of this object. - /// - /// Connection trying to take ownership. - [Server] - protected virtual void OnTakeOwnership(NetworkConnection caller) - { - //Client somehow disconnected between here and there. - if (!caller.IsActive) - return; - //Feature is not enabled. - if (!_allowTakeOwnership) - return; - //Already owner. - if (caller == base.Owner) - return; - - base.GiveOwnership(caller); - /* No need to send a response back because an ownershipchange will handle changes. - * Although if you were to override with this your own behavior - * you could send responses for approved/denied. */ - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedOwner.cs.meta b/Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedOwner.cs.meta deleted file mode 100644 index 2d0aa92..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedOwner.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 03002f7d324007e41b10a9dc87ed3c38 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedSpawn.cs b/Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedSpawn.cs deleted file mode 100644 index 307e1a7..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedSpawn.cs +++ /dev/null @@ -1,96 +0,0 @@ -using FishNet.Connection; -using FishNet.Object; -using UnityEngine; - -namespace FishNet.Component.Ownership -{ - /// - /// Adding this component allows any client to use predictive spawning on this prefab. - /// - public class PredictedSpawn : NetworkBehaviour - { - #region Serialized. - /// - /// True to allow clients to predicted spawn this object. - /// - public bool GetAllowSpawning() => _allowSpawning; - /// - /// Sets to allow predicted spawning. This must be set on client and server. - /// - /// New value. - public void SetAllowSpawning(bool value) => _allowSpawning = value; - [Tooltip("True to allow clients to predicted spawn this object.")] - [SerializeField] - private bool _allowSpawning = true; - /// - /// True to allow clients to predicted despawn this object. - /// - public bool GetAllowDespawning() => _allowDespawning; - /// - /// Sets to allow predicted despawning. This must be set on client and server. - /// - /// New value. - public void SetAllowDespawning(bool value) => _allowDespawning = value; - [Tooltip("True to allow clients to predicted despawn this object.")] - [SerializeField] - private bool _allowDespawning = true; - /// - /// - /// - [Tooltip("True to allow clients to predicted set syncTypes prior to spawning the item. Set values will be applied on the server and sent to other clients.")] - [SerializeField] - private bool _allowSyncTypes = true; - /// - /// True to allow clients to predicted set syncTypes prior to spawning the item. Set values will be applied on the server and sent to other clients. - /// - public bool GetAllowSyncTypes() => _allowSyncTypes; - /// - /// Sets to allow syncTypes. This must be set on client and server. - /// - /// New value. - public void SetAllowSyncTypes(bool value) => _allowSyncTypes = value; - #endregion - - /// - /// Called on the client when trying to predicted spawn this object. - /// - /// Owner specified to spawn with. - /// True if able to spawn. - public virtual bool OnTrySpawnClient(NetworkConnection owner = null) - { - return GetAllowSpawning(); - } - /// - /// Called on the server when a client tries to predicted spawn this object. - /// - /// Connection trying to predicted spawn this object. - /// Owner specified to spawn with. - /// True if able to spawn. - public virtual bool OnTrySpawnServer(NetworkConnection spawner, NetworkConnection owner = null) - { - return GetAllowSpawning(); - } - - /// - /// Called on the client when trying to predicted spawn this object. - /// - /// True if able to despawn. - public virtual bool OnTryDespawnClient() - { - return GetAllowDespawning(); - } - /// - /// Called on the server when a client tries to predicted despawn this object. - /// - /// Connection trying to predicted despawn this object. - /// True if able to despawn. - public virtual bool OnTryDepawnServer(NetworkConnection despawner) - { - return GetAllowDespawning(); - } - - - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedSpawn.cs.meta b/Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedSpawn.cs.meta deleted file mode 100644 index 1fa856f..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/TakeOwnership/PredictedSpawn.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e2b597e1828355a4d994a69cbb11ef85 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Utility.meta b/Assets/FishNet/Runtime/Generated/Component/Utility.meta deleted file mode 100644 index 3fb63eb..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Utility.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 4fbf39de0f731b64e97742bcbfa213d3 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Utility/BandwidthDisplay.cs b/Assets/FishNet/Runtime/Generated/Component/Utility/BandwidthDisplay.cs deleted file mode 100644 index c3c9f3b..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Utility/BandwidthDisplay.cs +++ /dev/null @@ -1,192 +0,0 @@ -using FishNet.Managing.Statistic; -using UnityEngine; - -namespace FishNet.Component.Utility -{ - /// - /// Add to any object to display current ping(round trip time). - /// - [AddComponentMenu("FishNet/Component/BandwidthDisplay")] - public class BandwidthDisplay : MonoBehaviour - { - #region Types. - private enum Corner - { - TopLeft, - TopRight, - BottomLeft, - BottomRight - } - #endregion - - #region Serialized. - /// - /// Color for text. - /// - [Tooltip("Color for text.")] - [SerializeField] - private Color _color = Color.white; - /// - /// Which corner to display network statistics in. - /// - [Tooltip("Which corner to display network statistics in.")] - [SerializeField] - private Corner _placement = Corner.TopRight; - /// - /// rue to show outgoing data bytes. - /// - [Tooltip("True to show outgoing data bytes.")] - [SerializeField] - private bool _showOutgoing = true; - /// - /// Sets ShowOutgoing value. - /// - /// - public void SetShowOutgoing(bool value) => _showOutgoing = value; - /// - /// True to show incoming data bytes. - /// - [Tooltip("True to show incoming data bytes.")] - [SerializeField] - private bool _showIncoming = true; - /// - /// Sets ShowIncoming value. - /// - /// - public void SetShowIncoming(bool value) => _showIncoming = value; - #endregion - - #region Private. - /// - /// Style for drawn ping. - /// - private GUIStyle _style = new GUIStyle(); - /// - /// Text to show for client in/out data. - /// - private string _clientText; - /// - /// Text to show for server in/out data. - /// - private string _serverText; - /// - /// First found NetworkTrafficStatistics. - /// - private NetworkTraficStatistics _networkTrafficStatistics; - #endregion - - private void Start() - { - _networkTrafficStatistics = InstanceFinder.NetworkManager.StatisticsManager.NetworkTraffic; - //Subscribe to both traffic updates. - _networkTrafficStatistics.OnClientNetworkTraffic += NetworkTraffic_OnClientNetworkTraffic; - _networkTrafficStatistics.OnServerNetworkTraffic += NetworkTraffic_OnServerNetworkTraffic; - - if (!_networkTrafficStatistics.UpdateClient && !_networkTrafficStatistics.UpdateServer) - Debug.LogWarning($"StatisticsManager.NetworkTraffic is not updating for client nor server. To see results ensure your NetworkManager has a StatisticsManager component added with the NetworkTraffic values configured."); - } - - private void OnDestroy() - { - if (_networkTrafficStatistics != null) - { - _networkTrafficStatistics.OnClientNetworkTraffic -= NetworkTraffic_OnClientNetworkTraffic; - _networkTrafficStatistics.OnServerNetworkTraffic -= NetworkTraffic_OnClientNetworkTraffic; - } - } - - - /// - /// Called when client network traffic is updated. - /// - private void NetworkTraffic_OnClientNetworkTraffic(NetworkTrafficArgs obj) - { - string nl = System.Environment.NewLine; - string result = string.Empty; - if (_showIncoming) - result += $"Client In: {NetworkTraficStatistics.FormatBytesToLargest(obj.FromServerBytes)}/s{nl}"; - if (_showOutgoing) - result += $"Client Out: {NetworkTraficStatistics.FormatBytesToLargest(obj.ToServerBytes)}/s{nl}"; - - _clientText = result; - } - - /// - /// Called when client network traffic is updated. - /// - private void NetworkTraffic_OnServerNetworkTraffic(NetworkTrafficArgs obj) - { - string nl = System.Environment.NewLine; - string result = string.Empty; - if (_showIncoming) - result += $"Server In: {NetworkTraficStatistics.FormatBytesToLargest(obj.ToServerBytes)}/s{nl}"; - if (_showOutgoing) - result += $"Server Out: {NetworkTraficStatistics.FormatBytesToLargest(obj.FromServerBytes)}/s{nl}"; - - _serverText = result; - } - - - - private void OnGUI() - { - //No need to perform these actions on server. -#if !UNITY_EDITOR && UNITY_SERVER - return; -#endif - - _style.normal.textColor = _color; - _style.fontSize = 15; - - float width = 100f; - float height = 0f; - if (_showIncoming) - height += 15f; - if (_showOutgoing) - height += 15f; - - bool isClient = InstanceFinder.IsClient; - bool isServer = InstanceFinder.IsServer; - if (!isClient) - _clientText = string.Empty; - if (!isServer) - _serverText = string.Empty; - if (isServer && isClient) - height *= 2f; - - float edge = 10f; - - float horizontal; - float vertical; - - if (_placement == Corner.TopLeft) - { - horizontal = 10f; - vertical = 10f; - _style.alignment = TextAnchor.UpperLeft; - } - else if (_placement == Corner.TopRight) - { - horizontal = Screen.width - width - edge; - vertical = 10f; - _style.alignment = TextAnchor.UpperRight; - } - else if (_placement == Corner.BottomLeft) - { - horizontal = 10f; - vertical = Screen.height - height - edge; - _style.alignment = TextAnchor.LowerLeft; - } - else - { - horizontal = Screen.width - width - edge; - vertical = Screen.height - height - edge; - _style.alignment = TextAnchor.LowerRight; - } - - GUI.Label(new Rect(horizontal, vertical, width, height), (_clientText + _serverText), _style); - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/Utility/BandwidthDisplay.cs.meta b/Assets/FishNet/Runtime/Generated/Component/Utility/BandwidthDisplay.cs.meta deleted file mode 100644 index 95e27f8..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Utility/BandwidthDisplay.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8bc8f0363ddc75946a958043c5e49a83 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Utility/DefaultScene.cs b/Assets/FishNet/Runtime/Generated/Component/Utility/DefaultScene.cs deleted file mode 100644 index 517be13..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Utility/DefaultScene.cs +++ /dev/null @@ -1,239 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing; -using FishNet.Managing.Logging; -using FishNet.Managing.Scened; -using FishNet.Transporting; -using FishNet.Utility; -using System.IO; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnitySceneManager = UnityEngine.SceneManagement.SceneManager; - -/// -/// Add to a NetworkManager object to change between Online and Offline scene based on connection states of the server or client. -/// -[AddComponentMenu("FishNet/Component/DefaultScene")] -public class DefaultScene : MonoBehaviour -{ - - #region Serialized. - [Tooltip("True to load the online scene as global, false to load it as connection.")] - [SerializeField] - private bool _useGlobalScenes = true; - /// - /// True to replace all scenes with the offline scene immediately. - /// - [Tooltip("True to replace all scenes with the offline scene immediately.")] - [SerializeField] - private bool _startInOffline; - /// - /// - /// - [Tooltip("Scene to load when disconnected. Server and client will load this scene.")] - [SerializeField, Scene] - private string _offlineScene; - /// - /// Sets which offline scene to use. - /// - /// Scene name to use as the offline scene. - public void SetOfflineScene(string sceneName) => _offlineScene = sceneName; - /// - /// Scene to load when disconnected. Server and client will load this scene. - /// - /// - public string GetOfflineScene() => _offlineScene; - /// - /// - /// - [Tooltip("Scene to load when connected. Server and client will load this scene.")] - [SerializeField, Scene] - private string _onlineScene; - /// - /// Sets which online scene to use. - /// - /// Scene name to use as the online scene. - public void SetOnlineScene(string sceneName) => _onlineScene = sceneName; - /// - /// Scene to load when connected. Server and client will load this scene. - /// - /// - public string GetOnlineScene() => _onlineScene; - /// - /// Which scenes to replace when loading into OnlineScene. - /// - [Tooltip("Which scenes to replace when loading into OnlineScene.")] - [SerializeField] - private ReplaceOption _replaceScenes = ReplaceOption.All; - #endregion - - #region Private. - /// - /// NetworkManager for this component. - /// - private NetworkManager _networkManager; - #endregion - - private void Awake() - { - InitializeOnce(); - } - - private void OnDestroy() - { - - if (!ApplicationState.IsQuitting() && _networkManager != null && _networkManager.Initialized) - { - _networkManager.ClientManager.OnClientConnectionState -= ClientManager_OnClientConnectionState; - _networkManager.ServerManager.OnServerConnectionState -= ServerManager_OnServerConnectionState; - _networkManager.SceneManager.OnLoadEnd -= SceneManager_OnLoadEnd; - _networkManager.ServerManager.OnAuthenticationResult -= ServerManager_OnAuthenticationResult; - } - } - - /// - /// Initializes this script for use. - /// - private void InitializeOnce() - { - _networkManager = GetComponentInParent(); - if (_networkManager == null) - { - - NetworkManager.StaticLogError($"NetworkManager not found on {gameObject.name} or any parent objects. DefaultScene will not work."); - return; - } - //A NetworkManager won't be initialized if it's being destroyed. - if (!_networkManager.Initialized) - return; - if (_onlineScene == string.Empty || _offlineScene == string.Empty) - { - - NetworkManager.StaticLogWarning("Online or Offline scene is not specified. Default scenes will not load."); - return; - } - - _networkManager.ClientManager.OnClientConnectionState += ClientManager_OnClientConnectionState; - _networkManager.ServerManager.OnServerConnectionState += ServerManager_OnServerConnectionState; - _networkManager.SceneManager.OnLoadEnd += SceneManager_OnLoadEnd; - _networkManager.ServerManager.OnAuthenticationResult += ServerManager_OnAuthenticationResult; - if (_startInOffline) - LoadOfflineScene(); - } - - /// - /// Called when a scene load ends. - /// - private void SceneManager_OnLoadEnd(SceneLoadEndEventArgs obj) - { - bool onlineLoaded = false; - foreach (Scene s in obj.LoadedScenes) - { - if (s.name == GetSceneName(_onlineScene)) - { - onlineLoaded = true; - break; - } - } - - //If online scene was loaded then unload offline. - if (onlineLoaded) - UnloadOfflineScene(); - } - - /// - /// Called after the local server connection state changes. - /// - private void ServerManager_OnServerConnectionState(ServerConnectionStateArgs obj) - { - /* When server starts load online scene as global. - * Since this is a global scene clients will automatically - * join it when connecting. */ - if (obj.ConnectionState == LocalConnectionState.Started) - { - /* If not exactly one server is started then - * that means either none are started, which isnt true because - * we just got a started callback, or two+ are started. - * When a server has already started there's no reason to load - * scenes again. */ - if (!_networkManager.ServerManager.OneServerStarted()) - return; - - //If here can load scene. - SceneLoadData sld = new SceneLoadData(GetSceneName(_onlineScene)); - sld.ReplaceScenes = _replaceScenes; - if (_useGlobalScenes) - _networkManager.SceneManager.LoadGlobalScenes(sld); - else - _networkManager.SceneManager.LoadConnectionScenes(sld); - } - //When server stops load offline scene. - else if (obj.ConnectionState == LocalConnectionState.Stopped) - { - LoadOfflineScene(); - } - } - - /// - /// Called after the local client connection state changes. - /// - private void ClientManager_OnClientConnectionState(ClientConnectionStateArgs obj) - { - if (obj.ConnectionState == LocalConnectionState.Stopped) - { - //Only load offline scene if not also server. - if (!_networkManager.IsServer) - LoadOfflineScene(); - } - } - - /// - /// Called when a client completes authentication. - /// - private void ServerManager_OnAuthenticationResult(NetworkConnection arg1, bool authenticated) - { - /* This is only for loading connection scenes. - * If using global there is no need to continue. */ - if (_useGlobalScenes) - return; - if (!authenticated) - return; - - SceneLoadData sld = new SceneLoadData(GetSceneName(_onlineScene)); - _networkManager.SceneManager.LoadConnectionScenes(arg1, sld); - } - - - /// - /// Loads offlineScene as single. - /// - private void LoadOfflineScene() - { - //Already in offline scene. - if (UnitySceneManager.GetActiveScene().name == GetSceneName(_offlineScene)) - return; - //Only use scene manager if networking scenes. I may add something in later to do both local and networked. - UnitySceneManager.LoadScene(_offlineScene); - } - - /// - /// Unloads the offline scene. - /// - private void UnloadOfflineScene() - { - Scene s = UnitySceneManager.GetSceneByName(GetSceneName(_offlineScene)); - if (string.IsNullOrEmpty(s.name)) - return; - - UnitySceneManager.UnloadSceneAsync(s); - } - - /// - /// Returns a scene name from fullPath. - /// - /// - /// - private string GetSceneName(string fullPath) - { - return Path.GetFileNameWithoutExtension(fullPath); - } -} diff --git a/Assets/FishNet/Runtime/Generated/Component/Utility/DefaultScene.cs.meta b/Assets/FishNet/Runtime/Generated/Component/Utility/DefaultScene.cs.meta deleted file mode 100644 index 317ec62..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Utility/DefaultScene.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 57ce8bbb58966cb45a7140f32da5327a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/Component/Utility/PingDisplay.cs b/Assets/FishNet/Runtime/Generated/Component/Utility/PingDisplay.cs deleted file mode 100644 index be0f714..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Utility/PingDisplay.cs +++ /dev/null @@ -1,118 +0,0 @@ -using FishNet.Managing.Timing; -using UnityEngine; - -namespace FishNet.Component.Utility -{ - /// - /// Add to any object to display current ping(round trip time). - /// - [AddComponentMenu("FishNet/Component/PingDisplay")] - public class PingDisplay : MonoBehaviour - { - #region Types. - private enum Corner - { - TopLeft, - TopRight, - BottomLeft, - BottomRight - } - #endregion - - #region Serialized. - /// - /// Color for text. - /// - [Tooltip("Color for text.")] - [SerializeField] - private Color _color = Color.white; - /// - /// Which corner to display ping in. - /// - [Tooltip("Which corner to display ping in.")] - [SerializeField] - private Corner _placement = Corner.TopRight; - /// - /// True to show the real ping. False to include tick rate latency within the ping. - /// - [Tooltip("True to show the real ping. False to include tick rate latency within the ping.")] - [SerializeField] - private bool _hideTickRate = true; - #endregion - - #region Private. - /// - /// Style for drawn ping. - /// - private GUIStyle _style = new GUIStyle(); - #endregion - - private void OnGUI() - { - //No need to perform these actions on server. -#if !UNITY_EDITOR && UNITY_SERVER - return; -#endif - - //Only clients can see pings. - if (!InstanceFinder.IsClient) - return; - - _style.normal.textColor = _color; - _style.fontSize = 15; - float width = 85f; - float height = 15f; - float edge = 10f; - - float horizontal; - float vertical; - - if (_placement == Corner.TopLeft) - { - horizontal = 10f; - vertical = 10f; - } - else if (_placement == Corner.TopRight) - { - horizontal = Screen.width - width - edge; - vertical = 10f; - } - else if (_placement == Corner.BottomLeft) - { - horizontal = 10f; - vertical = Screen.height - height - edge; - } - else - { - horizontal = Screen.width - width - edge; - vertical = Screen.height - height - edge; - } - - long ping; - TimeManager tm = InstanceFinder.TimeManager; - if (tm == null) - { - ping = 0; - } - else - { - ping = tm.RoundTripTime; - long deduction = 0; - if (_hideTickRate) - { - deduction = (long)(tm.TickDelta * 1000d); - /* If host subtract two ticks, if client only subtract one tick. - * This will reflect the users real ping without the tick rate latency. */ - if (InstanceFinder.IsHost) - deduction *= 2; - } - - ping = (long)Mathf.Max(0, ping - deduction); - } - - GUI.Label(new Rect(horizontal, vertical, width, height), $"Ping: {ping}ms", _style); - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Generated/Component/Utility/PingDisplay.cs.meta b/Assets/FishNet/Runtime/Generated/Component/Utility/PingDisplay.cs.meta deleted file mode 100644 index b0748f0..0000000 --- a/Assets/FishNet/Runtime/Generated/Component/Utility/PingDisplay.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f9b6b565cd9533c4ebc18003f0fc18a2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/SyncTypes.meta b/Assets/FishNet/Runtime/Generated/SyncTypes.meta deleted file mode 100644 index 0f657c7..0000000 --- a/Assets/FishNet/Runtime/Generated/SyncTypes.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: ece5f63c3df26d44497db8aa5892d46a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatch.cs b/Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatch.cs deleted file mode 100644 index 3b0f35c..0000000 --- a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatch.cs +++ /dev/null @@ -1,364 +0,0 @@ -using FishNet.Documenting; -using FishNet.Object.Synchronizing.Internal; -using FishNet.Serializing; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace FishNet.Object.Synchronizing -{ - - /// - /// A SyncObject to efficiently synchronize Stopwatchs over the network. - /// - public class SyncStopwatch : SyncBase, ICustomSync - { - - #region Type. - /// - /// Information about how the Stopwatch has changed. - /// - private struct ChangeData - { - public readonly SyncStopwatchOperation Operation; - public readonly float Previous; - - public ChangeData(SyncStopwatchOperation operation, float previous) - { - Operation = operation; - Previous = previous; - } - } - #endregion - - #region Public. - /// - /// Delegate signature for when the Stopwatch operation occurs. - /// - /// Operation which was performed. - /// Previous value of the Stopwatch. This will be -1f is the value is not available. - /// True if occurring on server. - public delegate void SyncTypeChanged(SyncStopwatchOperation op, float prev, bool asServer); - /// - /// Called when a Stopwatch operation occurs. - /// - public event SyncTypeChanged OnChange; - /// - /// How much time has passed since the Stopwatch started. - /// - public float Elapsed { get; private set; } = -1f; - /// - /// True if the SyncStopwatch is currently paused. Calls to Update(float) will be ignored when paused. - /// - public bool Paused { get; private set; } - #endregion - - #region Private. - /// - /// Changed data which will be sent next tick. - /// - private List _changed = new List(); - /// - /// Server OnChange events waiting for start callbacks. - /// - private readonly List _serverOnChanges = new List(); - /// - /// Client OnChange events waiting for start callbacks. - /// - private readonly List _clientOnChanges = new List(); - #endregion - - /// - /// Starts a Stopwatch. If called when a Stopwatch is already active then StopStopwatch will automatically be sent. - /// - /// Time in which the Stopwatch should start with. - /// True to include remaining time when automatically sending StopStopwatch. - public void StartStopwatch(bool sendElapsedOnStop = true) - { - if (!base.CanNetworkSetValues(true)) - return; - - if (Elapsed > 0f) - StopStopwatch(sendElapsedOnStop); - - Elapsed = 0f; - AddOperation(SyncStopwatchOperation.Start, 0f); - } - - /// - /// Pauses the Stopwatch. Calling while already paused will be result in no action. - /// - /// True to send Remaining with this operation. - public void PauseStopwatch(bool sendElapsed = false) - { - if (Elapsed < 0f) - return; - if (Paused) - return; - if (!base.CanNetworkSetValues(true)) - return; - - Paused = true; - float prev; - SyncStopwatchOperation op; - if (sendElapsed) - { - prev = Elapsed; - op = SyncStopwatchOperation.PauseUpdated; - } - else - { - prev = -1f; - op = SyncStopwatchOperation.Pause; - } - - AddOperation(op, prev); - } - - /// - /// Unpauses the Stopwatch. Calling while already unpaused will be result in no action. - /// - public void UnpauseStopwatch() - { - if (Elapsed < 0f) - return; - if (!Paused) - return; - if (!base.CanNetworkSetValues(true)) - return; - - Paused = false; - AddOperation(SyncStopwatchOperation.Unpause, -1f); - } - - /// - /// Stops and resets the Stopwatch. - /// - public void StopStopwatch(bool sendElapsed = false) - { - if (Elapsed < 0f) - return; - if (!base.CanNetworkSetValues(true)) - return; - - float prev = (sendElapsed) ? -1f : Elapsed; - StopStopwatch_Internal(true); - SyncStopwatchOperation op = (sendElapsed) ? SyncStopwatchOperation.StopUpdated : SyncStopwatchOperation.Stop; - AddOperation(op, prev); - } - - /// - /// Adds an operation to synchronize. - /// - private void AddOperation(SyncStopwatchOperation operation, float prev) - { - if (!base.IsRegistered) - return; - - bool asServerInvoke = (!base.IsNetworkInitialized || base.NetworkBehaviour.IsServer); - - if (asServerInvoke) - { - if (base.Dirty()) - { - ChangeData change = new ChangeData(operation, prev); - _changed.Add(change); - } - } - - OnChange?.Invoke(operation, prev, asServerInvoke); - } - - /// - /// Writes all changed values. - /// - ///True to set the next time data may sync. - public override void WriteDelta(PooledWriter writer, bool resetSyncTick = true) - { - base.WriteDelta(writer, resetSyncTick); - writer.WriteInt32(_changed.Count); - - for (int i = 0; i < _changed.Count; i++) - { - ChangeData change = _changed[i]; - writer.WriteByte((byte)change.Operation); - if (change.Operation == SyncStopwatchOperation.Start) - WriteStartStopwatch(writer, 0f, false); - //Pause and unpause updated need current value written. - //Updated stop also writes current value. - else if (change.Operation == SyncStopwatchOperation.PauseUpdated || change.Operation == SyncStopwatchOperation.StopUpdated) - writer.WriteSingle(change.Previous); - } - - _changed.Clear(); - } - - /// - /// Writes all values. - /// - public override void WriteFull(PooledWriter writer) - { - //Only write full if a Stopwatch is running. - if (Elapsed < 0f) - return; - - base.WriteDelta(writer, false); - - //There will be 1 or 2 entries. If paused 2, if not 1. - int entries = (Paused) ? 2 : 1; - writer.WriteInt32(entries); - //And the operations. - WriteStartStopwatch(writer, Elapsed, true); - if (Paused) - writer.WriteByte((byte)SyncStopwatchOperation.Pause); - } - - /// - /// Writers a start with elapsed time. - /// - /// - private void WriteStartStopwatch(Writer w, float elapsed, bool includeOperationByte) - { - if (includeOperationByte) - w.WriteByte((byte)SyncStopwatchOperation.Start); - - w.WriteSingle(elapsed); - } - - /// - /// Reads and sets the current values for server or client. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [APIExclude] - public override void Read(PooledReader reader, bool asServer) - { - int changes = reader.ReadInt32(); - - for (int i = 0; i < changes; i++) - { - SyncStopwatchOperation op = (SyncStopwatchOperation)reader.ReadByte(); - if (op == SyncStopwatchOperation.Start) - { - float elapsed = reader.ReadSingle(); - if (CanSetValues(asServer)) - Elapsed = elapsed; - InvokeOnChange(op, elapsed, asServer); - } - else if (op == SyncStopwatchOperation.Pause) - { - if (CanSetValues(asServer)) - Paused = true; - InvokeOnChange(op, -1f, asServer); - } - else if (op == SyncStopwatchOperation.PauseUpdated) - { - float prev = reader.ReadSingle(); - if (CanSetValues(asServer)) - Paused = true; - InvokeOnChange(op, prev, asServer); - } - else if (op == SyncStopwatchOperation.Unpause) - { - if (CanSetValues(asServer)) - Paused = false; - InvokeOnChange(op, -1f, asServer); - } - else if (op == SyncStopwatchOperation.Stop) - { - StopStopwatch_Internal(asServer); - InvokeOnChange(op, -1f, false); - } - else if (op == SyncStopwatchOperation.StopUpdated) - { - float prev = reader.ReadSingle(); - StopStopwatch_Internal(asServer); - InvokeOnChange(op, prev, asServer); - } - } - - if (changes > 0) - InvokeOnChange(SyncStopwatchOperation.Complete, -1f, asServer); - } - - /// - /// Returns if values can be updated. - /// - private bool CanSetValues(bool asServer) - { - return (asServer || !base.NetworkManager.IsServer); - } - - /// - /// Stops the Stopwatch and resets. - /// - private void StopStopwatch_Internal(bool asServer) - { - if (!CanSetValues(asServer)) - return; - - Paused = false; - Elapsed = -1f; - } - - - /// - /// Invokes OnChanged callback. - /// - private void InvokeOnChange(SyncStopwatchOperation operation, float prev, bool asServer) - { - if (asServer) - { - if (base.NetworkBehaviour.OnStartServerCalled) - OnChange?.Invoke(operation, prev, asServer); - else - _serverOnChanges.Add(new ChangeData(operation, prev)); - } - else - { - if (base.NetworkBehaviour.OnStartClientCalled) - OnChange?.Invoke(operation, prev, asServer); - else - _clientOnChanges.Add(new ChangeData(operation, prev)); - } - } - - - /// - /// Called after OnStartXXXX has occurred. - /// - /// True if OnStartServer was called, false if OnStartClient. - public override void OnStartCallback(bool asServer) - { - base.OnStartCallback(asServer); - List collection = (asServer) ? _serverOnChanges : _clientOnChanges; - - if (OnChange != null) - { - foreach (ChangeData item in collection) - OnChange.Invoke(item.Operation, item.Previous, asServer); - } - - collection.Clear(); - } - - /// - /// Removes delta from Remaining for server and client. - /// - /// Value to remove from Remaining. - public void Update(float delta) - { - //Not enabled. - if (Elapsed == -1f) - return; - if (Paused) - return; - - Elapsed += delta; - } - - /// - /// Return the serialized type. - /// - /// - public object GetSerializedType() => null; - } -} diff --git a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatch.cs.meta b/Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatch.cs.meta deleted file mode 100644 index 813b449..0000000 --- a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatch.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5b06067fb219c724785a23c4f15e9a2a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatchOperation.cs b/Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatchOperation.cs deleted file mode 100644 index 9ebd17b..0000000 --- a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatchOperation.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace FishNet.Object.Synchronizing -{ - - public enum SyncStopwatchOperation : byte - { - /// - /// Stopwatch is started. Value is included with start. - /// - Start = 1, - /// - /// Stopwatch was paused. - /// - Pause = 2, - /// - /// Stopwatch was paused. Value at time of pause is sent. - /// - PauseUpdated = 3, - /// - /// Stopwatch was unpaused. - /// - Unpause = 4, - /// - /// Stopwatch was stopped. - /// - Stop = 6, - /// - /// Stopwatch was stopped. Value prior to stopping is sent. - /// - StopUpdated = 7, - /// - /// All operations for the tick have been processed. This only occurs on clients as the server is unable to be aware of when the user is done modifying the list. - /// - Complete = 9, - } - -} diff --git a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatchOperation.cs.meta b/Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatchOperation.cs.meta deleted file mode 100644 index 0d89456..0000000 --- a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncStopwatchOperation.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3ef101e3b1527224ca96ef61c238adbb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimer.cs b/Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimer.cs deleted file mode 100644 index d9f844c..0000000 --- a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimer.cs +++ /dev/null @@ -1,407 +0,0 @@ -using FishNet.Documenting; -using FishNet.Object.Synchronizing.Internal; -using FishNet.Serializing; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace FishNet.Object.Synchronizing -{ - - /// - /// A SyncObject to efficiently synchronize timers over the network. - /// - public class SyncTimer : SyncBase, ICustomSync - { - - #region Type. - /// - /// Information about how the timer has changed. - /// - private struct ChangeData - { - public readonly SyncTimerOperation Operation; - public readonly float Previous; - public readonly float Next; - - public ChangeData(SyncTimerOperation operation, float previous, float next) - { - Operation = operation; - Previous = previous; - Next = next; - } - } - #endregion - - #region Public. - /// - /// Delegate signature for when the timer operation occurs. - /// - /// Operation which was performed. - /// Previous value of the timer. This will be -1f is the value is not available. - /// Value of the timer. This will be -1f is the value is not available. - /// True if occurring on server. - public delegate void SyncTypeChanged(SyncTimerOperation op, float prev, float next, bool asServer); - /// - /// Called when a timer operation occurs. - /// - public event SyncTypeChanged OnChange; - /// - /// Time remaining on the timer. When the timer is expired this value will be 0f. - /// - public float Remaining { get; private set; } - /// - /// How much time has passed since the timer started. - /// - public float Elapsed => (Duration - Remaining); - /// - /// Starting duration of the timer. - /// - public float Duration { get; private set; } - /// - /// True if the SyncTimer is currently paused. Calls to Update(float) will be ignored when paused. - /// - public bool Paused { get; private set; } - #endregion - - #region Private. - /// - /// Changed data which will be sent next tick. - /// - private List _changed = new List(); - /// - /// Server OnChange events waiting for start callbacks. - /// - private readonly List _serverOnChanges = new List(); - /// - /// Client OnChange events waiting for start callbacks. - /// - private readonly List _clientOnChanges = new List(); - - #endregion - - /// - /// Starts a timer. If called when a timer is already active then StopTimer will automatically be sent. - /// - /// Time in which the timer should start with. - /// True to include remaining time when automatically sending StopTimer. - public void StartTimer(float remaining, bool sendRemainingOnStop = true) - { - if (!base.CanNetworkSetValues(true)) - return; - - if (Remaining > 0f) - StopTimer(sendRemainingOnStop); - - Paused = false; - Remaining = remaining; - Duration = remaining; - AddOperation(SyncTimerOperation.Start, -1f, remaining); - } - - /// - /// Pauses the timer. Calling while already paused will be result in no action. - /// - /// True to send Remaining with this operation. - public void PauseTimer(bool sendRemaining = false) - { - if (Remaining <= 0f) - return; - if (Paused) - return; - if (!base.CanNetworkSetValues(true)) - return; - - Paused = true; - SyncTimerOperation op = (sendRemaining) ? SyncTimerOperation.PauseUpdated : SyncTimerOperation.Pause; - AddOperation(op, -1f, -1f); - } - - /// - /// Unpauses the timer. Calling while already unpaused will be result in no action. - /// - public void UnpauseTimer() - { - if (Remaining <= 0f) - return; - if (!Paused) - return; - if (!base.CanNetworkSetValues(true)) - return; - - Paused = false; - AddOperation(SyncTimerOperation.Unpause, -1f, -1f); - } - - /// - /// Stops and resets the timer. - /// - public void StopTimer(bool sendRemaining = false) - { - if (Remaining <= 0f) - return; - if (!base.CanNetworkSetValues(true)) - return; - - bool asServer = true; - float prev = Remaining; - StopTimer_Internal(asServer); - SyncTimerOperation op = (sendRemaining) ? SyncTimerOperation.StopUpdated : SyncTimerOperation.Stop; - AddOperation(op, prev, 0f); - } - - /// - /// Adds an operation to synchronize. - /// - private void AddOperation(SyncTimerOperation operation, float prev, float next) - { - if (!base.IsRegistered) - return; - - bool asServerInvoke = (!base.IsNetworkInitialized || base.NetworkBehaviour.IsServer); - - if (asServerInvoke) - { - if (base.Dirty()) - { - ChangeData change = new ChangeData(operation, prev, next); - _changed.Add(change); - } - } - - OnChange?.Invoke(operation, prev, next, asServerInvoke); - } - - /// - /// Writes all changed values. - /// - ///True to set the next time data may sync. - public override void WriteDelta(PooledWriter writer, bool resetSyncTick = true) - { - base.WriteDelta(writer, resetSyncTick); - writer.WriteInt32(_changed.Count); - - for (int i = 0; i < _changed.Count; i++) - { - ChangeData change = _changed[i]; - writer.WriteByte((byte)change.Operation); - - if (change.Operation == SyncTimerOperation.Start) - { - WriteStartTimer(writer, false); - } - //Pause and unpause updated need current value written. - //Updated stop also writes current value. - else if (change.Operation == SyncTimerOperation.PauseUpdated || change.Operation == SyncTimerOperation.StopUpdated) - { - writer.WriteSingle(change.Next); - } - } - - _changed.Clear(); - } - - /// - /// Writes all values. - /// - public override void WriteFull(PooledWriter writer) - { - //Only write full if a timer is running. - if (Remaining <= 0f) - return; - - base.WriteDelta(writer, false); - //There will be 1 or 2 entries. If paused 2, if not 1. - int entries = (Paused) ? 2 : 1; - writer.WriteInt32(entries); - //And the operations. - WriteStartTimer(writer, true); - if (Paused) - writer.WriteByte((byte)SyncTimerOperation.Pause); - } - - /// - /// Writes a StartTimer operation. - /// - /// - /// - private void WriteStartTimer(Writer w, bool includeOperationByte) - { - if (includeOperationByte) - w.WriteByte((byte)SyncTimerOperation.Start); - w.WriteSingle(Remaining); - w.WriteSingle(Duration); - } - - /// - /// Returns if values can be updated. - /// - private bool CanSetValues(bool asServer) - { - return (asServer || !base.NetworkManager.IsServer); - } - - /// - /// Reads and sets the current values for server or client. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [APIExclude] - public override void Read(PooledReader reader, bool asServer) - { - int changes = reader.ReadInt32(); - - for (int i = 0; i < changes; i++) - { - SyncTimerOperation op = (SyncTimerOperation)reader.ReadByte(); - if (op == SyncTimerOperation.Start) - { - float next = reader.ReadSingle(); - float duration = reader.ReadSingle(); - if (CanSetValues(asServer)) - { - Paused = false; - Remaining = next; - Duration = duration; - } - InvokeOnChange(op, -1f, next, asServer); - } - else if (op == SyncTimerOperation.Pause || op == SyncTimerOperation.PauseUpdated - || op == SyncTimerOperation.Unpause) - { - UpdatePauseState(op); - } - else if (op == SyncTimerOperation.Stop) - { - float prev = Remaining; - StopTimer_Internal(asServer); - InvokeOnChange(op, prev, 0f, false); - } - // - else if (op == SyncTimerOperation.StopUpdated) - { - float prev = Remaining; - float next = reader.ReadSingle(); - StopTimer_Internal(asServer); - InvokeOnChange(op, prev, next, asServer); - } - } - - //Updates a pause state with a pause or unpause operation. - void UpdatePauseState(SyncTimerOperation op) - { - bool newPauseState = (op == SyncTimerOperation.Pause || op == SyncTimerOperation.PauseUpdated); - - float prev = -1f; - float next = -1f; - //If updated time as well. - if (op == SyncTimerOperation.PauseUpdated) - { - prev = Remaining; - next = reader.ReadSingle(); - if (CanSetValues(asServer)) - Remaining = next; - } - - if (CanSetValues(asServer)) - Paused = newPauseState; - InvokeOnChange(op, prev, next, asServer); - } - - if (changes > 0) - InvokeOnChange(SyncTimerOperation.Complete, -1f, -1f, false); - } - - /// - /// Stops the timer and resets. - /// - private void StopTimer_Internal(bool asServer) - { - if (!CanSetValues(asServer)) - return; - - Paused = false; - Remaining = 0f; - } - - - /// - /// Invokes OnChanged callback. - /// - private void InvokeOnChange(SyncTimerOperation operation, float prev, float next, bool asServer) - { - if (asServer) - { - if (base.NetworkBehaviour.OnStartServerCalled) - OnChange?.Invoke(operation, prev, next, asServer); - else - _serverOnChanges.Add(new ChangeData(operation, prev, next)); - } - else - { - if (base.NetworkBehaviour.OnStartClientCalled) - OnChange?.Invoke(operation, prev, next, asServer); - else - _clientOnChanges.Add(new ChangeData(operation, prev, next)); - } - } - - - /// - /// Called after OnStartXXXX has occurred. - /// - /// True if OnStartServer was called, false if OnStartClient. - public override void OnStartCallback(bool asServer) - { - base.OnStartCallback(asServer); - List collection = (asServer) ? _serverOnChanges : _clientOnChanges; - - if (OnChange != null) - { - foreach (ChangeData item in collection) - OnChange.Invoke(item.Operation, item.Previous, item.Next, asServer); - } - - collection.Clear(); - } - - /// - /// Removes delta from Remaining for server and client. - /// - /// Value to remove from Remaining. - public void Update(float delta) - { - //Not enabled. - if (Remaining <= 0f) - return; - if (Paused) - return; - - if (delta < 0) - delta *= -1f; - float prev = Remaining; - Remaining -= delta; - //Still time left. - if (Remaining > 0f) - return; - - /* If here then the timer has - * ended. Invoking the events is tricky - * here because both the server and the client - * would share the same value. Because of this check - * if each socket is started and if so invoke for that - * side. There's a chance down the road this may need to be improved - * for some but at this time I'm unable to think of any - * problems. */ - Remaining = 0f; - if (base.NetworkManager.IsServer) - OnChange?.Invoke(SyncTimerOperation.Finished, prev, 0f, true); - if (base.NetworkManager.IsClient) - OnChange?.Invoke(SyncTimerOperation.Finished, prev, 0f, false); - } - - /// - /// Return the serialized type. - /// - /// - public object GetSerializedType() => null; - } -} diff --git a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimer.cs.meta b/Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimer.cs.meta deleted file mode 100644 index d513c5e..0000000 --- a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6abdbcaa07147024fbe99c2813126910 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimerOperation.cs b/Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimerOperation.cs deleted file mode 100644 index af95e7b..0000000 --- a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimerOperation.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace FishNet.Object.Synchronizing -{ - - public enum SyncTimerOperation : byte - { - /// - /// Timer is started. Value is included with start. - /// - Start = 1, - /// - /// Timer was paused. - /// - Pause = 2, - /// - /// Timer was paused. Value at time of pause is sent. - /// - PauseUpdated = 3, - /// - /// Timer was unpaused. - /// - Unpause = 4, - /// - /// Timer was stopped. - /// - Stop = 6, - /// - /// Timer was stopped. Value prior to stopping is sent. - /// - StopUpdated = 7, - /// - /// The timer has ended finished it's duration. - /// - Finished = 8, - /// - /// All operations for the tick have been processed. This only occurs on clients as the server is unable to be aware of when the user is done modifying the list. - /// - Complete = 9, - } - -} diff --git a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimerOperation.cs.meta b/Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimerOperation.cs.meta deleted file mode 100644 index ee8e489..0000000 --- a/Assets/FishNet/Runtime/Generated/SyncTypes/SyncTimerOperation.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c7732c822303d3c4387a4af44467e791 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/InstanceFinder.cs b/Assets/FishNet/Runtime/InstanceFinder.cs deleted file mode 100644 index 20d230b..0000000 --- a/Assets/FishNet/Runtime/InstanceFinder.cs +++ /dev/null @@ -1,219 +0,0 @@ -using FishNet.Component.ColliderRollback; -using FishNet.Managing; -using FishNet.Managing.Client; -using FishNet.Managing.Predicting; -using FishNet.Managing.Scened; -using FishNet.Managing.Server; -using FishNet.Managing.Statistic; -using FishNet.Managing.Timing; -using FishNet.Managing.Transporting; -using FishNet.Utility; -using System; -using System.Linq; -using UnityEngine; - -namespace FishNet -{ - - /// - /// Used to globally get information from the first found instance of NetworkManager. - /// - public static class InstanceFinder - { - - #region Public. - /// - /// Returns the first found NetworkManager instance. - /// - public static NetworkManager NetworkManager - { - get - { - if (_networkManager == null) - { - int managersCount = NetworkManager.Instances.Count; - //At least one manager. - if (managersCount > 0) - { - _networkManager = NetworkManager.Instances.First(); - if (managersCount > 1) - _networkManager.LogWarning($"Multiple NetworkManagers found, the first result will be returned. If you only wish to have one NetworkManager then uncheck 'Allow Multiple' within your NetworkManagers."); - } - //No managers. - else - { - //If application is quitting return null without logging. - if (ApplicationState.IsQuitting()) - return null; - - Debug.Log($"NetworkManager not found in any open scenes."); - } - } - - return _networkManager; - } - } - - /// - /// Returns the first instance of ServerManager. - /// - public static ServerManager ServerManager - { - get - { - NetworkManager nm = NetworkManager; - return (nm == null) ? null : nm.ServerManager; - } - } - - /// - /// Returns the first instance of ClientManager. - /// - public static ClientManager ClientManager - { - get - { - NetworkManager nm = NetworkManager; - return (nm == null) ? null : nm.ClientManager; - } - } - - /// - /// Returns the first instance of TransportManager. - /// - public static TransportManager TransportManager - { - get - { - NetworkManager nm = NetworkManager; - return (nm == null) ? null : nm.TransportManager; - } - } - - /// - /// Returns the first instance of TimeManager. - /// - public static TimeManager TimeManager - { - get - { - NetworkManager nm = NetworkManager; - return (nm == null) ? null : nm.TimeManager; - } - } - - /// - /// Returns the first instance of SceneManager. - /// - public static SceneManager SceneManager - { - get - { - NetworkManager nm = NetworkManager; - return (nm == null) ? null : nm.SceneManager; - } - } - /// - /// Returns the first instance of RollbackManager. - /// - public static RollbackManager RollbackManager - { - get - { - NetworkManager nm = NetworkManager; - return (nm == null) ? null : nm.RollbackManager; - } - } - /// - /// Returns the first instance of PredictionManager. - /// - public static PredictionManager PredictionManager - { - get - { - NetworkManager nm = NetworkManager; - return (nm == null) ? null : nm.PredictionManager; - } - } - /// - /// Returns the first instance of StatisticsManager. - /// - public static StatisticsManager StatisticsManager - { - get - { - NetworkManager nm = NetworkManager; - return (nm == null) ? null : nm.StatisticsManager; - } - } - - /// - /// True if the server is active. - /// - public static bool IsServer => (NetworkManager == null) ? false : NetworkManager.IsServer; - /// - /// True if only the server is active. - /// - public static bool IsServerOnly => (NetworkManager == null) ? false : NetworkManager.IsServerOnly; - /// - /// True if the client is active and authenticated. - /// - public static bool IsClient => (NetworkManager == null) ? false : NetworkManager.IsClient; - /// - /// True if only the client is active and authenticated. - /// - public static bool IsClientOnly => (NetworkManager == null) ? false : NetworkManager.IsClientOnly; - /// - /// True if client and server are active. - /// - public static bool IsHost => (NetworkManager == null) ? false : NetworkManager.IsHost; - /// - /// True if client nor server are active. - /// - public static bool IsOffline => (_networkManager == null) ? true : (!NetworkManager.IsServer && !NetworkManager.IsClient); - #endregion - - #region Private. - /// - /// NetworkManager instance. - /// - private static NetworkManager _networkManager; - #endregion - - #region Registered components - /// - /// Registers to invoke an action when a specified component becomes registered. Action will invoke immediately if already registered. - /// - /// Component type. - /// Action to invoke. - public static void RegisterInvokeOnInstance(Action handler) where T : UnityEngine.Component => NetworkManager?.RegisterInvokeOnInstance(handler); - /// - /// Unrgisters to invoke an action when a specified component becomes registered. Action will invoke immediately if already registered. - /// - /// Component type. - /// Action to invoke. - public static void UnregisterInvokeOnInstance(Action handler) where T : UnityEngine.Component => NetworkManager?.UnregisterInvokeOnInstance(handler); - /// - /// Returns class of type if found within CodegenBase classes. - /// - /// - /// - public static T GetInstance() where T : UnityEngine.Component => NetworkManager?.GetInstance(); - /// - /// Registers a new component to this NetworkManager. - /// - /// Type to register. - /// Reference of the component being registered. - /// True to replace existing references. - public static void RegisterInstance(T component, bool replace = true) where T : UnityEngine.Component => NetworkManager?.RegisterInstance(component, replace); - /// - /// Unregisters a component from this NetworkManager. - /// - /// Type to unregister. - public static void UnregisterInstance() where T : UnityEngine.Component => NetworkManager?.UnregisterInstance(); - #endregion - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/InstanceFinder.cs.meta b/Assets/FishNet/Runtime/InstanceFinder.cs.meta deleted file mode 100644 index 97dc53c..0000000 --- a/Assets/FishNet/Runtime/InstanceFinder.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 528668525d755164d989cddc73e3eee5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing.meta b/Assets/FishNet/Runtime/Managing.meta deleted file mode 100644 index f77c46d..0000000 --- a/Assets/FishNet/Runtime/Managing.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 2881da549094ec241b3a289e6151869e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Client.meta b/Assets/FishNet/Runtime/Managing/Client.meta deleted file mode 100644 index 1d0fe06..0000000 --- a/Assets/FishNet/Runtime/Managing/Client.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 96f81f64930875143840663a13e78564 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Client/ClientManager.Broadcast.cs b/Assets/FishNet/Runtime/Managing/Client/ClientManager.Broadcast.cs deleted file mode 100644 index c45b32a..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/ClientManager.Broadcast.cs +++ /dev/null @@ -1,179 +0,0 @@ -using FishNet.Broadcast; -using FishNet.Broadcast.Helping; -using FishNet.Managing.Logging; -using FishNet.Managing.Utility; -using FishNet.Object.Helping; -using FishNet.Serializing; -using FishNet.Serializing.Helping; -using FishNet.Transporting; -using FishNet.Utility.Extension; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Managing.Client -{ - public sealed partial class ClientManager : MonoBehaviour - { - #region Private. - /// - /// Delegate to read received broadcasts. - /// - /// - private delegate void ServerBroadcastDelegate(PooledReader reader); - /// - /// Delegates for each key. - /// - private readonly Dictionary> _broadcastHandlers = new Dictionary>(); - /// - /// Delegate targets for each key. - /// - private Dictionary> _handlerTargets = new Dictionary>(); - #endregion - - /// - /// Registers a method to call when a Broadcast arrives. - /// - /// Type of broadcast being registered. - /// Method to call. - public void RegisterBroadcast(Action handler) where T : struct, IBroadcast - { - ushort key = typeof(T).FullName.GetStableHash16(); - /* Create delegate and add for - * handler method. */ - HashSet handlers; - if (!_broadcastHandlers.TryGetValueIL2CPP(key, out handlers)) - { - handlers = new HashSet(); - _broadcastHandlers.Add(key, handlers); - } - ServerBroadcastDelegate del = CreateBroadcastDelegate(handler); - handlers.Add(del); - - /* Add hashcode of target for handler. - * This is so we can unregister the target later. */ - int handlerHashCode = handler.GetHashCode(); - HashSet<(int, ServerBroadcastDelegate)> targetHashCodes; - if (!_handlerTargets.TryGetValueIL2CPP(key, out targetHashCodes)) - { - targetHashCodes = new HashSet<(int, ServerBroadcastDelegate)>(); - _handlerTargets.Add(key, targetHashCodes); - } - - targetHashCodes.Add((handlerHashCode, del)); - } - - /// - /// Unregisters a method call from a Broadcast type. - /// - /// Type of broadcast being unregistered. - /// Method to unregister. - public void UnregisterBroadcast(Action handler) where T : struct, IBroadcast - { - ushort key = BroadcastHelper.GetKey(); - - /* If key is found for T then look for - * the appropriate handler to remove. */ - if (_broadcastHandlers.TryGetValueIL2CPP(key, out HashSet handlers)) - { - HashSet<(int, ServerBroadcastDelegate)> targetHashCodes; - if (_handlerTargets.TryGetValueIL2CPP(key, out targetHashCodes)) - { - int handlerHashCode = handler.GetHashCode(); - ServerBroadcastDelegate result = null; - foreach ((int targetHashCode, ServerBroadcastDelegate del) in targetHashCodes) - { - if (targetHashCode == handlerHashCode) - { - result = del; - targetHashCodes.Remove((targetHashCode, del)); - break; - } - } - //If no more in targetHashCodes then remove from handlerTarget. - if (targetHashCodes.Count == 0) - _handlerTargets.Remove(key); - - if (result != null) - handlers.Remove(result); - } - - //If no more in handlers then remove broadcastHandlers. - if (handlers.Count == 0) - _broadcastHandlers.Remove(key); - } - } - - /// - /// Creates a ServerBroadcastDelegate. - /// - /// - /// - /// - /// - private ServerBroadcastDelegate CreateBroadcastDelegate(Action handler) - { - void LogicContainer(PooledReader reader) - { - T broadcast = reader.Read(); - handler?.Invoke(broadcast); - } - return LogicContainer; - } - - /// - /// Parses a received broadcast. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ParseBroadcast(PooledReader reader, Channel channel) - { - ushort key = reader.ReadUInt16(); - int dataLength = Packets.GetPacketLength((ushort)PacketId.Broadcast, reader, channel); - // try to invoke the handler for that message - if (_broadcastHandlers.TryGetValueIL2CPP(key, out HashSet handlers)) - { - int readerStartPosition = reader.Position; - /* //muchlater resetting the position could be better by instead reading once and passing in - * the object to invoke with. */ - foreach (ServerBroadcastDelegate handler in handlers) - { - reader.Position = readerStartPosition; - handler.Invoke(reader); - } - } - else - { - reader.Skip(dataLength); - } - } - - - /// - /// Sends a Broadcast to the server. - /// - /// Type of broadcast to send. - /// Broadcast data being sent; for example: an instance of your broadcast type. - /// Channel to send on. - public void Broadcast(T message, Channel channel = Channel.Reliable) where T : struct, IBroadcast - { - //Check local connection state. - if (!Started) - { - NetworkManager.LogWarning($"Cannot send broadcast to server because client is not active."); - return; - } - - using (PooledWriter writer = WriterPool.GetWriter()) - { - Broadcasts.WriteBroadcast(writer, message, channel); - ArraySegment segment = writer.GetArraySegment(); - - NetworkManager.TransportManager.SendToServer((byte)channel, segment); - } - } - - } - - -} diff --git a/Assets/FishNet/Runtime/Managing/Client/ClientManager.Broadcast.cs.meta b/Assets/FishNet/Runtime/Managing/Client/ClientManager.Broadcast.cs.meta deleted file mode 100644 index 6b82d50..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/ClientManager.Broadcast.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 97ef4be4cfcc6a54d80a65a5c8d325d7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Client/ClientManager.LOD.cs b/Assets/FishNet/Runtime/Managing/Client/ClientManager.LOD.cs deleted file mode 100644 index 437132d..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/ClientManager.LOD.cs +++ /dev/null @@ -1,197 +0,0 @@ -using FishNet.Managing.Timing; -using FishNet.Object; -using FishNet.Serializing; -using FishNet.Transporting; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.Managing.Client -{ - public sealed partial class ClientManager : MonoBehaviour - { - #region Internal. - /// - /// How many ticks between each LOD update. - /// - public uint LevelOfDetailInterval => NetworkManager.TimeManager.TimeToTicks(0.5d, TickRounding.RoundUp); - #endregion - - #region Private. - /// - /// Positions of the player objects. - /// - private List _objectsPositionsCache = new List(); - /// - /// Next index within Spawned to update the LOD on. - /// - private int _nextLodNobIndex; - #endregion - - /// - /// Sends a level of update if conditions are met. - /// - /// True to force send a full update immediately. - /// This may be useful when teleporting clients. - /// This must be called by on the server by using ServerManager.ForceLodUpdate(NetworkConnection). - /// - internal void SendLodUpdate(bool forceFullUpdate) - { - if (!Connection.Authenticated) - return; - NetworkManager nm = NetworkManager; - if (forceFullUpdate) - { - nm.LogError($"ForceFullUpdate is not yet implemented. Setting this true should not be possible."); - return; - } - if (!nm.ObserverManager.GetUseNetworkLod()) - return; - - //Interval check. - uint localTick = nm.TimeManager.LocalTick; - uint intervalRequirement = LevelOfDetailInterval; - bool intervalMet = ((localTick - Connection.LastLevelOfDetailUpdate) >= intervalRequirement); - if (!forceFullUpdate && !intervalMet) - return; - - //Set next tick. - Connection.LastLevelOfDetailUpdate = localTick; - - List localClientSpawned = nm.ClientManager.Objects.LocalClientSpawned; - int spawnedCount = localClientSpawned.Count; - if (spawnedCount == 0) - return; - - //Rebuild position cache for players objects. - _objectsPositionsCache.Clear(); - foreach (NetworkObject playerObjects in Connection.Objects) - _objectsPositionsCache.Add(playerObjects.transform.position); - - /* Set the maximum number of entries per send. - * Each send is going to be approximately 3 bytes - * but sometimes can be 4. Calculate based off the maximum - * possible bytes. */ - //int mtu = NetworkManager.TransportManager.GetMTU((byte)Channel.Reliable); - const int estimatedMaximumIterations = ( 400 / 4); - /* Aim to process all objects over at most 10 seconds. - * To reduce the number of packets sent objects are - * calculated ~twice a second. This means if the client had - * 1000 objects visible to them they would need to process - * 100 objects a second, so 50 objects every half a second. - * This should be no problem even on slower mobile devices. */ - int iterations; - //Normal update. - if (!forceFullUpdate) - { - iterations = Mathf.Min(spawnedCount, estimatedMaximumIterations); - } - //Force does a full update. - else - { - _nextLodNobIndex = 0; - iterations = spawnedCount; - } - - //Cache a few more things. - Dictionary currentLods = Connection.LevelOfDetails; - List lodDistances = NetworkManager.ObserverManager.GetLevelOfDetailDistances(); - - //Index to use next is too high so reset it. - if (_nextLodNobIndex >= spawnedCount) - _nextLodNobIndex = 0; - int nobIndex = _nextLodNobIndex; - - PooledWriter tmpWriter = WriterPool.GetWriter(1000); - int written = 0; - - //Only check if player has objects. - if (_objectsPositionsCache.Count > 0) - { - for (int i = 0; i < iterations; i++) - { - NetworkObject nob = localClientSpawned[nobIndex]; - //Somehow went null. Can occur perhaps if client destroys objects between ticks maybe. - if (nob == null) - { - IncreaseObjectIndex(); - continue; - } - //Only check objects not owned by the local client. - if (!nob.IsOwner && !nob.IsDeinitializing) - { - Vector3 nobPosition = nob.transform.position; - float closestDistance = float.MaxValue; - foreach (Vector3 objPosition in _objectsPositionsCache) - { - float dist = Vector3.SqrMagnitude(nobPosition - objPosition); - if (dist < closestDistance) - closestDistance = dist; - } - - //If not within any distances then max lod will be used, the value below. - byte lod = (byte)(lodDistances.Count - 1); - for (byte z = 0; z < lodDistances.Count; z++) - { - //Distance is within range of this lod. - if (closestDistance <= lodDistances[z]) - { - lod = z; - break; - } - } - - bool changed; - /* See if value changed. Value is changed - * if it's not the same of old or if - * the nob has not yet been added to the - * level of details collection. - * Even if a forced update only delta - * needs to send. */ - if (currentLods.TryGetValue(nob, out byte oldLod)) - changed = (oldLod != lod); - else - changed = true; - - //If changed then set new value and write. - if (changed) - { - currentLods[nob] = lod; - tmpWriter.WriteNetworkObjectId(nob.ObjectId); - tmpWriter.WriteByte(lod); - written++; - } - } - - IncreaseObjectIndex(); - - void IncreaseObjectIndex() - { - nobIndex++; - if (nobIndex >= spawnedCount) - nobIndex = 0; - } - } - } - - //Set next lod index to current nob index. - _nextLodNobIndex = nobIndex; - /* Send using the reliable channel since - * we are using deltas. This is also why - * updates are sent larger chunked twice a second rather - * than smaller chunks regularly. */ - PooledWriter writer = WriterPool.GetWriter(1000); - writer.WritePacketId(PacketId.NetworkLODUpdate); - writer.WriteInt32(written); - writer.WriteArraySegment(tmpWriter.GetArraySegment()); - NetworkManager.TransportManager.SendToServer((byte)Channel.Reliable, writer.GetArraySegment(), true); - - //Dispose writers. - writer.DisposeLength(); - tmpWriter.DisposeLength(); - } - - - } - - -} diff --git a/Assets/FishNet/Runtime/Managing/Client/ClientManager.LOD.cs.meta b/Assets/FishNet/Runtime/Managing/Client/ClientManager.LOD.cs.meta deleted file mode 100644 index c7469a2..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/ClientManager.LOD.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 249df1192f06801488309cd13fd2b8ef -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Client/ClientManager.cs b/Assets/FishNet/Runtime/Managing/Client/ClientManager.cs deleted file mode 100644 index ef9be20..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/ClientManager.cs +++ /dev/null @@ -1,503 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing.Debugging; -using FishNet.Managing.Logging; -using FishNet.Managing.Server; -using FishNet.Managing.Transporting; -using FishNet.Serializing; -using FishNet.Transporting; -using FishNet.Utility.Extension; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.Managing.Client -{ - /// - /// A container for local client data and actions. - /// - [DisallowMultipleComponent] - [AddComponentMenu("FishNet/Manager/ClientManager")] - public sealed partial class ClientManager : MonoBehaviour - { - #region Public. - /// - /// Called after local client has authenticated. - /// - public event Action OnAuthenticated; - /// - /// Called after the local client connection state changes. - /// - public event Action OnClientConnectionState; - /// - /// Called when a client other than self connects. - /// This is only available when using ServerManager.ShareIds. - /// - public event Action OnRemoteConnectionState; - /// - /// True if the client connection is connected to the server. - /// - public bool Started { get; private set; } - /// - /// NetworkConnection the local client is using to send data to the server. - /// - public NetworkConnection Connection = NetworkManager.EmptyConnection; - /// - /// Handling and information for objects known to the local client. - /// - public ClientObjects Objects { get; private set; } - /// - /// All currently connected clients. This field only contains data while ServerManager.ShareIds is enabled. - /// - public Dictionary Clients = new Dictionary(); - /// - /// NetworkManager for client. - /// - [HideInInspector] - public NetworkManager NetworkManager { get; private set; } - #endregion - - #region Serialized. - /// - /// True to automatically set the frame rate when the client connects. - /// - [Tooltip("True to automatically set the frame rate when the client connects.")] - [SerializeField] - private bool _changeFrameRate = true; - /// - /// - /// - [Tooltip("Maximum frame rate the client may run at. When as host this value runs at whichever is higher between client and server.")] - [Range(1, NetworkManager.MAXIMUM_FRAMERATE)] - [SerializeField] - private ushort _frameRate = NetworkManager.MAXIMUM_FRAMERATE; - /// - /// Maximum frame rate the client may run at. When as host this value runs at whichever is higher between client and server. - /// - internal ushort FrameRate => (_changeFrameRate) ? _frameRate : (ushort)0; - #endregion - - #region Private. - /// - /// Used to read splits. - /// - private SplitReader _splitReader = new SplitReader(); -#if UNITY_EDITOR || DEVELOPMENT_BUILD - /// - /// Logs data about parser to help debug. - /// - private ParseLogger _parseLogger = new ParseLogger(); -#endif - #endregion - - private void OnDestroy() - { - Objects?.SubscribeToSceneLoaded(false); - } - - - /// - /// Initializes this script for use. - /// - /// - internal void InitializeOnce_Internal(NetworkManager manager) - { - NetworkManager = manager; - Objects = new ClientObjects(manager); - Objects.SubscribeToSceneLoaded(true); - /* Unsubscribe before subscribing. - * Shouldn't be an issue but better safe than sorry. */ - SubscribeToEvents(false); - SubscribeToEvents(true); - //Listen for client connections from server. - RegisterBroadcast(OnClientConnectionBroadcast); - RegisterBroadcast(OnConnectedClientsBroadcast); - } - - - /// - /// Called when the server sends a connection state change for any client. - /// - /// - private void OnClientConnectionBroadcast(ClientConnectionChangeBroadcast args) - { - //If connecting invoke after added to clients, otherwise invoke before removed. - RemoteConnectionStateArgs rcs = new RemoteConnectionStateArgs((args.Connected) ? RemoteConnectionState.Started : RemoteConnectionState.Stopped, args.Id, -1); - - if (args.Connected) - { - Clients[args.Id] = new NetworkConnection(NetworkManager, args.Id, false); - OnRemoteConnectionState?.Invoke(rcs); - } - else - { - OnRemoteConnectionState?.Invoke(rcs); - if (Clients.TryGetValue(args.Id, out NetworkConnection c)) - { - c.Dispose(); - Clients.Remove(args.Id); - } - } - } - - /// - /// Called when the server sends all currently connected clients. - /// - /// - private void OnConnectedClientsBroadcast(ConnectedClientsBroadcast args) - { - NetworkManager.ClearClientsCollection(Clients); - - List collection = args.ListCache.Collection;// args.Ids; - //No connected clients except self. - if (collection == null) - return; - - int count = collection.Count; - for (int i = 0; i < count; i++) - { - int id = collection[i]; - Clients[id] = new NetworkConnection(NetworkManager, id, false); - } - } - - /// - /// Changes subscription status to transport. - /// - /// - private void SubscribeToEvents(bool subscribe) - { - if (NetworkManager == null || NetworkManager.TransportManager == null || NetworkManager.TransportManager.Transport == null) - return; - - if (subscribe) - { - NetworkManager.TransportManager.OnIterateIncomingEnd += TransportManager_OnIterateIncomingEnd; - NetworkManager.TransportManager.Transport.OnClientReceivedData += Transport_OnClientReceivedData; - NetworkManager.TransportManager.Transport.OnClientConnectionState += Transport_OnClientConnectionState; - } - else - { - NetworkManager.TransportManager.OnIterateIncomingEnd -= TransportManager_OnIterateIncomingEnd; - NetworkManager.TransportManager.Transport.OnClientReceivedData -= Transport_OnClientReceivedData; - NetworkManager.TransportManager.Transport.OnClientConnectionState -= Transport_OnClientConnectionState; - } - } - - /// - /// Stops the local client connection. - /// - public void StopConnection() - { - NetworkManager.TransportManager.Transport.StopConnection(false); - } - - /// - /// Starts the local client connection. - /// - public void StartConnection() - { - NetworkManager.TransportManager.Transport.StartConnection(false); - } - - /// - /// Sets the transport address and starts the local client connection. - /// - public void StartConnection(string address) - { - StartConnection(address, NetworkManager.TransportManager.Transport.GetPort()); - } - /// - /// Sets the transport address and port, and starts the local client connection. - /// - public void StartConnection(string address, ushort port) - { - NetworkManager.TransportManager.Transport.SetClientAddress(address); - NetworkManager.TransportManager.Transport.SetPort(port); - StartConnection(); - } - - /// - /// Called when a connection state changes for the local client. - /// - /// - private void Transport_OnClientConnectionState(ClientConnectionStateArgs args) - { - LocalConnectionState state = args.ConnectionState; - Started = (state == LocalConnectionState.Started); - Objects.OnClientConnectionState(args); - - //Clear connection after so objects can update using current Connection value. - if (!Started) - { - Connection = NetworkManager.EmptyConnection; - NetworkManager.ClearClientsCollection(Clients); - } - - if (NetworkManager.CanLog(LoggingType.Common)) - { - Transport t = NetworkManager.TransportManager.GetTransport(args.TransportIndex); - string tName = (t == null) ? "Unknown" : t.GetType().Name; - Debug.Log($"Local client is {state.ToString().ToLower()} for {tName}."); - } - - NetworkManager.UpdateFramerate(); - OnClientConnectionState?.Invoke(args); - } - - /// - /// Called when a socket receives data. - /// - private void Transport_OnClientReceivedData(ClientReceivedDataArgs args) - { - args.Data = NetworkManager.TransportManager.ProcessIntermediateIncoming(args.Data, true); - ParseReceived(args); - } - - /// - /// Called after IterateIncoming has completed. - /// - private void TransportManager_OnIterateIncomingEnd(bool server) - { - /* Should the last packet received be a spawn or despawn - * then the cache won't yet be iterated because it only - * iterates when a packet is anything but those two. Because - * of such if any object caches did come in they must be iterated - * at the end of the incoming cycle. This isn't as clean as I'd - * like but it does ensure there will be no missing network object - * references on spawned objects. */ - if (Started && !server) - Objects.IterateObjectCache(); - } - - /// - /// Parses received data. - /// - private void ParseReceived(ClientReceivedDataArgs args) - { -#if UNITY_EDITOR || DEVELOPMENT_BUILD - _parseLogger.Reset(); -#endif - - ArraySegment segment = args.Data; - NetworkManager.StatisticsManager.NetworkTraffic.LocalClientReceivedData((ulong)segment.Count); - if (segment.Count <= TransportManager.TICK_BYTES) - return; - - PacketId packetId = PacketId.Unset; -#if !UNITY_EDITOR && !DEVELOPMENT_BUILD - try - { -#endif - using (PooledReader reader = ReaderPool.GetReader(segment, NetworkManager)) - { - NetworkManager.TimeManager.LastPacketTick = reader.ReadUInt32(AutoPackType.Unpacked); - /* This is a special condition where a message may arrive split. - * When this occurs buffer each packet until all packets are - * received. */ - if (reader.PeekPacketId() == PacketId.Split) - { - //Skip packetId. - reader.ReadPacketId(); - int expectedMessages; - _splitReader.GetHeader(reader, out expectedMessages); - _splitReader.Write(NetworkManager.TimeManager.LastPacketTick, reader, expectedMessages); - /* If fullMessage returns 0 count then the split - * has not written fully yet. Otherwise, if there is - * data within then reinitialize reader with the - * full message. */ - ArraySegment fullMessage = _splitReader.GetFullMessage(); - if (fullMessage.Count == 0) - return; - - //Initialize reader with full message. - reader.Initialize(fullMessage, NetworkManager); - } - - while (reader.Remaining > 0) - { - packetId = reader.ReadPacketId(); -#if UNITY_EDITOR || DEVELOPMENT_BUILD - _parseLogger.AddPacket(packetId); -#endif - bool spawnOrDespawn = (packetId == PacketId.ObjectSpawn || packetId == PacketId.ObjectDespawn); - /* Length of data. Only available if using unreliable. Unreliable packets - * can arrive out of order which means object orientated messages such as RPCs may - * arrive after the object for which they target has already been destroyed. When this happens - * on lesser solutions they just dump the entire packet. However, since FishNet batches data. - * it's very likely a packet will contain more than one packetId. With this mind, length is - * sent as well so if any reason the data does have to be dumped it will only be dumped for - * that single packetId but not the rest. Broadcasts don't need length either even if unreliable - * because they are not object bound. */ - - //Is spawn or despawn; cache packet. - if (spawnOrDespawn) - { - if (packetId == PacketId.ObjectSpawn) - Objects.CacheSpawn(reader); - else if (packetId == PacketId.ObjectDespawn) - Objects.CacheDespawn(reader); - } - //Not spawn or despawn. - else - { - /* Iterate object cache should any of the - * incoming packets rely on it. Objects - * in cache will always be received before any messages - * that use them. */ - Objects.IterateObjectCache(); - //Then process packet normally. - if ((ushort)packetId >= NetworkManager.StartingRpcLinkIndex) - { - Objects.ParseRpcLink(reader, (ushort)packetId, args.Channel); - } - else if (packetId == PacketId.Reconcile) - { - Objects.ParseReconcileRpc(reader, args.Channel); - } - else if (packetId == PacketId.ObserversRpc) - { - Objects.ParseObserversRpc(reader, args.Channel); - } - else if (packetId == PacketId.TargetRpc) - { - Objects.ParseTargetRpc(reader, args.Channel); - } - else if (packetId == PacketId.Broadcast) - { - ParseBroadcast(reader, args.Channel); - } - else if (packetId == PacketId.PingPong) - { - ParsePingPong(reader); - } - else if (packetId == PacketId.SyncVar) - { - Objects.ParseSyncType(reader, false, args.Channel); - } - else if (packetId == PacketId.SyncObject) - { - Objects.ParseSyncType(reader, true, args.Channel); - } - else if (packetId == PacketId.PredictedSpawnResult) - { - Objects.ParsePredictedSpawnResult(reader); - } - else if (packetId == PacketId.TimingUpdate) - { - NetworkManager.TimeManager.ParseTimingUpdate(); - } - else if (packetId == PacketId.OwnershipChange) - { - Objects.ParseOwnershipChange(reader); - } - else if (packetId == PacketId.Authenticated) - { - ParseAuthenticated(reader); - } - else if (packetId == PacketId.Disconnect) - { - reader.Clear(); - StopConnection(); - } - else - { - - NetworkManager.LogError($"Client received an unhandled PacketId of {(ushort)packetId}. Remaining data has been purged."); -#if UNITY_EDITOR || DEVELOPMENT_BUILD - _parseLogger.Print(NetworkManager); -#endif - return; - } - } - } - - /* Iterate cache when reader is emptied. - * This is incase the last packet received - * was a spawned, which wouldn't trigger - * the above iteration. There's no harm - * in doing this check multiple times as there's - * an exit early check. */ - Objects.IterateObjectCache(); - } -#if !UNITY_EDITOR && !DEVELOPMENT_BUILD - } - catch (Exception e) - { - if (NetworkManager.CanLog(LoggingType.Error)) - Debug.LogError($"Client encountered an error while parsing data for packetId {packetId}. Message: {e.Message}."); - } -#endif - } - - /// - /// Parses a PingPong packet. - /// - /// - private void ParsePingPong(PooledReader reader) - { - uint clientTick = reader.ReadUInt32(AutoPackType.Unpacked); - NetworkManager.TimeManager.ModifyPing(clientTick); - } - - /// - /// Parses a received connectionId. This is received before client receives connection state change. - /// - /// - private void ParseAuthenticated(PooledReader reader) - { - NetworkManager networkManager = NetworkManager; - int connectionId = reader.ReadNetworkConnectionId(); - //If only a client then make a new connection. - if (!networkManager.IsServer) - { - Clients.TryGetValueIL2CPP(connectionId, out Connection); - } - /* If also the server then use the servers connection - * for the connectionId. This is to resolve host problems - * where LocalConnection for client differs from the server Connection - * reference, which results in different field values. */ - else - { - if (networkManager.ServerManager.Clients.TryGetValueIL2CPP(connectionId, out NetworkConnection conn)) - { - Connection = conn; - } - else - { - networkManager.LogError($"Unable to lookup LocalConnection for {connectionId} as host."); - Connection = new NetworkConnection(networkManager, connectionId, false); - } - } - - //If predicted spawning is enabled also get reserved Ids. - if (NetworkManager.PredictionManager.GetAllowPredictedSpawning()) - { - byte count = reader.ReadByte(); - Queue q = Connection.PredictedObjectIds; - for (int i = 0; i < count; i++) - q.Enqueue(reader.ReadNetworkObjectId()); - } - - /* Set the TimeManager tick to lastReceivedTick. - * This still doesn't account for latency but - * it's the best we can do until the client gets - * a ping response. */ - networkManager.TimeManager.Tick = networkManager.TimeManager.LastPacketTick; - - //Mark as authenticated. - Connection.ConnectionAuthenticated(); - OnAuthenticated?.Invoke(); - /* Register scene objects for all scenes - * after being authenticated. This is done after - * authentication rather than when the connection - * is started because if also as server an online - * scene may already be loaded on server, but not - * for client. This means the sceneLoaded unity event - * won't fire, and since client isn't authenticated - * at the connection start phase objects won't be added. */ - Objects.RegisterAndDespawnSceneObjects(); - } - - } - -} diff --git a/Assets/FishNet/Runtime/Managing/Client/ClientManager.cs.meta b/Assets/FishNet/Runtime/Managing/Client/ClientManager.cs.meta deleted file mode 100644 index 3185de7..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/ClientManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: aca43cf6f20e77c4f8fcc078fd85081f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Client/Editor.meta b/Assets/FishNet/Runtime/Managing/Client/Editor.meta deleted file mode 100644 index bf04e9c..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 934151ddc3910094daef3552e81ecf24 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Client/Editor/ClientManagerEditor.cs b/Assets/FishNet/Runtime/Managing/Client/Editor/ClientManagerEditor.cs deleted file mode 100644 index 4208062..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/Editor/ClientManagerEditor.cs +++ /dev/null @@ -1,46 +0,0 @@ -#if UNITY_EDITOR -using UnityEditor; -using UnityEngine; - -namespace FishNet.Managing.Client.Editing -{ - - - [CustomEditor(typeof(ClientManager), true)] - [CanEditMultipleObjects] - public class ClientManagerEditor : Editor - { - private SerializedProperty _changeFrameRate; - private SerializedProperty _frameRate; - - protected virtual void OnEnable() - { - _changeFrameRate = serializedObject.FindProperty("_changeFrameRate"); - _frameRate = serializedObject.FindProperty("_frameRate"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - GUI.enabled = false; - EditorGUILayout.ObjectField("Script:", MonoScript.FromMonoBehaviour((ClientManager)target), typeof(ClientManager), false); - GUI.enabled = true; - - - EditorGUILayout.PropertyField(_changeFrameRate); - if (_changeFrameRate.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_frameRate); - EditorGUI.indentLevel--; - } - - EditorGUILayout.Space(); - - serializedObject.ApplyModifiedProperties(); - } - - } -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Client/Editor/ClientManagerEditor.cs.meta b/Assets/FishNet/Runtime/Managing/Client/Editor/ClientManagerEditor.cs.meta deleted file mode 100644 index 404a1fd..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/Editor/ClientManagerEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a652d51a1efa8a442966e885e2736599 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Client/Object.meta b/Assets/FishNet/Runtime/Managing/Client/Object.meta deleted file mode 100644 index 0717957..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/Object.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: cd638699438c5194ca93b15a5121d0a8 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.RpcLinks.cs b/Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.RpcLinks.cs deleted file mode 100644 index 46a65d8..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.RpcLinks.cs +++ /dev/null @@ -1,87 +0,0 @@ -using FishNet.Managing.Logging; -using FishNet.Managing.Object; -using FishNet.Managing.Utility; -using FishNet.Object; -using FishNet.Object.Helping; -using FishNet.Serializing; -using FishNet.Transporting; -using FishNet.Utility.Extension; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Managing.Client -{ - /// - /// Handles objects and information about objects for the local client. See ManagedObjects for inherited options. - /// - public partial class ClientObjects : ManagedObjects - { - - #region Private. - /// - /// RPCLinks of currently spawned objects. - /// - private Dictionary _rpcLinks = new Dictionary(); - #endregion - - /// - /// Parses a received RPCLink. - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ParseRpcLink(PooledReader reader, ushort index, Channel channel) - { - int dataLength = Packets.GetPacketLength(ushort.MaxValue, reader, channel); - - //Link index isn't stored. - if (!_rpcLinks.TryGetValueIL2CPP(index, out RpcLink link)) - { - SkipDataLength(index, reader, dataLength); - return; - } - else - //Found NetworkObject for link. - if (Spawned.TryGetValueIL2CPP(link.ObjectId, out NetworkObject nob)) - { - NetworkBehaviour nb = nob.NetworkBehaviours[link.ComponentIndex]; - if (link.RpcType == RpcType.Target) - nb.OnTargetRpc(link.RpcHash, reader, channel); - else if (link.RpcType == RpcType.Observers) - nb.OnObserversRpc(link.RpcHash, reader, channel); - else if (link.RpcType == RpcType.Reconcile) - nb.OnReconcileRpc(link.RpcHash, reader, channel); - } - //Could not find NetworkObject. - else - { - SkipDataLength(index, reader, dataLength, link.ObjectId); - } - } - - /// - /// Sets link to rpcLinks key linkIndex. - /// - /// - /// - internal void SetRpcLink(ushort linkIndex, RpcLink link) - { - _rpcLinks[linkIndex] = link; - } - - /// - /// Removes link index keys from rpcLinks. - /// - internal void RemoveLinkIndexes(List values) - { - if (values == null) - return; - - for (int i = 0; i < values.Count; i++) - _rpcLinks.Remove(values[i]); - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.RpcLinks.cs.meta b/Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.RpcLinks.cs.meta deleted file mode 100644 index f129249..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.RpcLinks.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2a20cc3f399aa614c931c9b45205937b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.cs b/Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.cs deleted file mode 100644 index ff177f4..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.cs +++ /dev/null @@ -1,688 +0,0 @@ -using FishNet.Connection; -using FishNet.Documenting; -using FishNet.Managing.Logging; -using FishNet.Managing.Object; -using FishNet.Managing.Server; -using FishNet.Managing.Utility; -using FishNet.Object; -using FishNet.Object.Helping; -using FishNet.Serializing; -using FishNet.Transporting; -using FishNet.Utility.Extension; -using FishNet.Utility.Performance; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; -using UnityEngine.SceneManagement; - -namespace FishNet.Managing.Client -{ - /// - /// Handles objects and information about objects for the local client. See ManagedObjects for inherited options. - /// - public partial class ClientObjects : ManagedObjects - { - #region Private. - /// - /// NetworkObjects which are cached to be spawned or despawned. - /// - private ClientObjectCache _objectCache; - #endregion - - internal ClientObjects(NetworkManager networkManager) - { - base.Initialize(networkManager); - _objectCache = new ClientObjectCache(this, networkManager); - } - - /// - /// Called when a connection state changes for the local server. - /// - internal void OnServerConnectionState(ServerConnectionStateArgs args) - { - //Nothing needs to be done if started. - if (args.ConnectionState == LocalConnectionState.Started) - return; - - /* If not started and client is active then deinitialize - * client objects first. This will let the deinit calls - * perform before the server destroys them. Ideally this - * would be done when the user shows intent to shutdown - * the server, but realistically planning for server socket - * drops is a much more universal solution. - * - * Calling StopConnection on the client will set it's local state - * to Stopping which will result in a deinit. */ - if (NetworkManager.IsClient) - base.NetworkManager.ClientManager.StopConnection(); - } - - /// - /// Called when the connection state changes for the local client. - /// - /// - internal void OnClientConnectionState(ClientConnectionStateArgs args) - { - /* If new state is not started then reset - * environment. */ - if (args.ConnectionState != LocalConnectionState.Started) - { - _objectCache.Reset(); - - //If not server then deinitialize normally. - if (!base.NetworkManager.IsServer) - { - base.DespawnWithoutSynchronization(false); - } - //Otherwise invoke stop callbacks only for client side. - else - { - foreach (NetworkObject n in Spawned.Values) - n.InvokeStopCallbacks(false); - } - /* Clear spawned and scene objects as they will be rebuilt. - * Spawned would have already be cleared if DespawnSpawned - * was called but it won't hurt anything clearing an empty collection. */ - base.Spawned.Clear(); - base.SceneObjects.Clear(); - base.LocalClientSpawned.Clear(); - } - } - - - /// - /// Called when a scene is loaded. - /// - /// - /// - [APIExclude] - protected internal override void SceneManager_sceneLoaded(Scene s, LoadSceneMode arg1) - { - base.SceneManager_sceneLoaded(s, arg1); - - if (!base.NetworkManager.IsClient) - return; - /* When a scene first loads for a client it should disable - * all network objects in that scene. The server will send - * spawn messages once it's aware client has loaded the scene. */ - RegisterAndDespawnSceneObjects(s); - } - - - /// - /// Sends a predicted spawn to the server. - /// - internal void PredictedSpawn(NetworkObject networkObject, NetworkConnection ownerConnection) - { - //No more Ids to use. - Queue predictedObjectIds = NetworkManager.ClientManager.Connection.PredictedObjectIds; - if (predictedObjectIds.Count == 0) - { - NetworkManager.LogError($"Predicted spawn for object {networkObject.name} failed because no more predicted ObjectIds remain. This usually occurs when the client is spawning excessively before the server can respond. Increasing ReservedObjectIds within the ServerManager component or reducing spawn rate could prevent this problem."); - return; - } - - networkObject.PreinitializePredictedObject_Client(base.NetworkManager, predictedObjectIds.Dequeue(), ownerConnection, base.NetworkManager.ClientManager.Connection); - NetworkManager.ClientManager.Objects.AddToSpawned(networkObject, false); - networkObject.Initialize(false, true); - - PooledWriter writer = WriterPool.GetWriter(); - WriteSpawn(networkObject, writer); - base.NetworkManager.TransportManager.SendToServer((byte)Channel.Reliable, writer.GetArraySegment()); - writer.Dispose(); - } - - /// - /// Writes a predicted spawn. - /// - /// - public void WriteSpawn(NetworkObject nob, Writer writer) - { - PooledWriter headerWriter = WriterPool.GetWriter(); - headerWriter.WritePacketId(PacketId.ObjectSpawn); - headerWriter.WriteNetworkObjectForSpawn(nob); - headerWriter.WriteNetworkConnection(nob.Owner); - - bool sceneObject = nob.IsSceneObject; - //Write type of spawn. - SpawnType st = SpawnType.Unset; - if (sceneObject) - st |= SpawnType.Scene; - else - st |= (nob.IsGlobal) ? SpawnType.InstantiatedGlobal : SpawnType.Instantiated; - headerWriter.WriteByte((byte)st); - - //ComponentIndex for the nob. 0 is root but more appropriately there's a IsNested boolean as shown above. - headerWriter.WriteByte(nob.ComponentIndex); - //Properties on the transform which diff from serialized value. - base.WriteChangedTransformProperties(nob, sceneObject, false, headerWriter); - /* Writing a scene object. */ - if (sceneObject) - { - headerWriter.WriteUInt64(nob.SceneId, AutoPackType.Unpacked); - } - /* Writing a spawned object. */ - else - { - //Nested predicted spawning will be added later. - headerWriter.WriteByte((byte)SpawnParentType.Unset); - headerWriter.WriteNetworkObjectId(nob.PrefabId); - } - - writer.WriteBytes(headerWriter.GetBuffer(), 0, headerWriter.Length); - - //If allowed to write synctypes. - if (nob.AllowPredictedSyncTypes) - { - PooledWriter tempWriter = WriterPool.GetWriter(); - WriteSyncTypes(writer, tempWriter, SyncTypeWriteType.All); - void WriteSyncTypes(Writer finalWriter, PooledWriter tWriter, SyncTypeWriteType writeType) - { - tWriter.Reset(); - foreach (NetworkBehaviour nb in nob.NetworkBehaviours) - nb.WriteSyncTypesForSpawn(tWriter, writeType); - finalWriter.WriteBytesAndSize(tWriter.GetBuffer(), 0, tWriter.Length); - } - tempWriter.Dispose(); - } - - //Dispose of writers created in this method. - headerWriter.Dispose(); - } - - - /// - /// Sends a predicted despawn to the server. - /// - internal void PredictedDespawn(NetworkObject networkObject) - { - PooledWriter writer = WriterPool.GetWriter(); - WriteDepawn(networkObject, writer); - base.NetworkManager.TransportManager.SendToServer((byte)Channel.Reliable, writer.GetArraySegment()); - writer.Dispose(); - - //Deinitialize after writing despawn so all the right data is sent. - networkObject.DeinitializePredictedObject_Client(); - } - - /// - /// Writes a predicted despawn. - /// - public void WriteDepawn(NetworkObject nob, Writer writer) - { - writer.WritePacketId(PacketId.ObjectDespawn); - writer.WriteNetworkObject(nob); - } - - /// - /// Registers NetworkObjects in all scenes and despawns them. - /// - internal void RegisterAndDespawnSceneObjects() - { - for (int i = 0; i < SceneManager.sceneCount; i++) - RegisterAndDespawnSceneObjects(SceneManager.GetSceneAt(i)); - } - - /// - /// Adds NetworkObjects within s to SceneObjects, and despawns them. - /// - /// - private void RegisterAndDespawnSceneObjects(Scene s) - { - ListCache nobs; - SceneFN.GetSceneNetworkObjects(s, false, out nobs); - - for (int i = 0; i < nobs.Written; i++) - { - NetworkObject nob = nobs.Collection[i]; - if (!nob.IsSceneObject) - continue; - - base.UpdateNetworkBehavioursForSceneObject(nob, false); - if (nob.IsNetworked && nob.IsNetworked) - { - base.AddToSceneObjects(nob); - //Only run if not also server, as this already ran on server. - if (!base.NetworkManager.IsServer) - nob.gameObject.SetActive(false); - } - } - - ListCaches.StoreCache(nobs); - } - - /// - /// Called when a NetworkObject runs Deactivate. - /// - /// - internal override void NetworkObjectUnexpectedlyDestroyed(NetworkObject nob, bool asServer) - { - nob.RemoveClientRpcLinkIndexes(); - base.NetworkObjectUnexpectedlyDestroyed(nob, asServer); - } - - /// - /// Parses an OwnershipChange packet. - /// - /// - internal void ParseOwnershipChange(PooledReader reader) - { - NetworkObject nob = reader.ReadNetworkObject(); - NetworkConnection newOwner = reader.ReadNetworkConnection(); - if (nob != null) - nob.GiveOwnership(newOwner, false); - else - NetworkManager.LogWarning($"NetworkBehaviour could not be found when trying to parse OwnershipChange packet."); - } - - /// - /// Parses a received syncVar. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ParseSyncType(PooledReader reader, bool isSyncObject, Channel channel) - { - //cleanup this is unique to synctypes where length comes first. - //this will change once I tidy up synctypes. - ushort packetId = (isSyncObject) ? (ushort)PacketId.SyncObject : (ushort)PacketId.SyncVar; - NetworkBehaviour nb = reader.ReadNetworkBehaviour(); - int dataLength = Packets.GetPacketLength(packetId, reader, channel); - - if (nb != null) - { - /* Length of data to be read for syncvars. - * This is important because syncvars are never - * a set length and data must be read through completion. - * The only way to know where completion of syncvar is, versus - * when another packet starts is by including the length. */ - if (dataLength > 0) - nb.OnSyncType(reader, dataLength, isSyncObject); - } - else - { - SkipDataLength(packetId, reader, dataLength); - } - } - - /// - /// Parses a - /// - /// - internal void ParsePredictedSpawnResult(Reader reader) - { - int usedObjectId = reader.ReadNetworkObjectId(); - bool success = reader.ReadBoolean(); - if (success) - { - int nextObjectId = reader.ReadNetworkObjectId(); - if (nextObjectId != NetworkObject.UNSET_OBJECTID_VALUE) - NetworkManager.ClientManager.Connection.PredictedObjectIds.Enqueue(nextObjectId); - } - } - - /// - /// Parses a ReconcileRpc. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ParseReconcileRpc(PooledReader reader, Channel channel) - { - NetworkBehaviour nb = reader.ReadNetworkBehaviour(); - int dataLength = Packets.GetPacketLength((ushort)PacketId.Reconcile, reader, channel); - - if (nb != null) - nb.OnReconcileRpc(null, reader, channel); - else - SkipDataLength((ushort)PacketId.ObserversRpc, reader, dataLength); - } - - /// - /// Parses an ObserversRpc. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ParseObserversRpc(PooledReader reader, Channel channel) - { - NetworkBehaviour nb = reader.ReadNetworkBehaviour(); - int dataLength = Packets.GetPacketLength((ushort)PacketId.ObserversRpc, reader, channel); - - if (nb != null) - nb.OnObserversRpc(null, reader, channel); - else - SkipDataLength((ushort)PacketId.ObserversRpc, reader, dataLength); - } - /// - /// Parses a TargetRpc. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ParseTargetRpc(PooledReader reader, Channel channel) - { - NetworkBehaviour nb = reader.ReadNetworkBehaviour(); - int dataLength = Packets.GetPacketLength((ushort)PacketId.TargetRpc, reader, channel); - - if (nb != null) - nb.OnTargetRpc(null, reader, channel); - else - SkipDataLength((ushort)PacketId.TargetRpc, reader, dataLength); - } - - /// - /// Caches a received spawn to be processed after all spawns and despawns are received for the tick. - /// - /// - internal void CacheSpawn(PooledReader reader) - { - sbyte initializeOrder; - ushort collectionId; - int objectId = reader.ReadNetworkObjectForSpawn(out initializeOrder, out collectionId, out _); - int ownerId = reader.ReadNetworkConnectionId(); - SpawnType st = (SpawnType)reader.ReadByte(); - byte componentIndex = reader.ReadByte(); - - //Read transform values which differ from serialized values. - Vector3? localPosition; - Quaternion? localRotation; - Vector3? localScale; - base.ReadTransformProperties(reader, out localPosition, out localRotation, out localScale); - - bool nested = SpawnTypeEnum.Contains(st, SpawnType.Nested); - int rootObjectId = (nested) ? reader.ReadNetworkObjectId() : 0; - bool sceneObject = SpawnTypeEnum.Contains(st, SpawnType.Scene); - - int? parentObjectId = null; - byte? parentComponentIndex = null; - int? prefabId = null; - ulong sceneId = 0; - - if (sceneObject) - ReadSceneObject(reader, out sceneId); - else - ReadSpawnedObject(reader, out parentObjectId, out parentComponentIndex, out prefabId); - - ArraySegment rpcLinks = reader.ReadArraySegmentAndSize(); - ArraySegment syncValues = reader.ReadArraySegmentAndSize(); - - /* If the objectId can be found as already spawned then check if it's predicted. - * Should the spawn be predicted then no need to continue. Later on however - * we may want to apply synctypes. - * - * Only check if not server, since if server the client doesnt need - * to predicted spawn. */ - if (!base.NetworkManager.IsServerOnly && base.Spawned.TryGetValue(objectId, out NetworkObject nob)) - { - //If not predicted the nob should not be in spawned. - if (!nob.PredictedSpawner.IsValid) - { - NetworkManager.LogError($"Received a spawn objectId of {objectId} which was already found in spawned, and was not predicted."); - } - //Everything is proper, apply RPC links. - else - { - PooledReader linkReader = ReaderPool.GetReader(rpcLinks, NetworkManager); - ApplyRpcLinks(nob, linkReader); - linkReader.Dispose(); - } - //No further initialization needed when predicting. - return; - } - - _objectCache.AddSpawn(base.NetworkManager, collectionId, objectId, initializeOrder, ownerId, st, componentIndex, rootObjectId, parentObjectId, parentComponentIndex, prefabId, localPosition, localRotation, localScale, sceneId, rpcLinks, syncValues); - } - /// - /// Caches a received despawn to be processed after all spawns and despawns are received for the tick. - /// - /// - internal void CacheDespawn(PooledReader reader) - { - DespawnType despawnType; - int objectId = reader.ReadNetworkObjectForDepawn(out despawnType); - _objectCache.AddDespawn(objectId, despawnType); - } - - /// - /// Iterates object cache which contains spawn and despawn messages. - /// Parses the packets within the cache and ensures objects are spawned and despawned before their sync values are applied. - /// This ensures there is no chance a sync value is referencing a spawned object which does not exist yet due to it normally being spawned later in the cache. - /// - internal void IterateObjectCache() - { - _objectCache.Iterate(); - } - - /// - /// Gets a nested NetworkObject within it's root. - /// - /// - /// - internal NetworkObject GetNestedNetworkObject(CachedNetworkObject cnob) - { - NetworkObject rootNob; - int rootObjectId = cnob.RootObjectId; - byte componentIndex = cnob.ComponentIndex; - - /* Spawns are processed after all spawns come in, - * this ensures no reference race conditions. Turns out because of this - * the parentNob may be in cache and not actually spawned, if it was spawned the same packet - * as this one. So when not found in the spawned collection try to - * find it in Spawning before throwing. */ - rootNob = _objectCache.GetSpawnedObject(rootObjectId); - //If still null, that's not good. - if (rootNob == null) - { - NetworkManager.LogError($"Nested spawned object with componentIndex of {componentIndex} and a parentId of {rootObjectId} could not be spawned because parent was not found."); - return null; - } - - NetworkObject nob = null; - List childNobs = rootNob.ChildNetworkObjects; - //Find nob with component index. - for (int i = 0; i < childNobs.Count; i++) - { - if (childNobs[i].ComponentIndex == componentIndex) - { - nob = childNobs[i]; - break; - } - } - //If child nob was not found. - if (nob == null) - { - NetworkManager.LogError($"Nested spawned object with componentIndex of {componentIndex} could not be found as a child NetworkObject of {rootNob.name}."); - return null; - } - - return nob; - } - - /// - /// Applies RPCLinks to a NetworkObject. - /// - internal void ApplyRpcLinks(NetworkObject nob, Reader reader) - { - List rpcLinkIndexes = new List(); - //Apply rpcLinks. - foreach (NetworkBehaviour nb in nob.NetworkBehaviours) - { - int length = reader.ReadInt32(); - - int readerStart = reader.Position; - while (reader.Position - readerStart < length) - { - //Index of RpcLink. - ushort linkIndex = reader.ReadUInt16(); - RpcLink link = new RpcLink(nob.ObjectId, nb.ComponentIndex, - //RpcHash. - reader.ReadUInt16(), - //ObserverRpc. - (RpcType)reader.ReadByte()); - //Add to links. - SetRpcLink(linkIndex, link); - - rpcLinkIndexes.Add(linkIndex); - } - } - nob.SetRpcLinkIndexes(rpcLinkIndexes); - } - - /// - /// Instantiates a NetworkObject if required and sets transform values. - /// - internal NetworkObject GetInstantiatedNetworkObject(CachedNetworkObject cnob) - { - if (cnob.PrefabId == null) - { - NetworkManager.LogError($"PrefabId for {cnob.ObjectId} is null. Object will not spawn."); - return null; - } - - NetworkManager networkManager = base.NetworkManager; - int prefabId = cnob.PrefabId.Value; - NetworkObject result; - - if (prefabId == NetworkObject.UNSET_OBJECTID_VALUE) - { - NetworkManager.LogError($"Spawned object has an invalid prefabId. Make sure all objects which are being spawned over the network are within SpawnableObjects on the NetworkManager."); - return null; - } - - ushort collectionId = cnob.CollectionId; - //PrefabObjects to get the prefab from. - PrefabObjects prefabObjects = networkManager.GetPrefabObjects(collectionId, false); - //Not found for collectionId > 0. This means the user likely did not setup the collection on client. - if (prefabObjects == null && collectionId > 0) - { - networkManager.LogError($"PrefabObjects collection is not found for CollectionId {collectionId}. Be sure to add your addressables NetworkObject prefabs to the collection on server and client before attempting to spawn them over the network."); - return null; - } - - //Only instantiate if not host. - if (!networkManager.IsHost) - { - Transform parentTransform = null; - bool hasParent = (cnob.ParentObjectId != null); - //Set parentTransform if there's a parent object. - if (hasParent) - { - int objectId = cnob.ParentObjectId.Value; - NetworkObject nob = _objectCache.GetSpawnedObject(objectId); - - if (nob == null) - { - NetworkObject prefab = prefabObjects.GetObject(false, prefabId); - networkManager.LogError($"NetworkObject not found for ObjectId {objectId}. Prefab {prefab.name} will be instantiated without parent synchronization."); - } - else - { - //If parent object is a network behaviour then find the component. - if (cnob.ParentIsNetworkBehaviour) - { - byte componentIndex = cnob.ComponentIndex; - NetworkBehaviour nb = nob.GetNetworkBehaviour(componentIndex, false); - if (nb != null) - { - parentTransform = nb.transform; - } - else - { - NetworkObject prefab = prefabObjects.GetObject(false, prefabId); - networkManager.LogError($"NetworkBehaviour on index {componentIndex} could nto be found within NetworkObject {nob.name} with ObjectId {objectId}. Prefab {prefab.name} will be instantiated without parent synchronization."); - } - } - //The networkObject is the parent. - else - { - parentTransform = nob.transform; - } - } - } - - result = networkManager.GetPooledInstantiated(prefabId, collectionId, false); - Transform t = result.transform; - t.SetParent(parentTransform, true); - //Only need to set IsGlobal also if not host. - bool isGlobal = SpawnTypeEnum.Contains(cnob.SpawnType, SpawnType.InstantiatedGlobal); - result.SetIsGlobal(isGlobal); - } - //If host then find server instantiated object. - else - { - ServerObjects so = networkManager.ServerManager.Objects; - if (!so.Spawned.TryGetValueIL2CPP(cnob.ObjectId, out result)) - result = so.GetFromPending(cnob.ObjectId); - - if (result == null) - networkManager.LogError($"ObjectId {cnob.ObjectId} could not be found in Server spawned, nor Server pending despawn."); - } - - return result; - } - - /// - /// Gets a NetworkObject from Spawned, or object cache. - /// - /// - /// - internal NetworkObject GetSpawnedNetworkObject(CachedNetworkObject cnob) - { - NetworkObject nob; - //Try checking already spawned objects first. - if (base.Spawned.TryGetValueIL2CPP(cnob.ObjectId, out nob)) - { - return nob; - } - /* If not found in already spawned objects see if - * the networkObject is in the objectCache. It's possible the despawn - * came immediately or shortly after the spawn message, before - * the object has been initialized. */ - else - { - nob = _objectCache.GetInCached(cnob.ObjectId, ClientObjectCache.CacheSearchType.Any); - /* Nob may be null if it's a child object being despawned, and the - * parent despawn already occurred. */ - return nob; - } - } - - /// - /// Finishes reading a scene object. - /// - private void ReadSceneObject(PooledReader reader, out ulong sceneId) - { - sceneId = reader.ReadUInt64(AutoPackType.Unpacked); - } - - /// - /// Finishes reading a spawned object, and instantiates the object. - /// - private void ReadSpawnedObject(PooledReader reader, out int? parentObjectId, out byte? parentComponentIndex, out int? prefabId) - { - //Parent. - SpawnParentType spt = (SpawnParentType)reader.ReadByte(); - //Defaults. - parentObjectId = null; - parentComponentIndex = null; - - if (spt == SpawnParentType.NetworkObject) - { - int objectId = reader.ReadNetworkObjectId(); - if (objectId != NetworkObject.UNSET_OBJECTID_VALUE) - parentObjectId = objectId; - } - else if (spt == SpawnParentType.NetworkBehaviour) - { - reader.ReadNetworkBehaviour(out int objectId, out byte componentIndex); - if (objectId != NetworkObject.UNSET_OBJECTID_VALUE) - { - parentObjectId = objectId; - parentComponentIndex = componentIndex; - } - } - - prefabId = (ushort)reader.ReadNetworkObjectId(); - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.cs.meta b/Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.cs.meta deleted file mode 100644 index 014b78e..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/Object/ClientObjects.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: da027fa27b0c0994ebfa317968862970 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Client/Object/ObjectCaching.cs b/Assets/FishNet/Runtime/Managing/Client/Object/ObjectCaching.cs deleted file mode 100644 index e86387a..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/Object/ObjectCaching.cs +++ /dev/null @@ -1,605 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing.Logging; -using FishNet.Managing.Object; -using FishNet.Object; -using FishNet.Object.Helping; -using FishNet.Serializing; -using FishNet.Utility.Extension; -using FishNet.Utility.Performance; -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Scripting; - -namespace FishNet.Managing.Client -{ - - /// - /// Information about cached network objects. - /// - internal class ClientObjectCache - { - #region Types. - public enum CacheSearchType - { - Any = 0, - Spawning = 1, - Despawning = 2 - } - #endregion - - #region Internal. - /// - /// Objets which are being spawned during iteration. - /// - internal Dictionary SpawningObjects = new Dictionary(); - #endregion - - #region Private. - /// - /// Cached objects buffer. Contains spawns and despawns. - /// - private ListCache _cachedObjects = new ListCache(); - /// - /// NetworkObjects which have been spawned already during the current iteration. - /// - private HashSet _iteratedSpawns = new HashSet(); - /// - /// Despawns which are occurring the same tick as their spawn. - /// - private HashSet _conflictingDespawns = new HashSet(); - /// - /// ClientObjects reference. - /// - private ClientObjects _clientObjects; - /// - /// NetworkManager for this cache. - /// - private NetworkManager _networkManager; - /// - /// True if logged the warning about despawning on the same tick as the spawn. - /// This exist to prevent excessive spam of the warning. - /// - private bool _loggedSameTickWarning; - /// - /// True if initializeOrder was not default for any spawned objects. - /// - private bool _initializeOrderChanged; - #endregion - - public ClientObjectCache(ClientObjects cobs, NetworkManager networkManager) - { - _clientObjects = cobs; - _networkManager = networkManager; - } - - /// - /// Returns a NetworkObject found in spawned cache using objectId. - /// - /// - /// - public NetworkObject GetInCached(int objectId, CacheSearchType searchType) - { - int count = _cachedObjects.Written; - List collection = _cachedObjects.Collection; - for (int i = 0; i < count; i++) - { - CachedNetworkObject cnob = collection[i]; - if (cnob.ObjectId == objectId) - { - //Any condition always returns. - if (searchType == CacheSearchType.Any) - return cnob.NetworkObject; - - bool spawning = (searchType == CacheSearchType.Spawning); - bool spawnAction = (cnob.Action == CachedNetworkObject.ActionType.Spawn); - if (spawning == spawnAction) - return cnob.NetworkObject; - else - return null; - } - } - - //Fall through. - return null; - } - - /// - /// Initializes for a spawned NetworkObject. - /// - /// - /// - /// - public void AddSpawn(NetworkManager manager, ushort collectionId, int objectId, sbyte initializeOrder, int ownerId, SpawnType ost, byte componentIndex, int rootObjectId, int? parentObjectId, byte? parentComponentIndex - , int? prefabId, Vector3? localPosition, Quaternion? localRotation, Vector3? localScale, ulong sceneId, ArraySegment rpcLinks, ArraySegment syncValues) - { - //Set if initialization order has changed. - _initializeOrderChanged |= (initializeOrder != 0); - - CachedNetworkObject cnob = null; - //If order has not changed then add normally. - if (!_initializeOrderChanged) - { - cnob = _cachedObjects.AddReference(); - } - //Otherwise see if values need to be sorted. - else - { - /* Spawns will be ordered at the end of their nearest order. - * If spawns arrived with Id order of 5, 7, 2 then the result - * would be as shown below... - * Id 5 / order -5 - * Id 7 / order -5 - * Id 2 / order 0 - * Not as if the values were inserted first such as... - * Id 7 / order -5 - * Id 5 / order -5 - * Id 2 / order 0 - * This is to prevent the likeliness of child nobs being out of order - * as well to preserve user spawn order if they spawned multiple - * objects the same which, with the same order. */ - - int written = _cachedObjects.Written; - for (int i = 0; i < written; i++) - { - CachedNetworkObject item = _cachedObjects.Collection[i]; - /* If item order is larger then that means - * initializeOrder has reached the last entry - * of its value. Insert just before item index. */ - if (initializeOrder < item.InitializeOrder) - { - cnob = _cachedObjects.InsertReference(i); - break; - } - } - - //If here and cnob is null then it was not inserted; add to end. - if (cnob == null) - cnob = _cachedObjects.AddReference(); - } - - cnob.InitializeSpawn(manager, collectionId, objectId, initializeOrder, ownerId, ost, componentIndex, rootObjectId, parentObjectId, parentComponentIndex - , prefabId, localPosition, localRotation, localScale, sceneId, rpcLinks, syncValues); - } - - public void AddDespawn(int objectId, DespawnType despawnType) - { - CachedNetworkObject cnob = _cachedObjects.AddReference(); - cnob.InitializeDespawn(objectId, despawnType); - } - - /// - /// Iterates any written objects. - /// - public void Iterate() - { - int written = _cachedObjects.Written; - if (written == 0) - return; - - try - { - //Indexes which have already been processed. - HashSet processedIndexes = new HashSet(); - List collection = _cachedObjects.Collection; - _conflictingDespawns.Clear(); - /* The next iteration will set rpclinks, - * synctypes, and so on. */ - for (int i = 0; i < written; i++) - { - /* An index may already be processed if it was pushed ahead. - * This can occur if a nested object spawn exists but the root - * object has not spawned yet. In this situation the root spawn is - * found and performed first. */ - if (processedIndexes.Contains(i)) - continue; - CachedNetworkObject cnob = collection[i]; - bool spawn = (cnob.Action == CachedNetworkObject.ActionType.Spawn); - - /* See if nested, and if so check if root is already spawned. - * If parent is not spawned then find it and process the parent first. */ - if (spawn) - { - /* When an object is nested or has a parent it is - * dependent upon either the root of nested, or the parent, - * being spawned to setup properly. - * - * When either of these are true check spawned objects first - * to see if the objects exist. If not check if they are appearing - * later in the cache. Root or parent objects can appear later - * in the cache depending on the order of which observers are rebuilt. - * While it is possible to have the server ensure spawns always send - * root/parents first, that's a giant can of worms that's not worth getting into. - * Not only are there many scenarios to cover, but it also puts more work - * on the server. It's more effective to have the client handle the sorting. */ - - //Nested. - if (cnob.IsNested || cnob.HasParent) - { - bool nested = cnob.IsNested; - //It's not possible to be nested and have a parent. Set the Id to look for based on if nested or parented. - int targetObjectId = (nested) ? cnob.RootObjectId : cnob.ParentObjectId.Value; - NetworkObject nob = GetSpawnedObject(targetObjectId); - //If not spawned yet. - if (nob == null) - { - bool found = false; - string errMsg; - for (int z = (i + 1); z < written; z++) - { - CachedNetworkObject zCnob = collection[z]; - if (zCnob.ObjectId == targetObjectId) - { - found = true; - if (cnob.Action != CachedNetworkObject.ActionType.Spawn) - { - errMsg = (nested) - ? $"ObjectId {targetObjectId} was found for a nested spawn, but ActionType is not spawn. ComponentIndex {cnob.ComponentIndex} will not be spawned." - : $"ObjectId {targetObjectId} was found for a parented spawn, but ActionType is not spawn. ObjectId {cnob.ObjectId} will not be spawned."; - _networkManager.LogError(errMsg); - break; - } - else - { - ProcessObject(zCnob, true, z); - break; - } - } - } - - //Root nob could not be found. - if (!found) - { - errMsg = (nested) - ? $"ObjectId {targetObjectId} could not be found for a nested spawn. ComponentIndex {cnob.ComponentIndex} will not be spawned." - : $"ObjectId {targetObjectId} was found for a parented spawn. ObjectId {cnob.ObjectId} will not be spawned."; - _networkManager.LogError(errMsg); - } - } - } - } - - ProcessObject(cnob, spawn, i); - } - - void ProcessObject(CachedNetworkObject cnob, bool spawn, int index) - { - processedIndexes.Add(index); - - if (spawn) - { - if (cnob.IsSceneObject) - cnob.NetworkObject = _clientObjects.GetSceneNetworkObject(cnob.SceneId); - else if (cnob.IsNested) - cnob.NetworkObject = _clientObjects.GetNestedNetworkObject(cnob); - else - cnob.NetworkObject = _clientObjects.GetInstantiatedNetworkObject(cnob); - - /* Apply transform changes but only if not host. - * These would have already been applied server side. */ - if (!_networkManager.IsHost && cnob.NetworkObject != null) - { - Transform t = cnob.NetworkObject.transform; - _clientObjects.GetTransformProperties(cnob.LocalPosition, cnob.LocalRotation, cnob.LocalScale, t, out Vector3 pos, out Quaternion rot, out Vector3 scale); - t.SetLocalPositionRotationAndScale(pos, rot, scale); - } - } - else - { - cnob.NetworkObject = _clientObjects.GetSpawnedNetworkObject(cnob); - /* Do not log unless not nested. Nested nobs sometimes - * could be destroyed if parent was first. */ - if (!_networkManager.IsHost && cnob.NetworkObject == null && !cnob.IsNested) - _networkManager.Log($"NetworkObject for ObjectId of {cnob.ObjectId} was found null. Unable to despawn object. This may occur if a nested NetworkObject had it's parent object unexpectedly destroyed. This incident is often safe to ignore."); - } - NetworkObject nob = cnob.NetworkObject; - //No need to error here, the other Gets above would have. - if (nob == null) - return; - - if (spawn) - { - //If not also server then object also has to be preinitialized. - if (!_networkManager.IsServer) - { - int ownerId = cnob.OwnerId; - //If local client is owner then use localconnection reference. - NetworkConnection localConnection = _networkManager.ClientManager.Connection; - NetworkConnection owner; - //If owner is self. - if (ownerId == localConnection.ClientId) - { - owner = localConnection; - } - else - { - /* If owner cannot be found then share owners - * is disabled */ - if (!_networkManager.ClientManager.Clients.TryGetValueIL2CPP(ownerId, out owner)) - owner = NetworkManager.EmptyConnection; - } - nob.Preinitialize_Internal(_networkManager, cnob.ObjectId, owner, false); - } - - _clientObjects.AddToSpawned(cnob.NetworkObject, false); - SpawningObjects.Add(cnob.ObjectId, cnob.NetworkObject); - - IterateSpawn(cnob); - _iteratedSpawns.Add(cnob.NetworkObject); - - /* Enable networkObject here if client only. - * This is to ensure Awake fires in the same order - * as InitializeOrder settings. There is no need - * to perform this action if server because server - * would have already spawned in order. */ - if (!_networkManager.IsServer && cnob.NetworkObject != null) - cnob.NetworkObject.gameObject.SetActive(true); - } - else - { - /* If spawned already this iteration then the nob - * must be initialized so that the start/stop cycles - * complete normally. Otherwise, the despawn callbacks will - * fire immediately while the start callbacks will run after all - * spawns have been iterated. - * The downside to this is that synctypes - * for spawns later in this iteration will not be initialized - * yet, and if the nob being spawned/despawned references - * those synctypes the values will be default. - * - * The alternative is to delay the despawning until after - * all spawns are iterated, but that will break the order - * reliability. This is unfortunately a lose/lose situation so - * the best we can do is let the user know the risk. */ - if (_iteratedSpawns.Contains(cnob.NetworkObject)) - { - if (!_loggedSameTickWarning) - { - _loggedSameTickWarning = true; - _networkManager.LogWarning($"NetworkObject {cnob.NetworkObject.name} is being despawned on the same tick it's spawned." + - $" When this occurs SyncTypes will not be set on other objects during the time of this despawn." + - $" In result, if NetworkObject {cnob.NetworkObject.name} is referencing a SyncType of another object being spawned this tick, the returned values will be default."); - } - - _conflictingDespawns.Add(cnob.ObjectId); - cnob.NetworkObject.gameObject.SetActive(true); - cnob.NetworkObject.Initialize(false, true); - } - //Now being initialized, despawn the object. - IterateDespawn(cnob); - } - } - - /* Activate the objects after all data - * has been synchronized. This will apply synctypes. */ - for (int i = 0; i < written; i++) - { - CachedNetworkObject cnob = collection[i]; - if (cnob.Action == CachedNetworkObject.ActionType.Spawn && cnob.NetworkObject != null) - { - /* Apply syncTypes. It's very important to do this after all - * spawns have been processed and added to the manager.Objects collection. - * Otherwise, the synctype may reference an object spawning the same tick - * and the result would be null due to said object not being in spawned. - * - * At this time the NetworkObject is not initialized so by calling - * OnSyncType the changes are cached to invoke callbacks after initialization, - * not during the time of this action. */ - foreach (NetworkBehaviour nb in cnob.NetworkObject.NetworkBehaviours) - { - PooledReader reader = cnob.SyncValuesReader; - //SyncVars. - int length = reader.ReadInt32(); - nb.OnSyncType(reader, length, false); - //SyncObjects - length = reader.ReadInt32(); - nb.OnSyncType(reader, length, true); - } - - /* Only continue with the initialization if it wasn't initialized - * early to prevent a despawn conflict. */ - bool canInitialize = (!_conflictingDespawns.Contains(cnob.ObjectId) || !_iteratedSpawns.Contains(cnob.NetworkObject)); - if (canInitialize) - cnob.NetworkObject.Initialize(false, false); - } - } - //Invoke synctype callbacks. - for (int i = 0; i < written; i++) - { - CachedNetworkObject cnob = collection[i]; - if (cnob.Action == CachedNetworkObject.ActionType.Spawn && cnob.NetworkObject != null) - cnob.NetworkObject.InvokeSyncTypeCallbacks(false); - } - } - finally - { - //Once all have been iterated reset. - Reset(); - } - } - - /// - /// Initializes an object on clients and spawns the NetworkObject. - /// - /// - private void IterateSpawn(CachedNetworkObject cnob) - { - /* All nob spawns have been added to spawned before - * they are processed. This ensures they will be found if - * anything is referencing them before/after initialization. */ - /* However, they have to be added again here should an ItereteDespawn - * had removed them. This can occur if an object is set to be spawned, - * thus added to spawned before iterations, then a despawn runs which - * removes it from spawn. */ - _clientObjects.AddToSpawned(cnob.NetworkObject, false); - _clientObjects.ApplyRpcLinks(cnob.NetworkObject, cnob.RpcLinkReader); - } - - /// - /// Deinitializes an object on clients and despawns the NetworkObject. - /// - /// - private void IterateDespawn(CachedNetworkObject cnob) - { - _clientObjects.Despawn(cnob.NetworkObject, cnob.DespawnType, false); - } - - /// - /// Returns a NetworkObject found in spawn cache, or Spawned. - /// - /// - internal NetworkObject GetSpawnedObject(int objectId) - { - NetworkObject result; - //If not found in Spawning then check Spawned. - if (!SpawningObjects.TryGetValue(objectId, out result)) - { - Dictionary spawned = (_networkManager.IsHost) ? - _networkManager.ServerManager.Objects.Spawned - : _networkManager.ClientManager.Objects.Spawned; - spawned.TryGetValue(objectId, out result); - } - - return result; - } - - - /// - /// Resets cache. - /// - public void Reset() - { - _initializeOrderChanged = false; - _cachedObjects.Reset(); - _iteratedSpawns.Clear(); - SpawningObjects.Clear(); - } - } - - /// - /// A cached network object which exist in world but has not been Initialized yet. - /// - [Preserve] - internal class CachedNetworkObject - { - #region Types. - public enum ActionType - { - Unset = 0, - Spawn = 1, - Despawn = 2, - } - #endregion - - /// - /// True if cached object is nested. - /// - public bool IsNested => (ComponentIndex > 0); - /// - /// True if a scene object. - /// - public bool IsSceneObject => (SceneId > 0); - /// - /// True if this object has a parent. - /// - public bool HasParent => (ParentObjectId != null); - /// - /// True if the parent object is a NetworkBehaviour. - /// - public bool ParentIsNetworkBehaviour => (HasParent && (ParentComponentIndex != null)); - - public ushort CollectionId; - public int ObjectId; - public sbyte InitializeOrder; - public int OwnerId; - public SpawnType SpawnType; - public DespawnType DespawnType; - public byte ComponentIndex; - public int RootObjectId; - public int? ParentObjectId; - public byte? ParentComponentIndex; - public int? PrefabId; - public Vector3? LocalPosition; - public Quaternion? LocalRotation; - public Vector3? LocalScale; - public ulong SceneId; - public ArraySegment RpcLinks; - public ArraySegment SyncValues; - - - - /// - /// True if spawning. - /// - public ActionType Action { get; private set; } - /// - /// Cached NetworkObject. - /// -#pragma warning disable 0649 - public NetworkObject NetworkObject; - /// - /// Reader containing rpc links for the network object. - /// - public PooledReader RpcLinkReader { get; private set; } - /// - /// Reader containing sync values for the network object. - /// - public PooledReader SyncValuesReader { get; private set; } -#pragma warning restore 0649 - - public void InitializeSpawn(NetworkManager manager, ushort collectionId, int objectId, sbyte initializeOrder, int ownerId, SpawnType objectSpawnType, byte componentIndex, int rootObjectId, int? parentObjectId, byte? parentComponentIndex - , int? prefabId, Vector3? localPosition, Quaternion? localRotation, Vector3? localScale, ulong sceneId, ArraySegment rpcLinks, ArraySegment syncValues) - { - ResetValues(); - Action = ActionType.Spawn; - CollectionId = collectionId; - ObjectId = objectId; - InitializeOrder = initializeOrder; - OwnerId = ownerId; - SpawnType = objectSpawnType; - ComponentIndex = componentIndex; - RootObjectId = rootObjectId; - ParentObjectId = parentObjectId; - ParentComponentIndex = parentComponentIndex; - PrefabId = prefabId; - LocalPosition = localPosition; - LocalRotation = localRotation; - LocalScale = localScale; - SceneId = sceneId; - RpcLinks = rpcLinks; - SyncValues = syncValues; - - RpcLinkReader = ReaderPool.GetReader(rpcLinks, manager); - SyncValuesReader = ReaderPool.GetReader(syncValues, manager); - } - - /// - /// Initializes for a despawned NetworkObject. - /// - /// - public void InitializeDespawn(int objectId, DespawnType despawnType) - { - ResetValues(); - Action = ActionType.Despawn; - DespawnType = despawnType; - ObjectId = objectId; - } - - /// - /// Resets values which could malform identify the cached object. - /// - private void ResetValues() - { - NetworkObject = null; - } - - ~CachedNetworkObject() - { - if (RpcLinkReader != null) - RpcLinkReader.Dispose(); - if (SyncValuesReader != null) - SyncValuesReader.Dispose(); - } - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Client/Object/ObjectCaching.cs.meta b/Assets/FishNet/Runtime/Managing/Client/Object/ObjectCaching.cs.meta deleted file mode 100644 index 5481a01..0000000 --- a/Assets/FishNet/Runtime/Managing/Client/Object/ObjectCaching.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 54cb2af8ab4557d479acb7fed98bd0c3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Debugging.meta b/Assets/FishNet/Runtime/Managing/Debugging.meta deleted file mode 100644 index 63f6644..0000000 --- a/Assets/FishNet/Runtime/Managing/Debugging.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: ae208c57eb1f4414896575607893b48d -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Debugging/DebugManager.cs b/Assets/FishNet/Runtime/Managing/Debugging/DebugManager.cs deleted file mode 100644 index 777b5ef..0000000 --- a/Assets/FishNet/Runtime/Managing/Debugging/DebugManager.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UnityEngine; - -namespace FishNet.Managing.Debugging -{ - /// - /// A container for debugging. - /// - [DisallowMultipleComponent] - [AddComponentMenu("FishNet/Manager/DebugManager")] - public class DebugManager : MonoBehaviour - { - public bool ObserverRpcLinks = true; - public bool TargetRpcLinks = true; - public bool ReplicateRpcLinks = true; - public bool ReconcileRpcLinks = true; - public bool ServerRpcLinks = true; - } - - -} diff --git a/Assets/FishNet/Runtime/Managing/Debugging/DebugManager.cs.meta b/Assets/FishNet/Runtime/Managing/Debugging/DebugManager.cs.meta deleted file mode 100644 index b36061b..0000000 --- a/Assets/FishNet/Runtime/Managing/Debugging/DebugManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6d0962ead4b02a34aae248fccce671ce -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Debugging/ParseLogger.cs b/Assets/FishNet/Runtime/Managing/Debugging/ParseLogger.cs deleted file mode 100644 index 558cfdb..0000000 --- a/Assets/FishNet/Runtime/Managing/Debugging/ParseLogger.cs +++ /dev/null @@ -1,73 +0,0 @@ -#if UNITY_EDITOR || DEVELOPMENT_BUILD -using FishNet.Managing.Logging; -using FishNet.Object; -using FishNet.Serializing; -using FishNet.Transporting; -using System; -using System.Collections.Generic; -using System.Text; -using UnityEngine; - -namespace FishNet.Managing.Debugging -{ - - internal class ParseLogger - { - /// - /// Contains the last several non-split packets to arrive. This is used for debugging. - /// - private Queue _incomingPacketIds = new Queue(); - /// - /// Maximum number of packets allowed to be queued. - /// - private const int PACKET_COUNT = 5; - - /// - /// Resets data. - /// - internal void Reset() - { - _incomingPacketIds.Clear(); - } - - /// - /// Adds a packet to data. - /// - /// - internal void AddPacket(PacketId pId) - { - _incomingPacketIds.Enqueue(pId); - if (_incomingPacketIds.Count > PACKET_COUNT) - _incomingPacketIds.Dequeue(); - } - - /// - /// Prints current data. - /// - internal void Print(NetworkManager nm) - { - if (nm == null) - nm = InstanceFinder.NetworkManager; - - //Only log if a NM was found. - if (nm != null) - { - StringBuilder sb = new StringBuilder(); - foreach (PacketId item in _incomingPacketIds) - sb.Insert(0, $"{item.ToString()}{Environment.NewLine}"); - - NetworkObject lastNob = Reader.LastNetworkObject; - string nobData = (lastNob == null) ? "Unset" : $"Id {lastNob.ObjectId} on gameObject {lastNob.name}"; - NetworkBehaviour lastNb = Reader.LastNetworkBehaviour; - string nbData = (lastNb == null) ? "Unset" : lastNb.GetType().Name; - - nm.LogError($"The last {_incomingPacketIds.Count} packets to arrive are: {Environment.NewLine}{sb.ToString()}"); - nm.LogError($"The last parsed NetworkObject is {nobData}, and NetworkBehaviour {nbData}."); - } - - Reset(); - } - } - -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Debugging/ParseLogger.cs.meta b/Assets/FishNet/Runtime/Managing/Debugging/ParseLogger.cs.meta deleted file mode 100644 index 0b7d4f2..0000000 --- a/Assets/FishNet/Runtime/Managing/Debugging/ParseLogger.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: afc241e869d97a44f8339510586dce73 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Editor.meta b/Assets/FishNet/Runtime/Managing/Editor.meta deleted file mode 100644 index 7f31d5b..0000000 --- a/Assets/FishNet/Runtime/Managing/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 30f99c38769dfc548b3b57c6866f6a44 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Editor/NetworkManagerEditor.cs b/Assets/FishNet/Runtime/Managing/Editor/NetworkManagerEditor.cs deleted file mode 100644 index 0f0bbfd..0000000 --- a/Assets/FishNet/Runtime/Managing/Editor/NetworkManagerEditor.cs +++ /dev/null @@ -1,71 +0,0 @@ -#if UNITY_EDITOR -using FishNet.Managing.Object; -using UnityEditor; -using UnityEngine; - -namespace FishNet.Managing.Editing -{ - [CustomEditor(typeof(NetworkManager))] - public class NetworkManagerEditor : Editor - { - private SerializedProperty _logging; - private SerializedProperty _refreshDefaultPrefabs; - private SerializedProperty _runInBackground; - private SerializedProperty _dontDestroyOnLoad; - private SerializedProperty _persistence; - private SerializedProperty _spawnablePrefabs; - private SerializedProperty _objectPool; - - private void OnEnable() - { - _logging = serializedObject.FindProperty("_logging"); - _refreshDefaultPrefabs = serializedObject.FindProperty("_refreshDefaultPrefabs"); - _runInBackground = serializedObject.FindProperty("_runInBackground"); - _dontDestroyOnLoad = serializedObject.FindProperty("_dontDestroyOnLoad"); - _persistence = serializedObject.FindProperty("_persistence"); - _spawnablePrefabs = serializedObject.FindProperty("_spawnablePrefabs"); - _objectPool = serializedObject.FindProperty("_objectPool"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - NetworkManager networkManager = (NetworkManager)target; - - GUI.enabled = false; - EditorGUILayout.ObjectField("Script:", MonoScript.FromMonoBehaviour(networkManager), typeof(NetworkManager), false); - GUI.enabled = true; - - //EditorGUILayout.BeginVertical(GUI.skin.box); - //EditorGUILayout.EndVertical(); - - - EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_runInBackground); - EditorGUILayout.PropertyField(_dontDestroyOnLoad); - EditorGUILayout.PropertyField(_persistence); - EditorGUILayout.Space(); - EditorGUI.indentLevel--; - - EditorGUILayout.LabelField("Logging", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_logging); - EditorGUILayout.Space(); - EditorGUI.indentLevel--; - - EditorGUILayout.LabelField("Prefabs", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_spawnablePrefabs); - EditorGUILayout.PropertyField(_objectPool); - EditorGUILayout.PropertyField(_refreshDefaultPrefabs); - - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - - serializedObject.ApplyModifiedProperties(); - } - } -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Editor/NetworkManagerEditor.cs.meta b/Assets/FishNet/Runtime/Managing/Editor/NetworkManagerEditor.cs.meta deleted file mode 100644 index 587918d..0000000 --- a/Assets/FishNet/Runtime/Managing/Editor/NetworkManagerEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4e8e16b3e97106a4980b954c56d7bbc5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Logging.meta b/Assets/FishNet/Runtime/Managing/Logging.meta deleted file mode 100644 index 8796da6..0000000 --- a/Assets/FishNet/Runtime/Managing/Logging.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 756fcf2bc72a3214baf43099a0be9799 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Logging/LevelLoggingConfiguration.cs b/Assets/FishNet/Runtime/Managing/Logging/LevelLoggingConfiguration.cs deleted file mode 100644 index dc83b59..0000000 --- a/Assets/FishNet/Runtime/Managing/Logging/LevelLoggingConfiguration.cs +++ /dev/null @@ -1,142 +0,0 @@ -using FishNet.Documenting; -using System; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Managing.Logging -{ - - /// - /// Configuration ScriptableObject specifying which data to log. Used in conjuction with NetworkManager. - /// - [CreateAssetMenu(fileName = "New LevelLoggingConfiguration", menuName = "FishNet/Logging/Level Logging Configuration")] - public class LevelLoggingConfiguration : LoggingConfiguration - { - - #region Serialized. - /// - /// Type of logging to use for development builds and editor. - /// - [Tooltip("Type of logging to use for development builds and editor.")] - [SerializeField] - private LoggingType _developmentLogging = LoggingType.Common; - /// - /// Type of logging to use for GUI builds. - /// - [Tooltip("Type of logging to use for GUI builds.")] - [SerializeField] - private LoggingType _guiLogging = LoggingType.Warning; - /// - /// Type of logging to use for headless builds. - /// - [Tooltip("Type of logging to use for headless builds.")] - [SerializeField] - private LoggingType _headlessLogging = LoggingType.Error; - #endregion - - #region Private. - /// - /// True when initialized. - /// - private bool _initialized; - /// - /// Highest type which can be logged. - /// - private LoggingType _highestLoggingType = LoggingType.Off; - #endregion - - [APIExclude] - public void LoggingConstructor(bool loggingEnabled, LoggingType development, LoggingType gui, LoggingType headless) - { - base.LoggingEnabled = loggingEnabled; - _developmentLogging = development; - _guiLogging = gui; - _headlessLogging = headless; - } - - /// - /// Initializes script for use. - /// - /// - public override void InitializeOnce() - { - byte currentHighest = (byte)LoggingType.Off; -#if UNITY_SERVER //if headless. - currentHighest = Math.Max(currentHighest, (byte)_headlessLogging); -#endif -#if UNITY_EDITOR || DEVELOPMENT_BUILD //if editor or development. - currentHighest = Math.Max(currentHighest, (byte)_developmentLogging); -#endif -#if !UNITY_EDITOR && !UNITY_SERVER //if a build. - currentHighest = Math.Max(currentHighest, (byte)_guiLogging); -#endif - _highestLoggingType = (LoggingType)currentHighest; - _initialized = true; - } - - /// - /// True if can log for loggingType. - /// - /// Type of logging being filtered. - /// - public override bool CanLog(LoggingType loggingType) - { - if (!base.LoggingEnabled) - return false; - - if (!_initialized) - { -#if UNITY_EDITOR || DEVELOPMENT_BUILD - if (Application.isPlaying) - Debug.LogError("CanLog called before being initialized."); - else - return true; -#endif - return false; - } - - return ((byte)loggingType <= (byte)_highestLoggingType); - } - - /// - /// Logs a common value if can log. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Log(string value) - { - if (CanLog(LoggingType.Common)) - Debug.Log(value); - } - - /// - /// Logs a warning value if can log. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void LogWarning(string value) - { - if (CanLog(LoggingType.Warning)) - Debug.LogWarning(value); - } - - /// - /// Logs an error value if can log. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void LogError(string value) - { - if (CanLog(LoggingType.Error)) - Debug.LogError(value); - } - - /// - /// Clones this logging configuration. - /// - /// - public override LoggingConfiguration Clone() - { - LevelLoggingConfiguration copy = ScriptableObject.CreateInstance(); - copy.LoggingConstructor(base.LoggingEnabled, _developmentLogging, _guiLogging, _headlessLogging); - return copy; - } - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Logging/LevelLoggingConfiguration.cs.meta b/Assets/FishNet/Runtime/Managing/Logging/LevelLoggingConfiguration.cs.meta deleted file mode 100644 index 109c326..0000000 --- a/Assets/FishNet/Runtime/Managing/Logging/LevelLoggingConfiguration.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 925fc096350b81f4f82f4fe4ac0c4dda -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Logging/LoggingConfiguration.cs b/Assets/FishNet/Runtime/Managing/Logging/LoggingConfiguration.cs deleted file mode 100644 index e3f5379..0000000 --- a/Assets/FishNet/Runtime/Managing/Logging/LoggingConfiguration.cs +++ /dev/null @@ -1,57 +0,0 @@ -using FishNet.Documenting; -using System; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Managing.Logging -{ - - /// - /// Base for logging configurations. - /// - public abstract class LoggingConfiguration : ScriptableObject - { - - #region Serialized. - /// - /// True to use logging features. False to disable all logging. - /// - [Tooltip("True to use logging features. False to disable all logging.")] - public bool LoggingEnabled = true; - #endregion - - /// - /// Initializes script for use. - /// - /// - public virtual void InitializeOnce() { } - - /// - /// True if can log for loggingType. - /// - /// Type of logging being filtered. - /// - public abstract bool CanLog(LoggingType loggingType); - - /// - /// Logs a common value if can log. - /// - public abstract void Log(string value); - - /// - /// Logs a warning value if can log. - /// - public abstract void LogWarning(string value); - - /// - /// Logs an error value if can log. - /// - public abstract void LogError(string value); - - /// - /// Clones this logging configuration. - /// - /// - public abstract LoggingConfiguration Clone(); - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Logging/LoggingConfiguration.cs.meta b/Assets/FishNet/Runtime/Managing/Logging/LoggingConfiguration.cs.meta deleted file mode 100644 index a448994..0000000 --- a/Assets/FishNet/Runtime/Managing/Logging/LoggingConfiguration.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 438d7e99b7655114891d4fa6e9f68c7d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Logging/LoggingType.cs b/Assets/FishNet/Runtime/Managing/Logging/LoggingType.cs deleted file mode 100644 index e5a82e1..0000000 --- a/Assets/FishNet/Runtime/Managing/Logging/LoggingType.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace FishNet.Managing.Logging -{ - /// - /// Type of logging being filtered. - /// - public enum LoggingType : byte - { - /// - /// Disable logging. - /// - Off = 0, - /// - /// Only log errors. - /// - Error = 1, - /// - /// Log warnings and errors. - /// - Warning = 2, - /// - /// Log all common activities, warnings, and errors. - /// - Common = 3 - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Logging/LoggingType.cs.meta b/Assets/FishNet/Runtime/Managing/Logging/LoggingType.cs.meta deleted file mode 100644 index 96f2758..0000000 --- a/Assets/FishNet/Runtime/Managing/Logging/LoggingType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8bf0a7ab3f60fe44984fcfd16d8fe7b4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/NetworkManager.Logging.cs b/Assets/FishNet/Runtime/Managing/NetworkManager.Logging.cs deleted file mode 100644 index e301c9e..0000000 --- a/Assets/FishNet/Runtime/Managing/NetworkManager.Logging.cs +++ /dev/null @@ -1,121 +0,0 @@ -using FishNet.Documenting; -using FishNet.Managing.Logging; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Managing -{ - public partial class NetworkManager : MonoBehaviour - { - #region Serialized. - /// - /// Logging configuration to use. When empty default logging settings will be used. - /// - [Tooltip("Logging configuration to use. When empty default logging settings will be used.")] - [SerializeField] - private LoggingConfiguration _logging; - #endregion - - #region Const. - private const string ERROR_LOGGING_PREFIX = "Error - "; - private const string WARNING_LOGGING_PREFIX = "Warning - "; - private const string COMMON_LOGGING_PREFIX = "Log - "; - #endregion - - /// - /// Initializes logging settings. - /// - private void InitializeLogging() - { - if (_logging == null) - _logging = ScriptableObject.CreateInstance(); - else - _logging = _logging.Clone(); - - _logging.InitializeOnce(); - } - - - /// - /// True if can log for loggingType. - /// - /// - /// - [APIExclude] - public static bool StaticCanLog(LoggingType loggingType) - { - NetworkManager nm = InstanceFinder.NetworkManager; - return (nm == null) ? false : nm.CanLog(loggingType); - } - - /// - /// True if can log for loggingType. - /// - /// Type of logging being filtered. - /// - public bool CanLog(LoggingType loggingType) - { - return _logging.CanLog(loggingType); - } - - - /// - /// Performs a common log, should logging settings permit it. - /// - [APIExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void StaticLog(string value) => InstanceFinder.NetworkManager?.Log(value); - - /// - /// Performs a common log, should logging settings permit it. - /// - public void Log(string value) - { - _logging.Log(value); - } - - /// - /// Performs a log using the loggingType, should logging settings permit it. - /// - public void Log(LoggingType loggingType, string value) - { - if (loggingType == LoggingType.Common) - _logging.Log(value); - else if (loggingType == LoggingType.Warning) - _logging.LogWarning(value); - else if (loggingType == LoggingType.Error) - _logging.LogError(value); - } - - /// - /// Performs a warning log, should logging settings permit it. - /// - /// - [APIExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void StaticLogWarning(string value) => InstanceFinder.NetworkManager?.LogWarning(value); - /// - /// Performs a warning log, should logging settings permit it. - /// - public void LogWarning(string value) - { - _logging.LogWarning(value); - } - - /// - /// Performs an error log, should logging settings permit it. - /// - [APIExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void StaticLogError(string value) => InstanceFinder.NetworkManager?.LogError(value); - /// - /// Performs an error log, should logging settings permit it. - /// - public void LogError(string value) - { - _logging.LogError(value); - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/NetworkManager.Logging.cs.meta b/Assets/FishNet/Runtime/Managing/NetworkManager.Logging.cs.meta deleted file mode 100644 index aef818b..0000000 --- a/Assets/FishNet/Runtime/Managing/NetworkManager.Logging.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4200d74f31ee8144fb606ce88ad1b747 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/NetworkManager.Pro.cs b/Assets/FishNet/Runtime/Managing/NetworkManager.Pro.cs deleted file mode 100644 index fd9ed2a..0000000 --- a/Assets/FishNet/Runtime/Managing/NetworkManager.Pro.cs +++ /dev/null @@ -1,20 +0,0 @@ -using FishNet.Component.ColliderRollback; -using UnityEngine; - -namespace FishNet.Managing -{ - public sealed partial class NetworkManager : MonoBehaviour - { - - #region Public. - /// - /// RollbackManager for this NetworkManager. - /// - public RollbackManager RollbackManager { get; private set; } - #endregion - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/NetworkManager.Pro.cs.meta b/Assets/FishNet/Runtime/Managing/NetworkManager.Pro.cs.meta deleted file mode 100644 index e25b92c..0000000 --- a/Assets/FishNet/Runtime/Managing/NetworkManager.Pro.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: cb7fdb186794b674788273f3b211ec5b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/NetworkManager.QOL.cs b/Assets/FishNet/Runtime/Managing/NetworkManager.QOL.cs deleted file mode 100644 index c04f7e1..0000000 --- a/Assets/FishNet/Runtime/Managing/NetworkManager.QOL.cs +++ /dev/null @@ -1,259 +0,0 @@ -using FishNet.Managing.Object; -using FishNet.Object; -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityComponent = UnityEngine.Component; - - -namespace FishNet.Managing -{ - public partial class NetworkManager : MonoBehaviour - { - #region Serialized. - /// - /// - /// - [Tooltip("Collection to use for spawnable objects.")] - [SerializeField] - private PrefabObjects _spawnablePrefabs; - /// - /// Collection to use for spawnable objects. - /// - public PrefabObjects SpawnablePrefabs { get => _spawnablePrefabs; set => _spawnablePrefabs = value; } - /// - /// - /// - private Dictionary _runtimeSpawnablePrefabs = new Dictionary(); - /// - /// Collection to use for spawnable objects added at runtime, such as addressables. - /// - public IReadOnlyDictionary RuntimeSpawnablePrefabs => _runtimeSpawnablePrefabs; - #endregion - - #region Private. - /// - /// Delegates waiting to be invoked when a component is registered. - /// - private Dictionary>> _pendingInvokes = new Dictionary>>(); - /// - /// Currently registered components. - /// - private Dictionary _registeredComponents = new Dictionary(); - #endregion - - /// - /// Gets the PrefabObjects to use for spawnableCollectionId. - /// - /// Type of PrefabObjects to return. This is also used to create an instance of type when createIfMissing is true. - /// Id to use. 0 will return the configured SpawnablePrefabs. - /// True to create and assign a PrefabObjects if missing for the collectionId. - /// - public PrefabObjects GetPrefabObjects(ushort spawnableCollectionId, bool createIfMissing) where T : PrefabObjects - { - if (spawnableCollectionId == 0) - { - if (createIfMissing) - { - LogError($"SpawnableCollectionId cannot be 0 when create missing is true."); - return null; - } - else - { - return SpawnablePrefabs; - } - } - - PrefabObjects po; - if (!_runtimeSpawnablePrefabs.TryGetValue(spawnableCollectionId, out po)) - { - //Do not create missing, return null for not found. - if (!createIfMissing) - return null; - - po = ScriptableObject.CreateInstance(); - po.SetCollectionId(spawnableCollectionId); - _runtimeSpawnablePrefabs[spawnableCollectionId] = po; - } - - return po; - } - - /// - /// Removes the PrefabObjects collection from memory. - /// This should only be called after you properly disposed of it's contents properly. - /// - /// CollectionId to remove. - /// True if collection was found and removed. - public bool RemoveSpawnableCollection(ushort spawnableCollectionId) - { - return _runtimeSpawnablePrefabs.Remove(spawnableCollectionId); - } - - /// - /// Gets the index a prefab uses. Can be used in conjuction with GetPrefab. - /// - /// - /// True if to get from the server collection. - /// Returns index if found, and -1 if not found. - public int GetPrefabIndex(GameObject prefab, bool asServer) - { - int count = SpawnablePrefabs.GetObjectCount(); - for (int i = 0; i < count; i++) - { - GameObject go = SpawnablePrefabs.GetObject(asServer, i).gameObject; - if (go == prefab) - return i; - } - - //Fall through, not found. - return -1; - } - - /// - /// Returns a prefab with prefabId. - /// This method will bypass object pooling. - /// - /// PrefabId to get. - /// True if getting the prefab asServer. - public NetworkObject GetPrefab(int prefabId, bool asServer) - { - return SpawnablePrefabs.GetObject(asServer, prefabId); - } - - - #region Registered components - /// - /// Invokes an action when a specified component becomes registered. Action will invoke immediately if already registered. - /// - /// Component type. - /// Action to invoke. - public void RegisterInvokeOnInstance(Action handler) where T : UnityComponent - { - T result = GetInstance(false); - //If not found yet make a pending invoke. - if (result == default(T)) - { - string tName = GetInstanceName(); - List> handlers; - if (!_pendingInvokes.TryGetValue(tName, out handlers)) - { - handlers = new List>(); - _pendingInvokes[tName] = handlers; - } - - handlers.Add(handler); - } - //Already exist, invoke right away. - else - { - handler.Invoke(result); - } - } - /// - /// Removes an action to be invokes when a specified component becomes registered. - /// - /// Component type. - /// Action to invoke. - public void UnregisterInvokeOnInstance(Action handler) where T : UnityComponent - { - string tName = GetInstanceName(); - List> handlers; - if (!_pendingInvokes.TryGetValue(tName, out handlers)) - return; - - handlers.Remove(handler); - //Do not remove pending to prevent garbage collection later on list recreation. - } - /// - /// Returns if an instance exists for type. - /// - /// - /// - public bool HasInstance() where T : UnityComponent - { - return (GetInstance(false) != null); - } - /// - /// Returns class of type if found within CodegenBase classes. - /// - /// - /// True to warn if component is not registered. - /// - public T GetInstance(bool warn = true) where T : UnityComponent - { - string tName = GetInstanceName(); - if (_registeredComponents.TryGetValue(tName, out UnityComponent result)) - return (T)result; - else if (warn) - LogWarning($"Component {tName} is not registered."); - - return default(T); - } - /// - /// Registers a new component to this NetworkManager. - /// - /// Type to register. - /// Reference of the component being registered. - /// True to replace existing references. - public void RegisterInstance(T component, bool replace = true) where T : UnityComponent - { - string tName = GetInstanceName(); - if (_registeredComponents.ContainsKey(tName) && !replace) - { - LogWarning($"Component {tName} is already registered."); - } - else - { - _registeredComponents[tName] = component; - RemoveNullPendingDelegates(); - //If in pending invokes also send these out. - if (_pendingInvokes.TryGetValue(tName, out List> dels)) - { - for (int i = 0; i < dels.Count; i++) - dels[i].Invoke(component); - /* Clear delegates but do not remove dictionary entry - * to prevent list from being re-initialized. */ - dels.Clear(); - } - } - } - /// - /// Unregisters a component from this NetworkManager. - /// - /// Type to unregister. - public void UnregisterInstance() where T : UnityComponent - { - string tName = GetInstanceName(); - _registeredComponents.Remove(tName); - } - /// - /// Removes delegates from pending invokes when may have gone missing. - /// - private void RemoveNullPendingDelegates() - { - foreach (List> handlers in _pendingInvokes.Values) - { - for (int i = 0; i < handlers.Count; i++) - { - if (handlers[i] == null) - { - handlers.RemoveAt(i); - i--; - } - } - } - } - /// - /// Returns the name to use for T. - /// - private string GetInstanceName() - { - return typeof(T).FullName; - } - #endregion - - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/NetworkManager.QOL.cs.meta b/Assets/FishNet/Runtime/Managing/NetworkManager.QOL.cs.meta deleted file mode 100644 index eddffd8..0000000 --- a/Assets/FishNet/Runtime/Managing/NetworkManager.QOL.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5761633dda73e7447a3a41b87354d06e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/NetworkManager.cs b/Assets/FishNet/Runtime/Managing/NetworkManager.cs deleted file mode 100644 index de29674..0000000 --- a/Assets/FishNet/Runtime/Managing/NetworkManager.cs +++ /dev/null @@ -1,573 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing.Client; -using FishNet.Managing.Server; -using FishNet.Managing.Timing; -using FishNet.Managing.Transporting; -using UnityEngine; -using FishNet.Managing.Scened; -using FishNet.Authenticating; -using FishNet.Object; -using FishNet.Documenting; -using FishNet.Managing.Logging; -using System.Collections.Generic; -using System; -using FishNet.Managing.Observing; -using System.Linq; -using FishNet.Managing.Debugging; -using FishNet.Managing.Object; -using FishNet.Transporting; -using FishNet.Utility.Extension; -using FishNet.Managing.Statistic; -using FishNet.Utility.Performance; -using FishNet.Component.ColliderRollback; -using FishNet.Managing.Predicting; -using System.Runtime.CompilerServices; -#if UNITY_EDITOR -using FishNet.Editing.PrefabCollectionGenerator; -#endif - -namespace FishNet.Managing -{ - /// - /// Acts as a container for all things related to your networking session. - /// - [DefaultExecutionOrder(short.MinValue)] - [DisallowMultipleComponent] - [AddComponentMenu("FishNet/Manager/NetworkManager")] - public sealed partial class NetworkManager : MonoBehaviour - { - #region Types. - /// - /// Which socket to iterate data on first when as host. - /// - public enum HostIterationOrder - { - ServerFirst, - ClientFirst - } - /// - /// How to persist with multiple NetworkManagers. - /// - public enum PersistenceType - { - /// - /// Destroy any new NetworkManagers. - /// - DestroyNewest, - /// - /// Destroy previous NetworkManager when a new NetworkManager occurs. - /// - DestroyOldest, - /// - /// Allow multiple NetworkManagers, do not destroy any automatically. - /// - AllowMultiple - } - - #endregion - - #region Public. - /// - /// True if this instance of the NetworkManager is initialized. - /// - public bool Initialized { get; private set; } - /// - /// - /// - private static List _instances = new List(); - /// - /// Currently initialized NetworkManagers. - /// - public static IReadOnlyCollection Instances - { - get - { - /* Remove null instances of NetworkManager. - * This shouldn't happen because instances are removed - * OnDestroy but none the less something is causing - * it. */ - for (int i = 0; i < _instances.Count; i++) - { - if (_instances[i] == null) - { - _instances.RemoveAt(i); - i--; - } - } - return _instances; - } - } - - /// - /// True if server is active. - /// - public bool IsServer => ServerManager.Started; - /// - /// True if only the server is active. - /// - public bool IsServerOnly => (IsServer && !IsClient); - /// - /// True if the client is active and authenticated. - /// - public bool IsClient => (ClientManager.Started && ClientManager.Connection.Authenticated); - /// - /// True if only the client is active and authenticated. - /// - public bool IsClientOnly => (!IsServer && IsClient); - /// - /// True if client and server are active. - /// - public bool IsHost => (IsServer && IsClient); - /// - /// True if client nor server are active. - /// - public bool IsOffline => (!IsServer && !IsClient); - /// - /// PredictionManager for this NetworkManager. - /// - internal PredictionManager PredictionManager { get; private set; } - /// - /// ServerManager for this NetworkManager. - /// - public ServerManager ServerManager { get; private set; } - /// - /// ClientManager for this NetworkManager. - /// - public ClientManager ClientManager { get; private set; } - /// - /// TransportManager for this NetworkManager. - /// - public TransportManager TransportManager { get; private set; } - /// - /// TimeManager for this NetworkManager. - /// - public TimeManager TimeManager { get; private set; } - /// - /// SceneManager for this NetworkManager. - /// - public SceneManager SceneManager { get; private set; } - /// - /// ObserverManager for this NetworkManager. - /// - public ObserverManager ObserverManager { get; private set; } - /// - /// Authenticator for this NetworkManager. May be null if no Authenticator is used. - /// - [Obsolete("Use ServerManager.GetAuthenticator or ServerManager.SetAuthenticator instead.")] //Remove on 2023/06/01 - public Authenticator Authenticator => ServerManager.Authenticator; - /// - /// DebugManager for this NetworkManager. - /// - public DebugManager DebugManager { get; private set; } - /// - /// StatisticsManager for this NetworkManager. - /// - public StatisticsManager StatisticsManager { get; private set; } - /// - /// An empty connection reference. Used when a connection cannot be found to prevent object creation. - /// - [APIExclude] - public static NetworkConnection EmptyConnection { get; private set; } = new NetworkConnection(); - #endregion - - #region Internal. - /// - /// Starting index for RpcLinks. - /// - internal static ushort StartingRpcLinkIndex; - #endregion - - #region Serialized. - /// - /// True to refresh the DefaultPrefabObjects collection whenever the editor enters play mode. This is an attempt to alleviate the DefaultPrefabObjects scriptable object not refreshing when using multiple editor applications such as ParrelSync. - /// - [Tooltip("True to refresh the DefaultPrefabObjects collection whenever the editor enters play mode. This is an attempt to alleviate the DefaultPrefabObjects scriptable object not refreshing when using multiple editor applications such as ParrelSync.")] - [SerializeField] - private bool _refreshDefaultPrefabs = false; - /// - /// True to have your application run while in the background. - /// - [Tooltip("True to have your application run while in the background.")] - [SerializeField] - private bool _runInBackground = true; - /// - /// True to make this instance DontDestroyOnLoad. This is typical if you only want one NetworkManager. - /// - [Tooltip("True to make this instance DontDestroyOnLoad. This is typical if you only want one NetworkManager.")] - [SerializeField] - private bool _dontDestroyOnLoad = true; - /// - /// Object pool to use for this NetworkManager. Value may be null. - /// - [Tooltip("Object pool to use for this NetworkManager. Value may be null.")] - [SerializeField] - private ObjectPool _objectPool; - /// - /// How to persist when other NetworkManagers are introduced. - /// - [Tooltip("How to persist when other NetworkManagers are introduced.")] - [SerializeField] - private PersistenceType _persistence = PersistenceType.DestroyNewest; - #endregion - - #region Private. - /// - /// True if this NetworkManager can persist after Awake checks. - /// - private bool _canPersist; - #endregion - - #region Const. - /// - /// Maximum framerate allowed. - /// - internal const ushort MAXIMUM_FRAMERATE = 500; - #endregion - - - private void Awake() - { - InitializeLogging(); - if (!ValidateSpawnablePrefabs(true)) - return; - - if (StartingRpcLinkIndex == 0) - StartingRpcLinkIndex = (ushort)(EnumFN.GetHighestValue() + 1); - - bool isDefaultPrefabs = (SpawnablePrefabs != null && SpawnablePrefabs is DefaultPrefabObjects); -#if UNITY_EDITOR - /* If first instance then force - * default prefabs to repopulate. - * This is only done in editor because - * cloning tools sometimes don't synchronize - * scriptable object changes, which is what - * the default prefabs is. */ - if (_refreshDefaultPrefabs && _instances.Count == 0 && isDefaultPrefabs) - { - Generator.IgnorePostProcess = true; - Debug.Log("DefaultPrefabCollection is being refreshed."); - Generator.GenerateFull(); - Generator.IgnorePostProcess = false; - } -#endif - //If default prefabs then also make a new instance and sort them. - if (isDefaultPrefabs) - { - DefaultPrefabObjects originalDpo = (DefaultPrefabObjects)SpawnablePrefabs; - //If not editor then a new instance must be made and sorted. - DefaultPrefabObjects instancedDpo = ScriptableObject.CreateInstance(); - instancedDpo.AddObjects(originalDpo.Prefabs.ToList(), false); - instancedDpo.Sort(); - SpawnablePrefabs = instancedDpo; - } - - _canPersist = CanInitialize(); - if (!_canPersist) - return; - - if (TryGetComponent(out _)) - LogError($"NetworkObject component found on the NetworkManager object {gameObject.name}. This is not allowed and will cause problems. Remove the NetworkObject component from this object."); - - SpawnablePrefabs.InitializePrefabRange(0); - SpawnablePrefabs.SetCollectionId(0); - - SetDontDestroyOnLoad(); - SetRunInBackground(); - DebugManager = GetOrCreateComponent(); - TransportManager = GetOrCreateComponent(); - - ServerManager = GetOrCreateComponent(); - ClientManager = GetOrCreateComponent(); - TimeManager = GetOrCreateComponent(); - SceneManager = GetOrCreateComponent(); - ObserverManager = GetOrCreateComponent(); - RollbackManager = GetOrCreateComponent(); - PredictionManager = GetOrCreateComponent(); - StatisticsManager = GetOrCreateComponent(); - if (_objectPool == null) - _objectPool = GetOrCreateComponent(); - - InitializeComponents(); - - _instances.Add(this); - Initialized = true; - } - - private void Start() - { - ServerManager.StartForHeadless(); - } - - private void OnDestroy() - { - _instances.Remove(this); - } - - /// - /// Initializes components. To be called after all components are added. - /// - private void InitializeComponents() - { - TimeManager.InitializeOnce_Internal(this); - TimeManager.OnLateUpdate += TimeManager_OnLateUpdate; - SceneManager.InitializeOnce_Internal(this); - TransportManager.InitializeOnce_Internal(this); - ClientManager.InitializeOnce_Internal(this); - ServerManager.InitializeOnce_Internal(this); - ObserverManager.InitializeOnce_Internal(this); - RollbackManager.InitializeOnce_Internal(this); - PredictionManager.InitializeOnce_Internal(this); - StatisticsManager.InitializeOnce_Internal(this); - _objectPool.InitializeOnce(this); - } - - /// - /// Updates the frame rate based on server and client status. - /// - internal void UpdateFramerate() - { - bool clientStarted = ClientManager.Started; - bool serverStarted = ServerManager.Started; - - int frameRate = 0; - //If both client and server are started then use whichever framerate is higher. - if (clientStarted && serverStarted) - frameRate = Math.Max(ServerManager.FrameRate, ClientManager.FrameRate); - else if (clientStarted) - frameRate = ClientManager.FrameRate; - else if (serverStarted) - frameRate = ServerManager.FrameRate; - - /* Make sure framerate isn't set to max on server. - * If it is then default to tick rate. If framerate is - * less than tickrate then also set to tickrate. */ -#if UNITY_SERVER - ushort minimumServerFramerate = (ushort)(TimeManager.TickRate + 1); - if (frameRate == MAXIMUM_FRAMERATE) - frameRate = minimumServerFramerate; - else if (frameRate < TimeManager.TickRate) - frameRate = minimumServerFramerate; -#endif - //If there is a framerate to set. - if (frameRate > 0) - Application.targetFrameRate = frameRate; - } - - /// - /// Called when MonoBehaviours call LateUpdate. - /// - private void TimeManager_OnLateUpdate() - { - /* Some reason runinbackground becomes unset - * or the setting goes ignored some times when it's set - * in awake. Rather than try to fix or care why Unity - * does this just set it in LateUpdate(or Update). */ - SetRunInBackground(); - } - - - /// - /// Returns if this NetworkManager can initialize. - /// - /// - private bool CanInitialize() - { - /* If allow multiple then any number of - * NetworkManagers are allowed. Don't - * automatically destroy any. */ - if (_persistence == PersistenceType.AllowMultiple) - return true; - - List instances = Instances.ToList(); - //This is the first instance, it may initialize. - if (instances.Count == 0) - return true; - - //First instance of NM. - NetworkManager firstInstance = instances[0]; - - //If to destroy the newest. - if (_persistence == PersistenceType.DestroyNewest) - { - Log($"NetworkManager on object {gameObject.name} is being destroyed due to persistence type {_persistence}. A NetworkManager instance already exist on {firstInstance.name}."); - Destroy(gameObject); - //This one is being destroyed because its the newest. - return false; - } - //If to destroy the oldest. - else if (_persistence == PersistenceType.DestroyOldest) - { - Log($"NetworkManager on object {firstInstance.name} is being destroyed due to persistence type {_persistence}. A NetworkManager instance has been created on {gameObject.name}."); - Destroy(firstInstance.gameObject); - //This being the new one will persist, allow initialization. - return true; - } - //Unhandled. - else - { - Log($"Persistance type of {_persistence} is unhandled on {gameObject.name}. Initialization will not proceed."); - return false; - } - } - - /// - /// Validates SpawnablePrefabs field and returns if validated successfully. - /// - /// - private bool ValidateSpawnablePrefabs(bool print) - { - //If null and object is in a scene. - if (SpawnablePrefabs == null && !string.IsNullOrEmpty(gameObject.scene.name)) - { - //Always throw an error as this would cause failure. - if (print) - Debug.LogError($"SpawnablePrefabs is null on {gameObject.name}. Select the NetworkManager in scene {gameObject.scene.name} and choose a prefabs file. Choosing DefaultPrefabObjects will automatically populate prefabs for you."); - return false; - } - - return true; - } - - /// - /// Sets DontDestroyOnLoad if configured to. - /// - private void SetDontDestroyOnLoad() - { - if (_dontDestroyOnLoad) - DontDestroyOnLoad(this); - } - - /// - /// Sets Application.runInBackground to runInBackground. - /// - private void SetRunInBackground() - { - Application.runInBackground = _runInBackground; - } - - /// - /// Gets a component, creating and adding it if it does not exist. - /// - /// Value which may already be set. When not null this is returned instead. - private T GetOrCreateComponent(T presetValue = null) where T : UnityEngine.Component - { - //If already set then return set value. - if (presetValue != null) - return presetValue; - - if (gameObject.TryGetComponent(out T result)) - return result; - else - return gameObject.AddComponent(); - } - - /// - /// Clears a client collection after disposing of the NetworkConnections. - /// - /// - internal void ClearClientsCollection(Dictionary clients) - { - foreach (NetworkConnection conn in clients.Values) - conn.Dispose(); - - clients.Clear(); - } - - #region Object pool. - /// - /// Returns an instantiated copy of prefab. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public NetworkObject GetPooledInstantiated(NetworkObject prefab, bool asServer) - { - return GetPooledInstantiated(prefab, 0, asServer); - } - /// - /// Returns an instantiated copy of prefab. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public NetworkObject GetPooledInstantiated(NetworkObject prefab, ushort collectionId, bool asServer) - { - return GetPooledInstantiated(prefab.PrefabId, collectionId, asServer); - } - /// - /// Returns an instantiated copy of prefab. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public NetworkObject GetPooledInstantiated(GameObject prefab, bool asServer) - { - return GetPooledInstantiated(prefab, 0, asServer); - } - /// - /// Returns an instantiated copy of prefab. - /// - public NetworkObject GetPooledInstantiated(GameObject prefab, ushort collectionId, bool asServer) - { - NetworkObject nob; - if (!prefab.TryGetComponent(out nob)) - { - LogError($"NetworkObject was not found on {prefab}. An instantiated NetworkObject cannot be returned."); - return null; - } - else - { - return GetPooledInstantiated(nob.PrefabId, collectionId, asServer); - } - } - /// - /// Returns an instantiated object that has prefabId. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public NetworkObject GetPooledInstantiated(int prefabId, bool asServer) - { - return GetPooledInstantiated(prefabId, 0, asServer); - } - /// - /// Returns an instantiated object that has prefabId. - /// - public NetworkObject GetPooledInstantiated(int prefabId, ushort collectionId, bool asServer) - { - return _objectPool.RetrieveObject(prefabId, collectionId, asServer); - } - /// - /// Stores an instantiated object. - /// - /// Object which was instantiated. - /// - /// True to store for the server. - [Obsolete("Use StorePooledInstantiated(NetworkObject, bool)")] //Remove on 2023/06/01. - public void StorePooledInstantiated(NetworkObject instantiated, int prefabId, bool asServer) - { - StorePooledInstantiated(instantiated, asServer); - } - /// - /// Stores an instantied object. - /// - /// Object which was instantiated. - /// True to store for the server. - public void StorePooledInstantiated(NetworkObject instantiated, bool asServer) - { - _objectPool.StoreObject(instantiated, asServer); - } - #endregion - - #region Editor. -#if UNITY_EDITOR - private void OnValidate() - { - if (SpawnablePrefabs == null) - Reset(); - } - private void Reset() - { - ValidateSpawnablePrefabs(true); - } - -#endif - - #endregion - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/NetworkManager.cs.meta b/Assets/FishNet/Runtime/Managing/NetworkManager.cs.meta deleted file mode 100644 index 1f1685d..0000000 --- a/Assets/FishNet/Runtime/Managing/NetworkManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d2c95dfde7d73b54dbbdc23155d35d36 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Object.meta b/Assets/FishNet/Runtime/Managing/Object.meta deleted file mode 100644 index 6f25714..0000000 --- a/Assets/FishNet/Runtime/Managing/Object.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: ba48f298f92e0684db6b68c8d3fc2672 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Object/DespawnWriter.cs b/Assets/FishNet/Runtime/Managing/Object/DespawnWriter.cs deleted file mode 100644 index 2111ff4..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/DespawnWriter.cs +++ /dev/null @@ -1 +0,0 @@ -//Remove on 2023/06/01 \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Object/DespawnWriter.cs.meta b/Assets/FishNet/Runtime/Managing/Object/DespawnWriter.cs.meta deleted file mode 100644 index ee1eaef..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/DespawnWriter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b444a2a7364932340a4a3dede4a434a9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Object/DualPrefab.cs b/Assets/FishNet/Runtime/Managing/Object/DualPrefab.cs deleted file mode 100644 index b0e3096..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/DualPrefab.cs +++ /dev/null @@ -1,16 +0,0 @@ -using FishNet.Object; - -namespace FishNet.Managing.Object -{ - - /// - /// When using dual prefabs, defines which prefab to spawn for server, and which for clients. - /// - [System.Serializable] - public struct DualPrefab - { - public NetworkObject Server; - public NetworkObject Client; - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Object/DualPrefab.cs.meta b/Assets/FishNet/Runtime/Managing/Object/DualPrefab.cs.meta deleted file mode 100644 index 0011412..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/DualPrefab.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 76840b2b810d8fc45aeccef03122763c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.Spawning.cs b/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.Spawning.cs deleted file mode 100644 index 925fc7f..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.Spawning.cs +++ /dev/null @@ -1,380 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing.Logging; -using FishNet.Managing.Server; -using FishNet.Object; -using FishNet.Serializing; -using FishNet.Transporting; -using FishNet.Utility.Extension; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Managing.Object -{ - public abstract partial class ManagedObjects - { - /// - /// Reads and outputs a transforms values. - /// - protected void ReadTransformProperties(Reader reader, out Vector3? localPosition, out Quaternion? localRotation, out Vector3? localScale) - { - //Read changed. - ChangedTransformProperties ctp = (ChangedTransformProperties)reader.ReadByte(); - //Position. - if (ChangedTransformPropertiesEnum.Contains(ctp, ChangedTransformProperties.LocalPosition)) - localPosition = reader.ReadVector3(); - else - localPosition = null; - //Rotation. - if (ChangedTransformPropertiesEnum.Contains(ctp, ChangedTransformProperties.LocalRotation)) - localRotation = reader.ReadQuaternion(NetworkManager.ServerManager.SpawnPacking.Rotation); - else - localRotation = null; - //Scale. - if (ChangedTransformPropertiesEnum.Contains(ctp, ChangedTransformProperties.LocalScale)) - localScale = reader.ReadVector3(); - else - localScale = null; - } - - /// - /// Writes a spawn to clients. - /// - internal void WriteSpawn_Server(NetworkObject nob, NetworkConnection connection, Writer everyoneWriter, Writer ownerWriter) - { - /* Using a number of writers to prevent rebuilding the - * packets excessively for values that are owner only - * vs values that are everyone. To save performance the - * owner writer is only written to if owner is valid. - * This makes the code a little uglier but will scale - * significantly better with more connections. - * - * EG: - * with this technique networkBehaviours are iterated - * twice if there is an owner; once for data to send to everyone - * and again for data only going to owner. - * - * The alternative would be to iterate the networkbehaviours - * for every connection it's going to and filling a single - * writer with values based on if owner or not. This would - * result in significantly more iterations. */ - PooledWriter headerWriter = WriterPool.GetWriter(); - headerWriter.WritePacketId(PacketId.ObjectSpawn); - headerWriter.WriteNetworkObjectForSpawn(nob); - if (NetworkManager.ServerManager.ShareIds || connection == nob.Owner) - headerWriter.WriteNetworkConnection(nob.Owner); - else - headerWriter.WriteInt16(-1); - - bool nested = (nob.IsNested && nob.ParentNetworkObject != null); - bool sceneObject = nob.IsSceneObject; - //Write type of spawn. - SpawnType st = SpawnType.Unset; - if (sceneObject) - st |= SpawnType.Scene; - else - st |= (nob.IsGlobal) ? SpawnType.InstantiatedGlobal : SpawnType.Instantiated; - //Add on nested if needed. - if (nested) - st |= SpawnType.Nested; - - headerWriter.WriteByte((byte)st); - //ComponentIndex for the nob. 0 is root but more appropriately there's a IsNested boolean as shown above. - headerWriter.WriteByte(nob.ComponentIndex); - //Properties on the transform which diff from serialized value. - WriteChangedTransformProperties(nob, sceneObject, nested, headerWriter); - - /* When nested the parent nob needs to be written. */ - if (nested) - headerWriter.WriteNetworkObjectId(nob.ParentNetworkObject); - - /* Writing a scene object. */ - if (sceneObject) - { - headerWriter.WriteUInt64(nob.SceneId, AutoPackType.Unpacked); - } - /* Writing a spawned object. */ - else - { - //Check to write parent behaviour or nob. - NetworkBehaviour parentNb; - Transform t = nob.transform.parent; - if (t != null) - { - parentNb = t.GetComponent(); - /* Check for a NetworkObject if there is no NetworkBehaviour. - * There is a small chance the parent object will only contain - * a NetworkObject. */ - if (parentNb == null) - { - //If null check if there is a nob. - NetworkObject parentNob = t.GetComponent(); - //ParentNob is null or not spawned. - if (!ParentIsSpawned(parentNob)) - { - headerWriter.WriteByte((byte)SpawnParentType.Unset); - } - else - { - headerWriter.WriteByte((byte)SpawnParentType.NetworkObject); - headerWriter.WriteNetworkObjectId(parentNob); - } - } - //NetworkBehaviour found on parent. - else - { - //ParentNb is null or not spawned. - if (!ParentIsSpawned(parentNb.NetworkObject)) - { - headerWriter.WriteByte((byte)SpawnParentType.Unset); - } - else - { - headerWriter.WriteByte((byte)SpawnParentType.NetworkBehaviour); - headerWriter.WriteNetworkBehaviour(parentNb); - } - } - - //True if pNob is not null, and is spawned. - bool ParentIsSpawned(NetworkObject pNob) - { - bool isNull = (pNob == null); - if (isNull || !pNob.IsSpawned) - { - /* Only log if pNob exist. Otherwise this would print if the user - * was parenting any object, which may not be desirable as they could be - * simply doing it for organization reasons. */ - if (!isNull) - NetworkManager.LogWarning($"Parent {t.name} is not spawned. {nob.name} will not have it's parent sent in the spawn message."); - return false; - } - - return true; - } - - } - //No parent. - else - { - headerWriter.WriteByte((byte)SpawnParentType.Unset); - } - - headerWriter.WriteNetworkObjectId(nob.PrefabId); - } - - //Write headers first. - everyoneWriter.WriteBytes(headerWriter.GetBuffer(), 0, headerWriter.Length); - if (nob.Owner.IsValid) - ownerWriter.WriteBytes(headerWriter.GetBuffer(), 0, headerWriter.Length); - - /* Used to write latest data which must be sent to - * clients, such as SyncTypes and RpcLinks. */ - PooledWriter tempWriter = WriterPool.GetWriter(); - //Send RpcLinks first. - foreach (NetworkBehaviour nb in nob.NetworkBehaviours) - nb.WriteRpcLinks(tempWriter); - //Add to everyone/owner. - everyoneWriter.WriteBytesAndSize(tempWriter.GetBuffer(), 0, tempWriter.Length); - if (nob.Owner.IsValid) - ownerWriter.WriteBytesAndSize(tempWriter.GetBuffer(), 0, tempWriter.Length); - - //Add most recent sync type values. - /* SyncTypes have to be populated for owner and everyone. - * The data may be unique for owner if synctypes are set - * to only go to owner. */ - WriteSyncTypes(everyoneWriter, tempWriter, SyncTypeWriteType.Observers); - //If owner is valid then populate owner writer as well. - if (nob.Owner.IsValid) - WriteSyncTypes(ownerWriter, tempWriter, SyncTypeWriteType.Owner); - - void WriteSyncTypes(Writer finalWriter, PooledWriter tWriter, SyncTypeWriteType writeType) - { - tWriter.Reset(); - foreach (NetworkBehaviour nb in nob.NetworkBehaviours) - nb.WriteSyncTypesForSpawn(tWriter, writeType); - finalWriter.WriteBytesAndSize(tWriter.GetBuffer(), 0, tWriter.Length); - } - - //Dispose of writers created in this method. - headerWriter.Dispose(); - tempWriter.Dispose(); - } - - /// - /// Writes changed transform proeprties to writer. - /// - protected void WriteChangedTransformProperties(NetworkObject nob, bool sceneObject, bool nested, Writer headerWriter) - { - /* Write changed transform properties. */ - ChangedTransformProperties ctp; - //If a scene object then get it from scene properties. - if (sceneObject || nested) - { - ctp = nob.GetTransformChanges(nob.SerializedTransformProperties); - } - else - { - PrefabObjects po = NetworkManager.GetPrefabObjects(nob.SpawnableCollectionId, false); - ctp = nob.GetTransformChanges(po.GetObject(true, nob.PrefabId).gameObject); - } - - headerWriter.WriteByte((byte)ctp); - //If properties have changed. - if (ctp != ChangedTransformProperties.Unset) - { - //Write any changed properties. - if (ChangedTransformPropertiesEnum.Contains(ctp, ChangedTransformProperties.LocalPosition)) - headerWriter.WriteVector3(nob.transform.localPosition); - if (ChangedTransformPropertiesEnum.Contains(ctp, ChangedTransformProperties.LocalRotation)) - headerWriter.WriteQuaternion(nob.transform.localRotation, NetworkManager.ServerManager.SpawnPacking.Rotation); - if (ChangedTransformPropertiesEnum.Contains(ctp, ChangedTransformProperties.LocalScale)) - headerWriter.WriteVector3(nob.transform.localScale); - } - - } - - /// - /// Writes a despawn. - /// - /// - protected void WriteDespawn(NetworkObject nob, DespawnType despawnType, Writer everyoneWriter) - { - everyoneWriter.WritePacketId(PacketId.ObjectDespawn); - everyoneWriter.WriteNetworkObjectForDespawn(nob, despawnType); - } - - /// - /// Gets transform properties by applying passed in values if they are not null, otherwise using transforms defaults. - /// - internal void GetTransformProperties(Vector3? readPos, Quaternion? readRot, Vector3? readScale, Transform defaultTransform, out Vector3 pos, out Quaternion rot, out Vector3 scale) - { - pos = (readPos == null) ? defaultTransform.localPosition : readPos.Value; - rot = (readRot == null) ? defaultTransform.localRotation : readRot.Value; - scale = (readScale == null) ? defaultTransform.localScale : readScale.Value; - } - - /// - /// Finds a scene NetworkObject and sets transform values. - /// - internal NetworkObject GetSceneNetworkObject(ulong sceneId) - { - NetworkObject nob; - SceneObjects.TryGetValueIL2CPP(sceneId, out nob); - //If found in scene objects. - if (nob == null) - NetworkManager.LogError($"SceneId of {sceneId} not found in SceneObjects. This may occur if your scene differs between client and server, if client does not have the scene loaded, or if networked scene objects do not have a SceneCondition. See ObserverManager in the documentation for more on conditions."); - - return nob; - } - - /// - /// Returns if a NetworkObject meets basic criteria for being predicted spawned. - /// - /// If not null reader will be cleared on error. - /// - protected bool CanPredictedSpawn(NetworkObject nob, NetworkConnection spawner, NetworkConnection owner, bool asServer, Reader reader = null) - { - //Does not allow predicted spawning. - if (!nob.AllowPredictedSpawning) - { - if (asServer) - spawner.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"Connection {spawner.ClientId} tried to spawn an object {nob.name} which does not support predicted spawning."); - else - NetworkManager.LogError($"Object {nob.name} does not support predicted spawning. Modify the NetworkObject component settings to allow predicted spawning."); - - reader?.Clear(); - return false; - } - //Parenting is not yet supported. - if (nob.transform.parent != null) - { - if (asServer) - spawner.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"Connection {spawner.ClientId} tried to spawn an object that is not root."); - else - NetworkManager.LogError($"Predicted spawning as a child is not supported."); - - reader?.Clear(); - return false; - } - //Nested nobs not yet supported. - if (nob.ChildNetworkObjects.Count > 0) - { - if (asServer) - spawner.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"Connection {spawner.ClientId} tried to spawn an object {nob.name} which has nested NetworkObjects."); - else - NetworkManager.LogError($"Predicted spawning prefabs which contain nested NetworkObjects is not yet supported but will be in a later release."); - - reader?.Clear(); - return false; - } - //Blocked by PredictedSpawn settings or user logic. - if ((asServer && !nob.PredictedSpawn.OnTrySpawnServer(spawner, owner)) - || (!asServer && !nob.PredictedSpawn.OnTrySpawnClient())) - { - reader?.Clear(); - return false; - } - - return true; - } - - /// - /// Returns if a NetworkObject meets basic criteria for being predicted despawned. - /// - /// If not null reader will be cleared on error. - /// - protected bool CanPredictedDespawn(NetworkObject nob, NetworkConnection despawner, bool asServer, Reader reader = null) - { - //Does not allow predicted spawning. - if (!nob.AllowPredictedDespawning) - { - if (asServer) - despawner.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"Connection {despawner.ClientId} tried to despawn an object {nob.name} which does not support predicted despawning."); - else - NetworkManager.LogError($"Object {nob.name} does not support predicted despawning. Modify the PredictedSpawn component settings to allow predicted despawning."); - - reader?.Clear(); - return false; - } - //Parenting is not yet supported. - if (nob.transform.parent != null) - { - if (asServer) - despawner.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"Connection {despawner.ClientId} tried to despawn an object that is not root."); - else - NetworkManager.LogError($"Predicted despawning as a child is not supported."); - - reader?.Clear(); - return false; - } - //Nested nobs not yet supported. - if (nob.ChildNetworkObjects.Count > 0) - { - if (asServer) - despawner.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"Connection {despawner.ClientId} tried to despawn an object {nob.name} which has nested NetworkObjects."); - else - NetworkManager.LogError($"Predicted despawning prefabs which contain nested NetworkObjects is not yet supported but will be in a later release."); - - reader?.Clear(); - return false; - } - //Blocked by PredictedSpawn settings or user logic. - if ( - (asServer && !nob.PredictedSpawn.OnTryDepawnServer(despawner)) - || (!asServer && !nob.PredictedSpawn.OnTryDespawnClient()) - ) - { - reader?.Clear(); - return false; - } - - return true; - } - - - - - - } -} - diff --git a/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.Spawning.cs.meta b/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.Spawning.cs.meta deleted file mode 100644 index bb07e79..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.Spawning.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1fcb759226359ad48926ff17cbf0ec6d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.cs b/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.cs deleted file mode 100644 index b32e15f..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.cs +++ /dev/null @@ -1,414 +0,0 @@ -using FishNet.Component.Observing; -using FishNet.Connection; -using FishNet.Managing.Logging; -using FishNet.Object; -using FishNet.Serializing; -using FishNet.Transporting; -using FishNet.Utility.Extension; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; -using UnityEngine.SceneManagement; - -namespace FishNet.Managing.Object -{ - public abstract partial class ManagedObjects - { - #region Public. - /// - /// NetworkObjects which are currently active. - /// - public Dictionary Spawned = new Dictionary(); - /// - /// NetworkObjects which are currently active on the local client. - /// //TODO Move this to ClientObjects. - /// - internal List LocalClientSpawned = new List(); - #endregion - - #region Protected. - /// - /// Returns the next ObjectId to use. - /// - protected internal virtual int GetNextNetworkObjectId(bool errorCheck = true) => NetworkObject.UNSET_OBJECTID_VALUE; - /// - /// NetworkManager handling this. - /// - protected NetworkManager NetworkManager { get; private set; } - /// - /// Objects in currently loaded scenes. These objects can be active or inactive. - /// Key is the objectId while value is the object. Key is not the same as NetworkObject.ObjectId. - /// - protected Dictionary SceneObjects = new Dictionary(); - #endregion - - protected void Initialize(NetworkManager manager) - { - NetworkManager = manager; - } - - /// - /// Subscribes to SceneManager.SceneLoaded event. - /// - /// - internal void SubscribeToSceneLoaded(bool subscribe) - { - if (subscribe) - SceneManager.sceneLoaded += SceneManager_sceneLoaded; - else - SceneManager.sceneLoaded -= SceneManager_sceneLoaded; - } - - /// - /// Called when a scene is loaded. - /// - /// - /// - protected internal virtual void SceneManager_sceneLoaded(Scene s, LoadSceneMode arg1) { } - - /// - /// Called when a NetworkObject runs Deactivate. - /// - /// - internal virtual void NetworkObjectUnexpectedlyDestroyed(NetworkObject nob, bool asServer) - { - if (nob == null) - return; - - RemoveFromSpawned(nob, true, asServer); - } - - /// - /// Removes a NetworkedObject from spawned. - /// - private void RemoveFromSpawned(NetworkObject nob, bool unexpectedlyDestroyed, bool asServer) - { - Spawned.Remove(nob.ObjectId); - if (!asServer) - LocalClientSpawned.Remove(nob); - //Do the same with SceneObjects. - if (unexpectedlyDestroyed && nob.IsSceneObject) - RemoveFromSceneObjects(nob); - } - - /// - /// Despawns a NetworkObject. - /// - internal virtual void Despawn(NetworkObject nob, DespawnType despawnType, bool asServer) - { - if (nob == null) - { - NetworkManager.LogWarning($"Cannot despawn a null NetworkObject."); - return; - } - - //True if should be destroyed, false if deactivated. - bool destroy = false; - /* Only modify object state if asServer, - * or !asServer and not host. This is so clients, when acting as - * host, don't destroy objects they lost observation of. */ - - /* Nested prefabs can never be destroyed. Only check to - * destroy if not nested. By nested prefab, this means the object - * despawning is part of another prefab that is also a spawned - * network object. */ - if (!nob.IsNested) - { - //If as server. - if (asServer) - { - //Scene object. - if (!nob.IsSceneObject) - { - /* If client-host has visibility - * then disable and wait for client-host to get destroy - * message. Otherwise destroy immediately. */ - if (nob.Observers.Contains(NetworkManager.ClientManager.Connection)) - NetworkManager.ServerManager.Objects.AddToPending(nob); - else - destroy = true; - } - } - //Not as server. - else - { - bool isServer = NetworkManager.IsServer; - //Only check to destroy if not a scene object. - if (!nob.IsSceneObject) - { - /* If was removed from pending then also destroy. - * Pending objects are ones that exist on the server - * side only to await destruction from client side. - * Objects can also be destroyed if server is not - * active. */ - destroy = (!isServer || NetworkManager.ServerManager.Objects.RemoveFromPending(nob.ObjectId)); - } - } - } - - //Deinitialize to invoke callbacks. - nob.Deinitialize(asServer); - //Remove from match condition only if server. - if (asServer) - MatchCondition.RemoveFromMatchWithoutRebuild(nob, NetworkManager); - RemoveFromSpawned(nob, false, asServer); - - //If to destroy. - if (destroy) - { - if (despawnType == DespawnType.Destroy) - MonoBehaviour.Destroy(nob.gameObject); - else - NetworkManager.StorePooledInstantiated(nob, asServer); - } - /* If to potentially disable instead of destroy. - * This is such as something is despawning server side - * but a clientHost is present, or if a scene object. */ - else - { - //If as server. - if (asServer) - { - //If not clientHost then the object can be disabled. - if (!NetworkManager.IsClient) - nob.gameObject.SetActive(false); - } - //Not as server. - else - { - //If the server is not active then the object can be disabled. - if (!NetworkManager.IsServer) - { - nob.gameObject.SetActive(false); - } - //If also server then checks must be done. - else - { - /* Object is still spawned on the server side. This means - * the clientHost likely lost visibility. When this is the case - * update clientHost renderers. */ - if (NetworkManager.ServerManager.Objects.Spawned.ContainsKey(nob.ObjectId)) - nob.SetRenderersVisible(false); - /* No longer spawned on the server, can - * deactivate on the client. */ - else - nob.gameObject.SetActive(false); - } - } - - /* Also despawn child objects. - * This only must be done when not destroying - * as destroying would result in the despawn being - * forced. - * - * Only run if asServer as well. The server will send - * individual despawns for each child. */ - if (asServer) - { - foreach (NetworkObject childNob in nob.ChildNetworkObjects) - { - if (childNob != null && !childNob.IsDeinitializing) - Despawn(childNob, despawnType, asServer); - } - } - } - - } - - - /// - /// Updates NetworkBehaviours on nob. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void UpdateNetworkBehavioursForSceneObject(NetworkObject nob, bool asServer) - { - //Would have already been done on server side. - if (!asServer && NetworkManager.IsServer) - return; - - InitializePrefab(nob, -1); - } - - /// - /// Initializes a prefab, not to be mistaken for initializing a spawned object. - /// - /// Prefab to initialize. - /// Index within spawnable prefabs. - public static void InitializePrefab(NetworkObject prefab, int index, ushort? collectionId = null) - { - if (prefab == null) - return; - /* Only set the Id if not -1. - * A value of -1 would indicate it's a scene - * object. */ - if (index != -1) - { - //Use +1 because 0 indicates unset. - prefab.PrefabId = (ushort)index; - if (collectionId != null) - prefab.SpawnableCollectionId = collectionId.Value; - } - - byte componentIndex = 0; - prefab.UpdateNetworkBehaviours(null, ref componentIndex); - } - - /// - /// Despawns Spawned NetworkObjects. Scene objects will be disabled, others will be destroyed. - /// - internal virtual void DespawnWithoutSynchronization(bool asServer) - { - foreach (NetworkObject nob in Spawned.Values) - DespawnWithoutSynchronization(nob, asServer, nob.GetDefaultDespawnType(), false); - - Spawned.Clear(); - } - - /// - /// Despawns a network object. - /// - /// - internal virtual void DespawnWithoutSynchronization(NetworkObject nob, bool asServer, DespawnType despawnType, bool removeFromSpawned) - { - //Null can occur when running as host and server already despawns such as when stopping. - if (nob == null) - return; - - nob.Deinitialize(asServer); - /* Only run if asServer, or not - * asServer and server isn't running. This - * prevents objects from affecting the server - * as host when being modified client side. */ - if (asServer || (!asServer && !NetworkManager.IsServer)) - { - if (removeFromSpawned) - RemoveFromSpawned(nob, false, asServer); - if (nob.IsSceneObject) - { - nob.gameObject.SetActive(false); - } - else - { - if (despawnType == DespawnType.Destroy) - MonoBehaviour.Destroy(nob.gameObject); - else - NetworkManager.StorePooledInstantiated(nob, asServer); - } - } - } - - /// - /// Adds a NetworkObject to Spawned. - /// - /// - internal void AddToSpawned(NetworkObject nob, bool asServer) - { - Spawned[nob.ObjectId] = nob; - if (!asServer) - { - LocalClientSpawned.Add(nob); - //If being added as client and is also server. - if (NetworkManager.IsServer) - nob.SetRenderersVisible(true); - } - } - - /// - /// Adds a NetworkObject to SceneObjects. - /// - /// - protected internal void AddToSceneObjects(NetworkObject nob) - { - SceneObjects[nob.SceneId] = nob; - } - - /// - /// Removes a NetworkObject from SceneObjects. - /// - /// - protected internal void RemoveFromSceneObjects(NetworkObject nob) - { - SceneObjects.Remove(nob.SceneId); - } - - /// - /// Removes a NetworkObject from SceneObjects. - /// - /// - protected internal void RemoveFromSceneObjects(ulong sceneId) - { - SceneObjects.Remove(sceneId); - } - - /// - /// Finds a NetworkObject within Spawned. - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected internal NetworkObject GetSpawnedNetworkObject(int objectId) - { - NetworkObject r; - if (!Spawned.TryGetValueIL2CPP(objectId, out r)) - NetworkManager.LogError($"Spawned NetworkObject not found for ObjectId {objectId}."); - - return r; - } - - /// - /// Tries to skip data length for a packet. - /// - /// - /// - /// - protected internal void SkipDataLength(ushort packetId, PooledReader reader, int dataLength, int rpcLinkObjectId = -1) - { - /* -1 means length wasn't set, which would suggest a reliable packet. - * Object should never be missing for reliable packets since spawns - * and despawns are reliable in order. */ - if (dataLength == (int)MissingObjectPacketLength.Reliable) - { - string msg; - bool isRpcLink = (packetId >= NetworkManager.StartingRpcLinkIndex); - if (isRpcLink) - { - msg = (rpcLinkObjectId == -1) ? - $"RPCLink of Id {(PacketId)packetId} could not be found. Remaining data will be purged." : - $"ObjectId {rpcLinkObjectId} for RPCLink {(PacketId)packetId} could not be found."; - } - else - { - msg = $"NetworkBehaviour could not be found for packetId {(PacketId)packetId}. Remaining data will be purged."; - } - - /* Default logging for server is errors only. Use error on client and warning - * on servers to reduce chances of allocation attacks. */ -#if DEVELOPMENT_BUILD || UNITY_EDITOR || !UNITY_SERVER - NetworkManager.LogError(msg); -#else - if (NetworkManager.CanLog(LoggingType.Warning)) - Debug.LogWarning(msg); -#endif - reader.Clear(); - } - /* If length is known then is unreliable packet. It's possible - * this packetId arrived before or after the object was spawned/destroyed. - * Skip past the data for this packet and use rest in reader. With non-linked - * RPCs length is sent before object information. */ - else if (dataLength >= 0) - { - reader.Skip(Math.Min(dataLength, reader.Remaining)); - } - /* -2 indicates the length is very long. Don't even try saving - * the packet, user shouldn't be sending this much data over unreliable. */ - else if (dataLength == (int)MissingObjectPacketLength.PurgeRemaiming) - { - reader.Clear(); - } - } - - } - -} diff --git a/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.cs.meta b/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.cs.meta deleted file mode 100644 index 345e662..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/ManagedObjects.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e1363007244792145846afddc31ac12c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Object/ObjectSpawnType.cs b/Assets/FishNet/Runtime/Managing/Object/ObjectSpawnType.cs deleted file mode 100644 index 04e590f..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/ObjectSpawnType.cs +++ /dev/null @@ -1,31 +0,0 @@ -using FishNet.Documenting; - -namespace FishNet.Managing.Object -{ - internal enum SpawnType : byte - { - Unset = 0, - Nested = 1, - Scene = 2, - Instantiated = 4, - InstantiatedGlobal = 8, - } - - [APIExclude] - internal static partial class SpawnTypeEnum - { - /// - /// Returns if whole contains part. - /// - /// - /// - /// - public static bool Contains(SpawnType whole, SpawnType part) - { - return (whole & part) == part; - } - } - - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Object/ObjectSpawnType.cs.meta b/Assets/FishNet/Runtime/Managing/Object/ObjectSpawnType.cs.meta deleted file mode 100644 index 39d74c8..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/ObjectSpawnType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ed15edf5a1a100d45b05f6adace574cd -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects.meta b/Assets/FishNet/Runtime/Managing/Object/PrefabObjects.meta deleted file mode 100644 index d227d92..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 681483aaaf105014b93c3c89c7f43fda -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DefaultPrefabObjects.cs b/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DefaultPrefabObjects.cs deleted file mode 100644 index 08df7b4..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DefaultPrefabObjects.cs +++ /dev/null @@ -1,104 +0,0 @@ -using FishNet.Documenting; -using FishNet.Object.Helping; -using System.Collections.Generic; -using UnityEngine; -#if UNITY_EDITOR -using FishNet.Editing; -using UnityEditor; -#endif -using FishNet.Object; - -namespace FishNet.Managing.Object -{ - - [APIExclude] - //[CreateAssetMenu(fileName = "New DefaultPrefabObjects", menuName = "FishNet/Spawnable Prefabs/Default Prefab Objects")] - public class DefaultPrefabObjects : SinglePrefabObjects - { - /// - /// Sets asset path hashes for prefabs starting at index, or if missing. - /// Returns true if one or more NetworkObjects were updated. - internal bool SetAssetPathHashes(int index) - { -#if UNITY_EDITOR - bool dirtied = false; - int count = base.GetObjectCount(); - - if (count == 0) - return false; - if (index < 0 || index >= count) - { - Debug.LogError($"Index {index} is out of range when trying to set asset path hashes. Collection length is {count}. Defaulf prefabs may need to be rebuilt."); - return false; - } - - for (int i = 0; i < count; i++) - { - NetworkObject n = base.Prefabs[i]; - if (i < index) - continue; - - string pathAndName = $"{AssetDatabase.GetAssetPath(n.gameObject)}{n.gameObject.name}"; - ulong hashcode = Hashing.GetStableHash64(pathAndName); - //Already set. - if (n.AssetPathHash == hashcode) - continue; - - n.SetAssetPathHash(hashcode); - EditorUtility.SetDirty(n); - dirtied = true; - } - - return dirtied; -#else - return false; -#endif - } - - /// - /// Sorts prefabs by name and path hashcode. - /// - internal void Sort() - { - if (base.GetObjectCount() == 0) - return; - - Dictionary hashcodesAndNobs = new Dictionary(); - List hashcodes = new List(); - - bool error = false; - foreach (NetworkObject n in base.Prefabs) - { - hashcodes.Add(n.AssetPathHash); - //If hashcode is 0 something is wrong - if (n.AssetPathHash == 0) - { - error = true; - Debug.LogError($"AssetPathHash is not set for GameObject {n.name}."); - - } - hashcodesAndNobs.Add(n.AssetPathHash, n); - } - //An error occured, no reason to continue. - if (error) - { - Debug.LogError($"One or more NetworkObject prefabs did not have their AssetPathHash set. This usually occurs when a prefab cannot be saved. Check the specified prefabs for missing scripts or serialization errors and correct them, then use Fish-Networking -> Refresh Default Prefabs."); - return; - } - - //Once all hashes have been made re-add them to prefabs sorted. - hashcodes.Sort(); - //Build to a new list using sorted hashcodes. - List sortedNobs = new List(); - foreach (ulong hc in hashcodes) - sortedNobs.Add(hashcodesAndNobs[hc]); - - base.Clear(); - base.AddObjects(sortedNobs, false); - } - - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DefaultPrefabObjects.cs.meta b/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DefaultPrefabObjects.cs.meta deleted file mode 100644 index 1258c30..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DefaultPrefabObjects.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3ad70174b079c2f4ebc7931d3dd1af6f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DualPrefabObjects.cs b/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DualPrefabObjects.cs deleted file mode 100644 index 45aff7c..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DualPrefabObjects.cs +++ /dev/null @@ -1,136 +0,0 @@ -using FishNet.Documenting; -using FishNet.Object; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Managing.Object -{ - - //document - [APIExclude] - [CreateAssetMenu(fileName = "New DualPrefabObjects", menuName = "FishNet/Spawnable Prefabs/Dual Prefab Objects")] - public class DualPrefabObjects : PrefabObjects - { - /// - /// - /// - [Tooltip("Prefabs which may be spawned.")] - [SerializeField] - private List _prefabs = new List(); - /// - /// Prefabs which may be spawned. - /// - public IReadOnlyCollection Prefabs => _prefabs; - - public override void Clear() - { - _prefabs.Clear(); - } - public override int GetObjectCount() - { - return _prefabs.Count; - } - - public override NetworkObject GetObject(bool asServer, int id) - { - if (id < 0 || id >= _prefabs.Count) - { - NetworkManager.StaticLogError($"PrefabId {id} is out of range."); - return null; - } - else - { - DualPrefab dp = _prefabs[id]; - NetworkObject nob = (asServer) ? dp.Server : dp.Client; - if (nob == null) - { - string lookupSide = (asServer) ? "server" : "client"; - NetworkManager.StaticLogError($"Prefab for {lookupSide} on id {id} is null "); - } - - return nob; - } - } - - public override void RemoveNull() - { - for (int i = 0; i < _prefabs.Count; i++) - { - if (_prefabs[i].Server == null || _prefabs[i].Client == null) - { - _prefabs.RemoveAt(i); - i--; - } - } - - if (Application.isPlaying) - InitializePrefabRange(0); - } - - public override void AddObject(DualPrefab dualPrefab, bool checkForDuplicates = false) - { - AddObjects(new DualPrefab[] { dualPrefab }, checkForDuplicates); - } - - public override void AddObjects(List dualPrefabs, bool checkForDuplicates = false) - { - AddObjects(dualPrefabs.ToArray(), checkForDuplicates); - } - - public override void AddObjects(DualPrefab[] dualPrefabs, bool checkForDuplicates = false) - { - if (!checkForDuplicates) - { - _prefabs.AddRange(dualPrefabs); - } - else - { - foreach (DualPrefab dp in dualPrefabs) - AddUniqueNetworkObjects(dp); - } - - if (Application.isPlaying) - InitializePrefabRange(0); - } - - private void AddUniqueNetworkObjects(DualPrefab dp) - { - for (int i = 0; i < _prefabs.Count; i++) - { - if (_prefabs[i].Server == dp.Server && _prefabs[i].Client == dp.Client) - return; - } - - _prefabs.Add(dp); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void InitializePrefabRange(int startIndex) - { - for (int i = startIndex; i < _prefabs.Count; i++) - { - ManagedObjects.InitializePrefab(_prefabs[i].Server, i, CollectionId); - ManagedObjects.InitializePrefab(_prefabs[i].Client, i, CollectionId); - } - } - - - #region Unused. - public override void AddObject(NetworkObject networkObject, bool checkForDuplicates = false) - { - NetworkManager.StaticLogError($"Single prefabs are not supported with DualPrefabObjects. Make a SinglePrefabObjects asset instead."); - } - - public override void AddObjects(List networkObjects, bool checkForDuplicates = false) - { - NetworkManager.StaticLogError($"Single prefabs are not supported with DualPrefabObjects. Make a SinglePrefabObjects asset instead."); - } - - public override void AddObjects(NetworkObject[] networkObjects, bool checkForDuplicates = false) - { - NetworkManager.StaticLogError($"Single prefabs are not supported with DualPrefabObjects. Make a SinglePrefabObjects asset instead."); - } - #endregion - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DualPrefabObjects.cs.meta b/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DualPrefabObjects.cs.meta deleted file mode 100644 index 4acd585..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/DualPrefabObjects.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e4b890523e001c74a9a2bf0d6340e5f7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/PrefabObjects.cs b/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/PrefabObjects.cs deleted file mode 100644 index cb4133a..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/PrefabObjects.cs +++ /dev/null @@ -1,36 +0,0 @@ -using FishNet.Documenting; -using FishNet.Object; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.Managing.Object -{ - //document - [APIExclude] - public abstract class PrefabObjects : ScriptableObject - { - /// - /// CollectionId for this PrefabObjects. - /// - public ushort CollectionId { get; private set; } - /// - /// Sets CollectionIdValue. - /// - internal void SetCollectionId(ushort id) => CollectionId = id; - - public abstract void Clear(); - public abstract int GetObjectCount(); - public abstract NetworkObject GetObject(bool asServer, int id); - public abstract void RemoveNull(); - public abstract void AddObject(NetworkObject networkObject, bool checkForDuplicates = false); - public abstract void AddObjects(List networkObjects, bool checkForDuplicates = false); - public abstract void AddObjects(NetworkObject[] networkObjects, bool checkForDuplicates = false); - public abstract void AddObject(DualPrefab dualPrefab, bool checkForDuplicates = false); - public abstract void AddObjects(List dualPrefab, bool checkForDuplicates = false); - public abstract void AddObjects(DualPrefab[] dualPrefab, bool checkForDuplicates = false); - public abstract void InitializePrefabRange(int startIndex); - - - - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/PrefabObjects.cs.meta b/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/PrefabObjects.cs.meta deleted file mode 100644 index 4b4ef77..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/PrefabObjects.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c5a7beb0d6ee75a4fb1f058eb3e2640a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/SinglePrefabObjects.cs b/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/SinglePrefabObjects.cs deleted file mode 100644 index d3e06af..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/SinglePrefabObjects.cs +++ /dev/null @@ -1,128 +0,0 @@ -using FishNet.Documenting; -using FishNet.Object; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Managing.Object -{ - //document - [APIExclude] - [CreateAssetMenu(fileName = "New SinglePrefabObjects", menuName = "FishNet/Spawnable Prefabs/Single Prefab Objects")] - public class SinglePrefabObjects : PrefabObjects - { - /// - /// - /// - [Tooltip("Prefabs which may be spawned.")] - [SerializeField] - private List _prefabs = new List(); - /// - /// Prefabs which may be spawned. - /// - public IReadOnlyList Prefabs => _prefabs; - - public override void Clear() - { - _prefabs.Clear(); - } - public override int GetObjectCount() - { - return _prefabs.Count; - } - public override NetworkObject GetObject(bool asServer, int id) - { - if (id < 0 || id >= _prefabs.Count) - { - NetworkManager.StaticLogError($"PrefabId {id} is out of range."); - return null; - } - else - { - NetworkObject nob = _prefabs[id]; - if (nob == null) - NetworkManager.StaticLogError($"Prefab on id {id} is null."); - - return nob; - } - } - - public override void RemoveNull() - { - for (int i = 0; i < _prefabs.Count; i++) - { - if (_prefabs[i] == null) - { - _prefabs.RemoveAt(i); - i--; - } - } - - if (Application.isPlaying) - InitializePrefabRange(0); - } - - public override void AddObject(NetworkObject networkObject, bool checkForDuplicates = false) - { - if (!checkForDuplicates) - _prefabs.Add(networkObject); - else - AddUniqueNetworkObject(networkObject); - - if (Application.isPlaying) - InitializePrefabRange(0); - } - - public override void AddObjects(List networkObjects, bool checkForDuplicates = false) - { - if (!checkForDuplicates) - { - _prefabs.AddRange(networkObjects); - } - else - { - foreach (NetworkObject nob in networkObjects) - AddUniqueNetworkObject(nob); - } - - if (Application.isPlaying) - InitializePrefabRange(0); - } - public override void AddObjects(NetworkObject[] networkObjects, bool checkForDuplicates = false) - { - AddObjects(networkObjects.ToList(), checkForDuplicates); - } - - private void AddUniqueNetworkObject(NetworkObject nob) - { - if (!_prefabs.Contains(nob)) - _prefabs.Add(nob); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void InitializePrefabRange(int startIndex) - { - for (int i = startIndex; i < _prefabs.Count; i++) - ManagedObjects.InitializePrefab(_prefabs[i], i, CollectionId); - } - - - #region Unused. - public override void AddObject(DualPrefab dualPrefab, bool checkForDuplicates = false) - { - NetworkManager.StaticLogError($"Dual prefabs are not supported with SinglePrefabObjects. Make a DualPrefabObjects asset instead."); - } - - public override void AddObjects(List dualPrefab, bool checkForDuplicates = false) - { - NetworkManager.StaticLogError($"Dual prefabs are not supported with SinglePrefabObjects. Make a DualPrefabObjects asset instead."); - } - - public override void AddObjects(DualPrefab[] dualPrefab, bool checkForDuplicates = false) - { - NetworkManager.StaticLogError($"Dual prefabs are not supported with SinglePrefabObjects. Make a DualPrefabObjects asset instead."); - } - #endregion - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/SinglePrefabObjects.cs.meta b/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/SinglePrefabObjects.cs.meta deleted file mode 100644 index 0cf790b..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/PrefabObjects/SinglePrefabObjects.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4489d77032a81ef42b0067acf2737d4d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Object/SpawnParentType.cs b/Assets/FishNet/Runtime/Managing/Object/SpawnParentType.cs deleted file mode 100644 index ff3a421..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/SpawnParentType.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace FishNet.Managing.Object -{ - public enum SpawnParentType : byte - { - Unset = 0, - NetworkObject = 1, - NetworkBehaviour = 2 - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Object/SpawnParentType.cs.meta b/Assets/FishNet/Runtime/Managing/Object/SpawnParentType.cs.meta deleted file mode 100644 index d346b30..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/SpawnParentType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: cbace351ced9ff94eb294dbb2e1d6a75 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Object/SpawnWriter.cs b/Assets/FishNet/Runtime/Managing/Object/SpawnWriter.cs deleted file mode 100644 index 2111ff4..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/SpawnWriter.cs +++ /dev/null @@ -1 +0,0 @@ -//Remove on 2023/06/01 \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Object/SpawnWriter.cs.meta b/Assets/FishNet/Runtime/Managing/Object/SpawnWriter.cs.meta deleted file mode 100644 index a3d8138..0000000 --- a/Assets/FishNet/Runtime/Managing/Object/SpawnWriter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fd305e51107fc3441a6f52636c27298f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Observing.meta b/Assets/FishNet/Runtime/Managing/Observing.meta deleted file mode 100644 index db0e55f..0000000 --- a/Assets/FishNet/Runtime/Managing/Observing.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 9c466e864bb3b114ab6e933d624f9934 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Observing/Editor.meta b/Assets/FishNet/Runtime/Managing/Observing/Editor.meta deleted file mode 100644 index 35d4018..0000000 --- a/Assets/FishNet/Runtime/Managing/Observing/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: b070cdff750cb4542bf0770a57f9936a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Observing/Editor/ObserverManagerEditor.cs b/Assets/FishNet/Runtime/Managing/Observing/Editor/ObserverManagerEditor.cs deleted file mode 100644 index bd6aeb9..0000000 --- a/Assets/FishNet/Runtime/Managing/Observing/Editor/ObserverManagerEditor.cs +++ /dev/null @@ -1,53 +0,0 @@ -#if UNITY_EDITOR -using UnityEditor; -using UnityEngine; - -namespace FishNet.Managing.Observing.Editing -{ - - - [CustomEditor(typeof(ObserverManager), true)] - [CanEditMultipleObjects] - public class ObserverManagerEditor : Editor - { - private SerializedProperty _useNetworkLod; - private SerializedProperty _levelOfDetailDistances; - private SerializedProperty _updateHostVisibility; - private SerializedProperty _defaultConditions; - - protected virtual void OnEnable() - { - _useNetworkLod = serializedObject.FindProperty(nameof(_useNetworkLod)); - _levelOfDetailDistances = serializedObject.FindProperty(nameof(_levelOfDetailDistances)); - _updateHostVisibility = serializedObject.FindProperty(nameof(_updateHostVisibility)); - _defaultConditions = serializedObject.FindProperty(nameof(_defaultConditions)); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - GUI.enabled = false; - EditorGUILayout.ObjectField("Script:", MonoScript.FromMonoBehaviour((ObserverManager)target), typeof(ObserverManager), false); - GUI.enabled = true; - - - EditorGUILayout.PropertyField(_useNetworkLod); - if (_useNetworkLod.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_levelOfDetailDistances); - EditorGUI.indentLevel--; - } - - EditorGUILayout.PropertyField(_updateHostVisibility); - EditorGUILayout.PropertyField(_defaultConditions); - - EditorGUILayout.Space(); - - serializedObject.ApplyModifiedProperties(); - } - - } -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Observing/Editor/ObserverManagerEditor.cs.meta b/Assets/FishNet/Runtime/Managing/Observing/Editor/ObserverManagerEditor.cs.meta deleted file mode 100644 index 3076866..0000000 --- a/Assets/FishNet/Runtime/Managing/Observing/Editor/ObserverManagerEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 86e21ffc228c07d4891b6e74080b8c90 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Observing/ObserverManager.cs b/Assets/FishNet/Runtime/Managing/Observing/ObserverManager.cs deleted file mode 100644 index 9970054..0000000 --- a/Assets/FishNet/Runtime/Managing/Observing/ObserverManager.cs +++ /dev/null @@ -1,324 +0,0 @@ -using FishNet.Connection; //remove on 2023/01/01 move to correct folder. -using FishNet.Object; -using FishNet.Observing; -using FishNet.Utility.Constant; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; -using UnityEngine.Serialization; - -[assembly: InternalsVisibleTo(UtilityConstants.DEMOS_ASSEMBLY_NAME)] -namespace FishNet.Managing.Observing -{ - /// - /// Additional options for managing the observer system. - /// - [DisallowMultipleComponent] - [AddComponentMenu("FishNet/Manager/ObserverManager")] - public sealed class ObserverManager : MonoBehaviour - { - #region Internal. - /// - /// Current index to use for level of detail based on tick. - /// - internal byte LevelOfDetailIndex { get; private set; } - #endregion - - #region Serialized. - /// - /// - /// - [Tooltip("True to use the NetworkLOD system.")] - [SerializeField] - private bool _useNetworkLod; - /// - /// True to use the NetworkLOD system. - /// - /// - internal bool GetUseNetworkLod() => _useNetworkLod; - /// - /// Distance for each level of detal. - /// - internal List GetLevelOfDetailDistances() => (_useNetworkLod) ? _levelOfDetailDistances : _singleLevelOfDetailDistances; - [Tooltip("Distance for each level of detal.")] - [SerializeField] - private List _levelOfDetailDistances = new List(); - /// - /// Returned when network LOD is off. Value contained is one level of detail with max distance. - /// - private List _singleLevelOfDetailDistances = new List() { float.MaxValue }; - /// - /// - /// - [Tooltip("True to update visibility for clientHost based on if they are an observer or not.")] - [FormerlySerializedAs("_setHostVisibility")] - [SerializeField] - private bool _updateHostVisibility = true; - /// - /// True to update visibility for clientHost based on if they are an observer or not. - /// - public bool UpdateHostVisibility - { - get => _updateHostVisibility; - private set => _updateHostVisibility = value; - } - /// - /// - /// - [Tooltip("Default observer conditions for networked objects.")] - [SerializeField] - private List _defaultConditions = new List(); - #endregion - - #region Private. - /// - /// NetworkManager on object. - /// - private NetworkManager _networkManager; - /// - /// Intervals for each level of detail. - /// - private uint[] _levelOfDetailIntervals; - #endregion - - private void Awake() - { - if (_useNetworkLod && _levelOfDetailDistances.Count > 1) - { - Debug.LogWarning("Network Level of Detail has been disabled while bugs are resolved in relation to this feature. You do not need to make any changes to your project. This warning will be removed once all issues are resolved."); - _useNetworkLod = false; - } - } - - /// - /// Initializes this script for use. - /// - /// - internal void InitializeOnce_Internal(NetworkManager manager) - { - _networkManager = manager; - ValidateLevelOfDetails(); - } - - /// - /// Sets a new value for UpdateHostVisibility. - /// - /// New value. - /// Which objects to update. - public void SetUpdateHostVisibility(bool value, HostVisibilityUpdateTypes updateType) - { - //Unchanged. - if (value == UpdateHostVisibility) - return; - - /* Update even if server state is not known. - * The setting should be updated so when the server - * does start spawned objects have latest setting. */ - if (HostVisibilityUpdateContains(updateType, HostVisibilityUpdateTypes.Manager)) - UpdateHostVisibility = value; - - /* If to update spawned as well then update all networkobservers - * with the setting and also update renderers. */ - if (_networkManager.IsServer && HostVisibilityUpdateContains(updateType, HostVisibilityUpdateTypes.Spawned)) - { - NetworkConnection clientConn = _networkManager.ClientManager.Connection; - foreach (NetworkObject n in _networkManager.ServerManager.Objects.Spawned.Values) - { - n.NetworkObserver.SetUpdateHostVisibility(value); - - //Only check to update renderers if clientHost. If not client then clientConn won't be active. - if (clientConn.IsActive) - n.SetRenderersVisible(n.Observers.Contains(clientConn), true); - } - } - - bool HostVisibilityUpdateContains(HostVisibilityUpdateTypes whole, HostVisibilityUpdateTypes part) - { - return (whole & part) == part; - } - } - - /// - /// Adds default observer conditions to nob and returns the NetworkObserver used. - /// - internal NetworkObserver AddDefaultConditions(NetworkObject nob) - { - bool isGlobal = (nob.IsGlobal && !nob.IsSceneObject); - bool obsAdded; - - NetworkObserver result; - if (!nob.TryGetComponent(out result)) - { - obsAdded = true; - result = nob.gameObject.AddComponent(); - } - else - { - obsAdded = false; - } - - /* NetworkObserver is null and there are no - * conditions to add. Nothing will change by adding - * the NetworkObserver component so exit early. */ - if (!obsAdded && _defaultConditions.Count == 0) - return result; - - //If the NetworkObserver component was just added. - if (obsAdded) - { - /* Global nobs do not need a NetworkObserver. - * Ultimately, a global NetworkObject is one without - * any conditions. */ - if (isGlobal) - return result; - //If there are no conditions then there's nothing to add. - if (_defaultConditions.Count == 0) - return result; - /* If here then there not a global networkobject and there are conditions to use. - * Since the NetworkObserver is being added fresh, set OverrideType to UseManager - * so that the NetworkObserver is populated with the manager conditions. */ - result.OverrideType = NetworkObserver.ConditionOverrideType.UseManager; - } - //NetworkObject has a NetworkObserver already on it. - else - { - //If global the NetworkObserver has to be cleared and set to ignore manager. - if (isGlobal) - { - result.ObserverConditionsInternal.Clear(); - result.OverrideType = NetworkObserver.ConditionOverrideType.IgnoreManager; - } - } - - //If ignoring manager then use whatever is already configured. - if (result.OverrideType == NetworkObserver.ConditionOverrideType.IgnoreManager) - { - //Do nothing. - } - //If using manager then replace all with conditions. - else if (result.OverrideType == NetworkObserver.ConditionOverrideType.UseManager) - { - result.ObserverConditionsInternal.Clear(); - AddMissing(result); - } - //Adding only new. - else if (result.OverrideType == NetworkObserver.ConditionOverrideType.AddMissing) - { - AddMissing(result); - } - - void AddMissing(NetworkObserver networkObserver) - { - int count = _defaultConditions.Count; - for (int i = 0; i < count; i++) - { - ObserverCondition oc = _defaultConditions[i]; - if (!networkObserver.ObserverConditionsInternal.Contains(oc)) - networkObserver.ObserverConditionsInternal.Add(oc); - } - } - - return result; - } - - /// - /// Gets the tick interval to use for a lod level. - /// - /// - /// - public byte GetLevelOfDetailInterval(byte lodLevel) - { - if (LevelOfDetailIndex == 0) - return 1; - - return (byte)System.Math.Pow(2, lodLevel); - } - - /// - /// Calculates and sets the current level of detail index for the tick. - /// - internal void CalculateLevelOfDetail(uint tick) - { - int count = GetLevelOfDetailDistances().Count; - for (int i = (count - 1); i > 0; i--) - { - uint interval = _levelOfDetailIntervals[i]; - if (tick % interval == 0) - { - LevelOfDetailIndex = (byte)i; - return; - } - } - - //If here then index is 0 and interval is every tick. - LevelOfDetailIndex = 0; - } - - /// - /// Validates that level of detail intervals are proper. - /// - private void ValidateLevelOfDetails() - { - if (!_useNetworkLod) - return; - - //No distances specified. - if (_levelOfDetailDistances == null || _levelOfDetailDistances.Count == 0) - { - if (_networkManager != null) - { - _networkManager.LogWarning("Level of detail distances contains no entries. NetworkLOD has been disabled."); - _useNetworkLod = false; - } - return; - } - - //Make sure every distance is larger than the last. - float lastDistance = float.MinValue; - foreach (float dist in _levelOfDetailDistances) - { - if (dist <= 0f || dist <= lastDistance) - { - if (_networkManager != null) - { - _networkManager.LogError($"Level of detail distances must be greater than 0f, and each distance larger than the previous. NetworkLOD has been disabled."); - _useNetworkLod = false; - } - return; - } - lastDistance = dist; - } - - int maxEntries = 8; - //Too many distances. - if (_levelOfDetailDistances.Count > maxEntries) - { - _networkManager?.LogWarning("There can be a maximum of 8 level of detail distances. Entries beyond this quantity have been discarded."); - while (_levelOfDetailDistances.Count > maxEntries) - _levelOfDetailDistances.RemoveAt(_levelOfDetailDistances.Count - 1); - } - - if (Application.isPlaying) - { - //Build intervals and sqr distances. - int count = _levelOfDetailDistances.Count; - _levelOfDetailIntervals = new uint[count]; - for (int i = (count - 1); i > 0; i--) - { - uint power = (uint)Mathf.Pow(2, i); - _levelOfDetailIntervals[i] = power; - - } - //Sqr - for (int i = 0; i < count; i++) - { - float dist = _levelOfDetailDistances[i]; - dist *= dist; - _levelOfDetailDistances[i] = dist; - } - } - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Observing/ObserverManager.cs.meta b/Assets/FishNet/Runtime/Managing/Observing/ObserverManager.cs.meta deleted file mode 100644 index ed04656..0000000 --- a/Assets/FishNet/Runtime/Managing/Observing/ObserverManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7d331f979d46e8e4a9fc90070c596d44 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Prediction.meta b/Assets/FishNet/Runtime/Managing/Prediction.meta deleted file mode 100644 index bdb3631..0000000 --- a/Assets/FishNet/Runtime/Managing/Prediction.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -<<<<<<<< HEAD:Assets/FishNet/Runtime/Managing/Prediction.meta -guid: 549a94b4ad77ccc4b8511ccb476d767c -======== -guid: 678ea4b95d0063048acf8abf6928acf4 ->>>>>>>> origin/3-pre-3.1:Assets/Test/InitializeOrder.meta -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Prediction/Editor.meta b/Assets/FishNet/Runtime/Managing/Prediction/Editor.meta deleted file mode 100644 index a928c88..0000000 --- a/Assets/FishNet/Runtime/Managing/Prediction/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: f57d8859721e294489f2991b0458aea9 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Prediction/Editor/PredictionManagerEditor.cs b/Assets/FishNet/Runtime/Managing/Prediction/Editor/PredictionManagerEditor.cs deleted file mode 100644 index a94ac6e..0000000 --- a/Assets/FishNet/Runtime/Managing/Prediction/Editor/PredictionManagerEditor.cs +++ /dev/null @@ -1,74 +0,0 @@ -#if UNITY_EDITOR -using UnityEditor; -using UnityEngine; - -namespace FishNet.Managing.Predicting.Editing -{ - - - [CustomEditor(typeof(PredictionManager), true)] - [CanEditMultipleObjects] - public class PredictionManagerEditor : Editor - { - private SerializedProperty _dropExcessiveReplicates; - private SerializedProperty _maximumServerReplicates; - private SerializedProperty _maximumConsumeCount; - private SerializedProperty _redundancyCount; - private SerializedProperty _allowPredictedSpawning; - private SerializedProperty _reservedObjectIds; - - - protected virtual void OnEnable() - { - _dropExcessiveReplicates = serializedObject.FindProperty("_dropExcessiveReplicates"); - _maximumServerReplicates = serializedObject.FindProperty("_maximumServerReplicates"); - _maximumConsumeCount = serializedObject.FindProperty("_maximumConsumeCount"); - _redundancyCount = serializedObject.FindProperty("_redundancyCount"); - _allowPredictedSpawning = serializedObject.FindProperty(nameof(_allowPredictedSpawning)); - _reservedObjectIds = serializedObject.FindProperty(nameof(_reservedObjectIds)); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - GUI.enabled = false; - EditorGUILayout.ObjectField("Script:", MonoScript.FromMonoBehaviour((PredictionManager)target), typeof(PredictionManager), false); - GUI.enabled = true; - - EditorGUILayout.LabelField("Server", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_dropExcessiveReplicates); - EditorGUI.indentLevel++; - if (_dropExcessiveReplicates.boolValue == true) - { - EditorGUILayout.PropertyField(_maximumServerReplicates); - } - else - { - EditorGUILayout.PropertyField(_maximumConsumeCount); - } - EditorGUI.indentLevel--; - EditorGUI.indentLevel--; - - EditorGUILayout.LabelField("Client", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_redundancyCount); - EditorGUI.indentLevel--; - - EditorGUILayout.PropertyField(_allowPredictedSpawning); - if (_allowPredictedSpawning.boolValue == true) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_reservedObjectIds); - EditorGUI.indentLevel--; - } - - EditorGUILayout.Space(); - - serializedObject.ApplyModifiedProperties(); - } - - } -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Prediction/Editor/PredictionManagerEditor.cs.meta b/Assets/FishNet/Runtime/Managing/Prediction/Editor/PredictionManagerEditor.cs.meta deleted file mode 100644 index a2276c4..0000000 --- a/Assets/FishNet/Runtime/Managing/Prediction/Editor/PredictionManagerEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5382c1ab98f25c8439d23140d36651fe -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Prediction/PredictionManager.cs b/Assets/FishNet/Runtime/Managing/Prediction/PredictionManager.cs deleted file mode 100644 index 694b3b7..0000000 --- a/Assets/FishNet/Runtime/Managing/Prediction/PredictionManager.cs +++ /dev/null @@ -1,323 +0,0 @@ -using FishNet.Documenting; -using FishNet.Object; -using FishNet.Serializing.Helping; -using FishNet.Transporting; -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityScene = UnityEngine.SceneManagement.Scene; - - -namespace FishNet.Managing.Predicting -{ - - /// - /// Additional options for managing the observer system. - /// - [DisallowMultipleComponent] - [AddComponentMenu("FishNet/Manager/PredictionManager")] - public sealed class PredictionManager : MonoBehaviour - { - #region Public. - /// - /// Called before performing a reconcile on NetworkBehaviour. - /// - public event Action OnPreReconcile; - /// - /// Called after performing a reconcile on a NetworkBehaviour. - /// - public event Action OnPostReconcile; - /// - /// Called before physics is simulated when replaying a replicate method. - /// Contains the PhysicsScene and PhysicsScene2D which was simulated. - /// - public event Action OnPreReplicateReplay; - /// - /// Called after physics is simulated when replaying a replicate method. - /// Contains the PhysicsScene and PhysicsScene2D which was simulated. - /// - public event Action OnPostReplicateReplay; - /// - /// Called before the server sends a reconcile. - /// - public event Action OnPreServerReconcile; - /// - /// Called after the server sends a reconcile. - /// - public event Action OnPostServerReconcile; - /// - /// Last tick any object reconciled. - /// - public uint LastReconcileTick { get; internal set; } - /// - /// Last tick any object replicated. - /// - public uint LastReplicateTick { get; internal set; } - /// - /// True if rigidbodies are being predicted. - /// - internal bool UsingRigidbodies => (_rigidbodies.Count > 0); - /// - /// Returns if any prediction is replaying. - /// - /// - public bool IsReplaying() => _isReplaying; - private bool _isReplaying; - /// - /// Returns if scene is replaying. - /// - /// - /// - public bool IsReplaying(UnityScene scene) => _replayingScenes.Contains(scene); - #endregion - - #region Serialized. - /// - /// - /// - [Tooltip("True to drop replicates from clients which are being received excessively. This can help with attacks but may cause client to temporarily desynchronize during connectivity issues. When false the server will hold at most up to 3 seconds worth of replicates, consuming multiple per tick to clear out the buffer quicker. This is good to ensure all inputs are executed but potentially could allow speed hacking.")] - [SerializeField] - private bool _dropExcessiveReplicates = true; - /// - /// True to drop replicates from clients which are being received excessively. This can help with attacks but may cause client to temporarily desynchronize during connectivity issues. - /// When false the server will hold at most up to 3 seconds worth of replicates, consuming multiple per tick to clear out the buffer quicker. This is good to ensure all inputs are executed but potentially could allow speed hacking. - /// - internal bool DropExcessiveReplicates => _dropExcessiveReplicates; - /// - /// - /// - [Tooltip("Maximum number of replicates a server can queue per object. Higher values will put more load on the server and add replicate latency for the client.")] - [SerializeField] - private ushort _maximumServerReplicates = 15; - /// - /// Maximum number of replicates a server can queue per object. Higher values will put more load on the server and add replicate latency for the client. - /// - public ushort GetMaximumServerReplicates() => _maximumServerReplicates; - /// - /// Sets the maximum number of replicates a server can queue per object. - /// - /// - public void SetMaximumServerReplicates(ushort value) - { - _maximumServerReplicates = (ushort)Mathf.Clamp(value, MINIMUM_REPLICATE_QUEUE_SIZE, MAXIMUM_REPLICATE_QUEUE_SIZE); - } - /// - /// - /// - [Tooltip("Maximum number of excessive replicates which can be consumed per tick. Consumption count will scale up to this value automatically.")] - [SerializeField] - private byte _maximumConsumeCount = 4; - /// - /// Maximum number of excessive replicates which can be consumed per tick. Consumption count will scale up to this value automatically. - /// - internal byte GetMaximumConsumeCount() => _maximumConsumeCount; - - /// - /// - /// - [Tooltip("Maximum number of past inputs which may send.")] - [Range(MINIMUM_PAST_INPUTS, MAXIMUM_PAST_INPUTS)] - [SerializeField] - private byte _redundancyCount = 3; - /// - /// Maximum number of past inputs which may send and resend redundancy. - /// -#if UNITY_WEBGL -//WebGL uses reliable so no reason to use redundancy. - internal byte GetRedundancyCount() => 1; -#else - internal byte GetRedundancyCount() => _redundancyCount; -#endif - /// - /// True to allow clients to use predicted spawning. While true, each NetworkObject prefab you wish to predicted spawn must be marked as to allow this feature. - /// - internal bool GetAllowPredictedSpawning() => _allowPredictedSpawning; - [Tooltip("True to allow clients to use predicted spawning and despawning. While true, each NetworkObject prefab you wish to predicted spawn must be marked as to allow this feature.")] - [SerializeField] - private bool _allowPredictedSpawning = false; - /// - /// - /// - [Tooltip("Maximum number of Ids to reserve on clients for predicted spawning. Higher values will allow clients to send more predicted spawns per second but may reduce availability of ObjectIds with high player counts.")] - [Range(1, 100)] - [SerializeField] - private byte _reservedObjectIds = 15; - /// - /// Maximum number of Ids to reserve on clients for predicted spawning. Higher values will allow clients to send more predicted spawns per second but may reduce availability of ObjectIds with high player counts. - /// - /// - internal byte GetReservedObjectIds() => _reservedObjectIds; - #endregion - - #region Private. - /// - /// Number of active predicted rigidbodies. - /// - [System.NonSerialized] - private HashSet _rigidbodies = new HashSet(); - /// - /// Cache to remove null entries from _rigidbodies. - /// - [System.NonSerialized] - private HashSet _componentCache = new HashSet(); - /// - /// NetworkManager used with this. - /// - private NetworkManager _networkManager; - /// - /// Scenes which are currently replaying prediction. - /// - private HashSet _replayingScenes = new HashSet(new SceneHandleEqualityComparer()); -#endregion - -#region Const. - /// - /// Minimum number of past inputs which can be sent. - /// - private const byte MINIMUM_PAST_INPUTS = 2; - /// - /// Maximum number of past inputs which can be sent. - /// - internal const byte MAXIMUM_PAST_INPUTS = 15; - /// - /// Minimum amount of replicate queue size. - /// - private const ushort MINIMUM_REPLICATE_QUEUE_SIZE = 10; - /// - /// Maxmimum amount of replicate queue size. - /// - private const ushort MAXIMUM_REPLICATE_QUEUE_SIZE = 500; -#endregion - - private void OnEnable() - { - UnityEngine.SceneManagement.SceneManager.sceneUnloaded += SceneManager_sceneUnloaded; - } - - private void OnDisable() - { - UnityEngine.SceneManagement.SceneManager.sceneUnloaded -= SceneManager_sceneUnloaded; - } - - internal void InitializeOnce_Internal(NetworkManager manager) - { - _networkManager = manager; - _networkManager.ClientManager.OnClientConnectionState += ClientManager_OnClientConnectionState; - } - - /// - /// Called after the local client connection state changes. - /// - private void ClientManager_OnClientConnectionState(ClientConnectionStateArgs obj) - { - if (obj.ConnectionState != LocalConnectionState.Started) - _replayingScenes.Clear(); - _isReplaying = false; - - } - - - /// - /// Called before and after server sends a reconcile. - /// - /// True if before the reconcile is sent. - internal void InvokeServerReconcile(NetworkBehaviour caller, bool before) - { - if (before) - OnPreServerReconcile?.Invoke(caller); - else - OnPostServerReconcile?.Invoke(caller); - } - - /// - /// Increases Rigidbodies count by 1. - /// - [APIExclude] - public void AddRigidbodyCount(UnityEngine.Component c) - { - _rigidbodies.Add(c); - } - - /// - /// Dencreases Rigidbodies count by 1. - /// - [APIExclude] - public void RemoveRigidbodyCount(UnityEngine.Component c) - { - bool removed = _rigidbodies.Remove(c); - /* If remove failed the rigidbodies may need to be rebuild. - * This might happen when an object is destroyed as - * the referenced is passed. Could be any number of things - * but it seems to occur frequently enough in Unity, - * especially when testing in editor. - * - * This operation is not ideal in the hot path but - * the odds of it happening are pretty slim and - * it ensures stability against user error. */ - if (!removed) - { - //Cannt remove null entries from a hashset so have to rebuild. - _componentCache.Clear(); - foreach (UnityEngine.Component item in _rigidbodies) - { - if (item != null) - _componentCache.Add(item); - } - - //Apply to rigidbodies. - _rigidbodies.Clear(); - foreach (UnityEngine.Component item in _componentCache) - _rigidbodies.Add(item); - } - } - - - /// - /// Invokes OnPre/PostReconcile events. - /// Internal use. - /// - [APIExclude] - [CodegenMakePublic] //To internal. - public void InvokeOnReconcile_Internal(NetworkBehaviour nb, bool before) - { - nb.IsReconciling = before; - if (before) - OnPreReconcile?.Invoke(nb); - else - OnPostReconcile?.Invoke(nb); - } - - /// - /// Invokes OnReplicateReplay. - /// Internal use. - /// - [APIExclude] - [CodegenMakePublic] //To internal. - public void InvokeOnReplicateReplay_Internal(UnityScene scene, uint tick, PhysicsScene ps, PhysicsScene2D ps2d, bool before) - { - _isReplaying = before; - if (before) - { - _replayingScenes.Add(scene); - OnPreReplicateReplay?.Invoke(tick, ps, ps2d); - } - else - { - _replayingScenes.Remove(scene); - OnPostReplicateReplay?.Invoke(tick, ps, ps2d); - } - } - - - /// - /// Called when a scene unloads. - /// - /// - private void SceneManager_sceneUnloaded(UnityScene s) - { - _replayingScenes.Remove(s); - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Prediction/PredictionManager.cs.meta b/Assets/FishNet/Runtime/Managing/Prediction/PredictionManager.cs.meta deleted file mode 100644 index a2acd01..0000000 --- a/Assets/FishNet/Runtime/Managing/Prediction/PredictionManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e08bb003fce297d4086cf8cba5aa459a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened.meta b/Assets/FishNet/Runtime/Managing/Scened.meta deleted file mode 100644 index 3e495f2..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 212ba5e93fab23e45a461067dc0bf611 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/Broadcast.meta b/Assets/FishNet/Runtime/Managing/Scened/Broadcast.meta deleted file mode 100644 index 0704a09..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/Broadcast.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 8eb071c832ae3664c9b1701b52872513 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/Broadcast/SceneBroadcasts.cs b/Assets/FishNet/Runtime/Managing/Scened/Broadcast/SceneBroadcasts.cs deleted file mode 100644 index 5ce7c3b..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/Broadcast/SceneBroadcasts.cs +++ /dev/null @@ -1,38 +0,0 @@ -using FishNet.Broadcast; -using FishNet.Documenting; - -namespace FishNet.Managing.Scened -{ - - /// - /// Sent when there are starting scenes for the client to load. - /// - public struct EmptyStartScenesBroadcast : IBroadcast { } - /// - /// Sent to clients to load networked scenes. - /// - [APIExclude] - public struct LoadScenesBroadcast : IBroadcast - { - public LoadQueueData QueueData; - } - - /// - /// Sent to clients to unload networked scenes. - /// - [APIExclude] - public struct UnloadScenesBroadcast : IBroadcast - { - public UnloadQueueData QueueData; - } - - /// - /// Sent to server to indicate which scenes a client has loaded. - /// - [APIExclude] - public struct ClientScenesLoadedBroadcast : IBroadcast - { - public SceneLookupData[] SceneLookupDatas; - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/Broadcast/SceneBroadcasts.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/Broadcast/SceneBroadcasts.cs.meta deleted file mode 100644 index 1c271ef..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/Broadcast/SceneBroadcasts.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 698a94b4f8664ac4ab108deae0ba3b7c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/DefaultSceneProcessor.cs b/Assets/FishNet/Runtime/Managing/Scened/DefaultSceneProcessor.cs deleted file mode 100644 index df5ef1e..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/DefaultSceneProcessor.cs +++ /dev/null @@ -1,155 +0,0 @@ -using System.Collections.Generic; -using UnityEngine; -using UnitySceneManager = UnityEngine.SceneManagement.SceneManager; -using UnityScene = UnityEngine.SceneManagement.Scene; -using System.Collections; - -namespace FishNet.Managing.Scened -{ - - public class DefaultSceneProcessor : SceneProcessorBase - { - #region Private. - /// - /// Currently active loading AsyncOperations. - /// - protected List LoadingAsyncOperations = new List(); - /// - /// A collection of scenes used both for loading and unloading. - /// - protected List Scenes = new List(); - /// - /// Current AsyncOperation being processed. - /// - protected AsyncOperation CurrentAsyncOperation; - #endregion - - /// - /// Called when scene loading has begun. - /// - public override void LoadStart(LoadQueueData queueData) - { - base.LoadStart(queueData); - ResetValues(); - } - - public override void LoadEnd(LoadQueueData queueData) - { - base.LoadEnd(queueData); - ResetValues(); - } - - /// - /// Resets values for a fresh load or unload. - /// - private void ResetValues() - { - CurrentAsyncOperation = null; - LoadingAsyncOperations.Clear(); - } - - /// - /// Called when scene unloading has begun within an unload operation. - /// - /// - public override void UnloadStart(UnloadQueueData queueData) - { - base.UnloadStart(queueData); - Scenes.Clear(); - } - - /// - /// Begin loading a scene using an async method. - /// - /// Scene name to load. - public override void BeginLoadAsync(string sceneName, UnityEngine.SceneManagement.LoadSceneParameters parameters) - { - AsyncOperation ao = UnitySceneManager.LoadSceneAsync(sceneName, parameters); - LoadingAsyncOperations.Add(ao); - - CurrentAsyncOperation = ao; - CurrentAsyncOperation.allowSceneActivation = false; - } - - /// - /// Begin unloading a scene using an async method. - /// - /// Scene name to unload. - public override void BeginUnloadAsync(UnityScene scene) - { - CurrentAsyncOperation = UnitySceneManager.UnloadSceneAsync(scene); - } - - /// - /// Returns if a scene load or unload percent is done. - /// - /// - public override bool IsPercentComplete() - { - return (GetPercentComplete() >= 0.9f); - } - - /// - /// Returns the progress on the current scene load or unload. - /// - /// - public override float GetPercentComplete() - { - return (CurrentAsyncOperation == null) ? 1f : CurrentAsyncOperation.progress; - } - - /// - /// Adds a loaded scene. - /// - /// Scene loaded. - public override void AddLoadedScene(UnityScene scene) - { - base.AddLoadedScene(scene); - Scenes.Add(scene); - } - - /// - /// Returns scenes which were loaded during a load operation. - /// - public override List GetLoadedScenes() - { - return Scenes; - } - - /// - /// Activates scenes which were loaded. - /// - public override void ActivateLoadedScenes() - { - foreach (AsyncOperation ao in LoadingAsyncOperations) - ao.allowSceneActivation = true; - } - - /// - /// Returns if all asynchronized tasks are considered IsDone. - /// - /// - public override IEnumerator AsyncsIsDone() - { - bool notDone; - do - { - notDone = false; - foreach (AsyncOperation ao in LoadingAsyncOperations) - { - - if (!ao.isDone) - { - notDone = true; - break; - } - } - yield return null; - } while (notDone); - - yield break; - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/DefaultSceneProcessor.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/DefaultSceneProcessor.cs.meta deleted file mode 100644 index 086a4ba..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/DefaultSceneProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0c6eacaa60569d947b383df03fff1ea3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/Events.meta b/Assets/FishNet/Runtime/Managing/Scened/Events.meta deleted file mode 100644 index 8c02699..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/Events.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 09823f70d9231d34f91d88d11b937758 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/Events/ClientPresenceChangeEventArgs.cs b/Assets/FishNet/Runtime/Managing/Scened/Events/ClientPresenceChangeEventArgs.cs deleted file mode 100644 index 440613c..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/Events/ClientPresenceChangeEventArgs.cs +++ /dev/null @@ -1,34 +0,0 @@ -using FishNet.Connection; -using UnityEngine.SceneManagement; - -namespace FishNet.Managing.Scened -{ - /// - /// Data container about a scene presence change for a client. - /// - public struct ClientPresenceChangeEventArgs - { - - /// - /// Scene on the server which the client's presence has changed. - /// - public Scene Scene; - /// - /// Connection to client. - /// - public NetworkConnection Connection; - /// - /// True if the client was added to the scene, false is removed. - /// - public bool Added; - - internal ClientPresenceChangeEventArgs(Scene scene, NetworkConnection conn, bool added) - { - Scene = scene; - Connection = conn; - Added = added; - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/Events/ClientPresenceChangeEventArgs.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/Events/ClientPresenceChangeEventArgs.cs.meta deleted file mode 100644 index e250e89..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/Events/ClientPresenceChangeEventArgs.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fa91039d4ab1c6445af72881af122b0a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/Events/LoadSceneEventArgs.cs b/Assets/FishNet/Runtime/Managing/Scened/Events/LoadSceneEventArgs.cs deleted file mode 100644 index 304fcd5..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/Events/LoadSceneEventArgs.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System.Collections.Generic; -using UnityEngine.SceneManagement; - -namespace FishNet.Managing.Scened -{ - /// - /// Data container about a scene load start. - /// - public struct SceneLoadStartEventArgs - { - /// - /// Queue data used by the current scene action. - /// - public readonly LoadQueueData QueueData; - - internal SceneLoadStartEventArgs(LoadQueueData lqd) - { - QueueData = lqd; - } - } - - - /// - /// Data container about a scene load percent change. - /// - public struct SceneLoadPercentEventArgs - { - /// - /// Queue data used by the current scene action. - /// - public readonly LoadQueueData QueueData; - /// - /// Percentage of change completion. 1f is equal to 100% complete. - /// - public readonly float Percent; - - internal SceneLoadPercentEventArgs(LoadQueueData lqd, float percent) - { - QueueData = lqd; - Percent = percent; - } - } - - - /// - /// Data container about a scene load end. - /// - public struct SceneLoadEndEventArgs - { - /// - /// Queue data used by the current scene action. - /// - public readonly LoadQueueData QueueData; - /// - /// Scenes which were loaded. - /// - public readonly Scene[] LoadedScenes; - /// - /// Scenes which were skipped because they were already loaded. - /// - public readonly string[] SkippedSceneNames; - /// - /// Scenes which were unloaded. - /// - public readonly string[] UnloadedSceneNames; - - internal SceneLoadEndEventArgs(LoadQueueData lqd, string[] skipped, Scene[] loaded, string[] unloadedSceneNames) - { - QueueData = lqd; - SkippedSceneNames = skipped; - LoadedScenes = loaded; - UnloadedSceneNames = unloadedSceneNames; - } - - - } - -} diff --git a/Assets/FishNet/Runtime/Managing/Scened/Events/LoadSceneEventArgs.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/Events/LoadSceneEventArgs.cs.meta deleted file mode 100644 index 58c3671..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/Events/LoadSceneEventArgs.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 86278568f8087de49b0908f148501993 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/Events/UnloadSceneEventArgs.cs b/Assets/FishNet/Runtime/Managing/Scened/Events/UnloadSceneEventArgs.cs deleted file mode 100644 index 2178873..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/Events/UnloadSceneEventArgs.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using UnityEngine.SceneManagement; - -namespace FishNet.Managing.Scened -{ - - /// - /// Data container about a scene unload start. - /// - public struct SceneUnloadStartEventArgs - { - /// - /// Queue data used by the current scene action. - /// - public readonly UnloadQueueData QueueData; - - internal SceneUnloadStartEventArgs(UnloadQueueData sqd) - { - QueueData = sqd; - } - } - - /// - /// Data container about a scene unload end. - /// - public struct SceneUnloadEndEventArgs - { - /// - /// Queue data used by the current scene action. - /// - public readonly UnloadQueueData QueueData; - /// - /// Handles of scenes which were successfully unloaded. - /// - [Obsolete("Use UnloadedScenesV2")] - public int[] UnloadedSceneHandles; - /// - /// Names of scenes which were successfully unloaded. - /// - [Obsolete("Use UnloadedScenesV2")] - public string[] UnloadedSceneNames; - - /// - /// Scenes which were successfully unloaded. - /// This collection may be populated with empty scenes depending on engine version. - /// - public List UnloadedScenes; - /// - /// Unloaded scenes with names and handles cached. - /// This will be renamed as UnloadedScenes in Fish-Networking version 4. - /// - public List UnloadedScenesV2; - - internal SceneUnloadEndEventArgs(UnloadQueueData sqd, List unloadedScenes, List newUnloadedScenes) - { - QueueData = sqd; - UnloadedScenes = unloadedScenes; - UnloadedScenesV2 = newUnloadedScenes; - -#pragma warning disable CS0618 // Type or member is obsolete - UnloadedSceneNames = new string[newUnloadedScenes.Count]; - UnloadedSceneHandles = new int[newUnloadedScenes.Count]; - for (int i = 0; i < newUnloadedScenes.Count; i++) - { - UnloadedSceneNames[i] = newUnloadedScenes[i].Name; - UnloadedSceneHandles[i] = newUnloadedScenes[i].Handle; - } -#pragma warning restore CS0618 - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/Events/UnloadSceneEventArgs.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/Events/UnloadSceneEventArgs.cs.meta deleted file mode 100644 index da3c534..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/Events/UnloadSceneEventArgs.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2c24765fea85b564aa331b529f324f92 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas.meta b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas.meta deleted file mode 100644 index ad45a3a..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: beefc84827a4af141aa1b326fca9084f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadOptions.cs b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadOptions.cs deleted file mode 100644 index 95cb085..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadOptions.cs +++ /dev/null @@ -1,39 +0,0 @@ -using UnityEngine.SceneManagement; - -namespace FishNet.Managing.Scened -{ - /// - /// Settings to apply when loading a scene. - /// - public class LoadOptions - { - /// - /// True if to automatically unload the loaded scenes when they are no longer being used by clients. This field only applies to scenes loaded for connections, not globally loaded scenes. - /// - [System.NonSerialized] - public bool AutomaticallyUnload = true; - /// - /// False if to only load scenes which are not yet loaded. When true a scene may load multiple times; this is known as scene stacking. Only the server is able to stack scenes; clients will load a single instance. Global scenes cannot be stacked. - /// - [System.NonSerialized] - public bool AllowStacking; - /// - /// LocalPhysics mode to use when loading this scene. Generally this will only be used when applying scene stacking. Only used by the server. - /// https://docs.unity3d.com/ScriptReference/SceneManagement.LocalPhysicsMode.html - /// - [System.NonSerialized] - public LocalPhysicsMode LocalPhysics = LocalPhysicsMode.None; - /// - /// True to reload a scene if it's already loaded. - /// This does not function yet. - /// - [System.Obsolete("This feature is not functional yet but will be at a later release.")] - public bool ReloadScenes; - /// - /// True if scenes should be loaded using addressables. This field only exists for optional use so the user may know if their queue data is using addressables. - /// - public bool Addressables; - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadOptions.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadOptions.cs.meta deleted file mode 100644 index 3ca0ef9..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadOptions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1614453d3786b2a4eb18b69297da7dc9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadParams.cs b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadParams.cs deleted file mode 100644 index 0c62f63..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadParams.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace FishNet.Managing.Scened -{ - /// - /// Additional user-crafted data which can be included in scene load callbacks. - /// - public class LoadParams - { - /// - /// Objects which are included in callbacks on the server when loading a scene. Can be useful for including unique information about the scene, such as match id. These are not sent to clients; use ClientParams for this. - /// - [System.NonSerialized] - public object[] ServerParams = new object[0]; - /// - /// Bytes which are sent to clients during scene loads. Can contain any information. - /// - public byte[] ClientParams = new byte[0]; - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadParams.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadParams.cs.meta deleted file mode 100644 index ce62050..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadParams.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d8b395f67f61b4e45830a70289a1901d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadQueueData.cs b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadQueueData.cs deleted file mode 100644 index c2300f6..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadQueueData.cs +++ /dev/null @@ -1,51 +0,0 @@ -using FishNet.Connection; -using FishNet.Utility.Constant; -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo(UtilityConstants.GENERATED_ASSEMBLY_NAME)] -namespace FishNet.Managing.Scened -{ - - - /// - /// Data generated when loading a scene. - /// - public class LoadQueueData - { - /// - /// Clients which receive this SceneQueueData. If Networked, all clients do. If Connections, only the specified Connections do. - /// - [System.NonSerialized] - public SceneScopeType ScopeType; - /// - /// Connections to load scenes for. Only valid on the server and when ScopeType is Connections. - /// - [System.NonSerialized] - public NetworkConnection[] Connections = new NetworkConnection[0]; - /// - /// SceneLoadData to use. - /// - public SceneLoadData SceneLoadData = null; - /// - /// Current global scenes. - /// - public string[] GlobalScenes = new string[0]; - /// - /// True if to iterate this queue data as server. - /// - [System.NonSerialized] - public readonly bool AsServer; - - public LoadQueueData() { } - internal LoadQueueData(SceneScopeType scopeType, NetworkConnection[] conns, SceneLoadData sceneLoadData, string[] globalScenes, bool asServer) - { - ScopeType = scopeType; - Connections = conns; - SceneLoadData = sceneLoadData; - GlobalScenes = globalScenes; - AsServer = asServer; - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadQueueData.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadQueueData.cs.meta deleted file mode 100644 index d58489f..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/LoadQueueData.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8fb4183af628f754b800dfdbb1ba9bf0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/ReplaceOption.cs b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/ReplaceOption.cs deleted file mode 100644 index 96a3800..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/ReplaceOption.cs +++ /dev/null @@ -1,25 +0,0 @@ - -namespace FishNet.Managing.Scened -{ - /// - /// How to replace scenes when loading. - /// - public enum ReplaceOption : byte - { - /// - /// Replace all scenes, online and offline. - /// - All, - /// - /// Only replace scenes loaded using the SceneManager. - /// - OnlineOnly, - /// - /// Do not replace any scenes, additional scenes will be loaded as additive. - /// - None - } - - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/ReplaceOption.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/ReplaceOption.cs.meta deleted file mode 100644 index c1ab805..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/ReplaceOption.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: cb8e2c0fe3b9d3344a05810936861555 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneLoadData.cs b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneLoadData.cs deleted file mode 100644 index 06eb39f..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneLoadData.cs +++ /dev/null @@ -1,201 +0,0 @@ -using FishNet.Object; -using FishNet.Serializing.Helping; -using System.Collections.Generic; -using System.IO; -using UnityEngine.SceneManagement; - -namespace FishNet.Managing.Scened -{ - /// - /// Data about which scenes to load. - /// - public class SceneLoadData - { - /// - /// When specified this scene will be set as the active scene after loading occurs. - /// - public SceneLookupData PreferredActiveScene = null; - /// - /// SceneLookupData for each scene to load. - /// - public SceneLookupData[] SceneLookupDatas = new SceneLookupData[0]; - /// - /// NetworkObjects to move to the new scenes. Objects will be moved to the first scene. - /// - public NetworkObject[] MovedNetworkObjects = new NetworkObject[0]; - /// - /// How to replace current scenes with new ones. When replacing scenes the first scene loaded will be set as the active scene, and the rest additive. - /// - public ReplaceOption ReplaceScenes = ReplaceOption.None; - /// - /// Parameters which may be set and will be included in load callbacks. - /// - public LoadParams Params = new LoadParams(); - /// - /// Additional options to use for loaded scenes. - /// - public LoadOptions Options = new LoadOptions(); - - public SceneLoadData() { } - /// - /// - /// - /// Scene to load. - public SceneLoadData(Scene scene) : this(new Scene[] { scene }, null) { } - /// - /// - /// - /// Scene to load by name. - public SceneLoadData(string sceneName) : this(new string[] { sceneName }, null) { } - /// - /// - /// - /// Scene to load by handle. - public SceneLoadData(int sceneHandle) : this(new int[] { sceneHandle }, null) { } - /// - /// - /// - /// Scene to load by handle. - /// Scene to load by name. - public SceneLoadData(int sceneHandle, string sceneName) : this(new SceneLookupData(sceneHandle, sceneName)) { } - /// - /// - /// - /// Scene to load by SceneLookupData. - public SceneLoadData(SceneLookupData sceneLookupData) : this(new SceneLookupData[] { sceneLookupData }) { } - /// - /// - /// - /// Scenes to load. - public SceneLoadData(List scenes) : this(scenes.ToArray(), null) { } - /// - /// - /// - /// Scenes to load by name. - public SceneLoadData(List sceneNames) : this(sceneNames.ToArray(), null) { } - /// - /// - /// - /// Scenes to load by handle. - public SceneLoadData(List sceneHandles) : this(sceneHandles.ToArray(), null) { } - /// - /// - /// - /// Scenes to load. - public SceneLoadData(Scene[] scenes) : this(scenes, null) { } - /// - /// - /// - /// Scenes to load by name. - public SceneLoadData(string[] sceneNames) : this(sceneNames, null) { } - /// - /// - /// - /// Scenes to load by handle. - public SceneLoadData(int[] sceneHandles) : this(sceneHandles, null) { } - /// - /// - /// - /// Scenes to load by SceneLookupDatas. - public SceneLoadData(SceneLookupData[] sceneLookupDatas) : this(sceneLookupDatas, null) { } - - /// - /// - /// - /// Scene to load. - /// NetworkObjects to move to the first specified scene. - public SceneLoadData(Scene scene, NetworkObject[] movedNetworkObjects) - { - SceneLookupData data = SceneLookupData.CreateData(scene); - Construct(new SceneLookupData[] { data }, movedNetworkObjects); - } - /// - /// - /// - /// Scenes to load. - /// NetworkObjects to move to the first specified scene. - public SceneLoadData(Scene[] scenes, NetworkObject[] movedNetworkObjects) - { - SceneLookupData[] datas = SceneLookupData.CreateData(scenes); - Construct(datas, movedNetworkObjects); - } - /// - /// - /// - /// Scenes to load by Name. - /// NetworkObjects to move to the first specified scene. - public SceneLoadData(string[] sceneNames, NetworkObject[] movedNetworkObjects) - { - SceneLookupData[] datas = SceneLookupData.CreateData(sceneNames); - Construct(datas, movedNetworkObjects); - } - /// - /// - /// - /// Scenes to load by handle. - /// NetworkObjects to move to the first specified scene. - public SceneLoadData(int[] sceneHandles, NetworkObject[] movedNetworkObjects) - { - SceneLookupData[] datas = SceneLookupData.CreateData(sceneHandles); - Construct(datas, movedNetworkObjects); - } - /// - /// - /// - /// Scenes to load by SceneLookupDatas. - /// NetworkObjects to move to the first specified scene. - public SceneLoadData(SceneLookupData[] sceneLookupDatas, NetworkObject[] movedNetworkObjects) - { - Construct(sceneLookupDatas, movedNetworkObjects); - } - - /// - /// Called at the end of every constructor. - /// - private void Construct(SceneLookupData[] datas, NetworkObject[] movedNetworkObjects) - { - SceneLookupDatas = datas; - if (movedNetworkObjects == null) - movedNetworkObjects = new NetworkObject[0]; - MovedNetworkObjects = movedNetworkObjects; - } - - /// - /// Gets the first Scene in SceneLookupDatas. - /// - /// - public Scene GetFirstLookupScene() - { - foreach (SceneLookupData sld in SceneLookupDatas) - { - Scene result = sld.GetScene(out _); - if (!string.IsNullOrEmpty(result.name)) - return result; - } - - return default; - } - - - /// - /// Returns if any data is invalid, such as null entries. - /// - /// - internal bool DataInvalid() - { - //Null values. - if (Params == null || MovedNetworkObjects == null || SceneLookupDatas == null || - Options == null) - return true; - //No lookups. - if (SceneLookupDatas.Length == 0) - return true; - - return false; - } - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneLoadData.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneLoadData.cs.meta deleted file mode 100644 index e6bb59a..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneLoadData.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ecd4065158ab62047a074c594f245d90 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneScopeTypes.cs b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneScopeTypes.cs deleted file mode 100644 index 91087e0..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneScopeTypes.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace FishNet.Managing.Scened -{ - /// - /// Type of scopes for a scene load or unload. - /// - public enum SceneScopeType : byte - { - /// - /// Scene action occured for all clients. - /// - Global = 0, - /// - /// Scene action occurred for specified clients. - /// - Connections = 1 - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneScopeTypes.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneScopeTypes.cs.meta deleted file mode 100644 index 9baf271..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneScopeTypes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2be621eb04519a14eb2297a666b1bc2c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneUnloadData.cs b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneUnloadData.cs deleted file mode 100644 index d17a63b..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneUnloadData.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System.Collections.Generic; -using UnityEngine.SceneManagement; - -namespace FishNet.Managing.Scened -{ - - /// - /// Data about which scenes to unload. - /// - public class SceneUnloadData - { - /// - /// When specified this scene will be set as the active scene after unloading occurs. - /// - public SceneLookupData PreferredActiveScene = null; - /// - /// SceneLookupData for each scene to load. - /// - public SceneLookupData[] SceneLookupDatas = new SceneLookupData[0]; - /// - /// Parameters which may be set and will be included in load callbacks. - /// - public UnloadParams Params = new UnloadParams(); - /// - /// Additional options to use for loaded scenes. - /// - public UnloadOptions Options = new UnloadOptions(); - - /// - /// - /// - public SceneUnloadData() { } - /// - /// - /// - /// Scene to unload. - public SceneUnloadData(Scene scene) : this(new Scene[] { scene }) { } - /// - /// - /// - /// Scene to unload by name. - public SceneUnloadData(string sceneName) : this(new string[] { sceneName }) { } - /// - /// - /// - /// Scene to unload by handle. - public SceneUnloadData(int sceneHandle) : this(new int[] { sceneHandle }) { } - /// - /// - /// - /// Scenes to unload. - public SceneUnloadData(List scenes) : this(scenes.ToArray()) { } - /// - /// - /// - /// Scenes to unload by names. - public SceneUnloadData(List sceneNames) : this(sceneNames.ToArray()) { } - /// - /// - /// - /// Scenes to unload by handles. - public SceneUnloadData(List sceneHandles) : this(sceneHandles.ToArray()) { } - /// - /// - /// - /// Scenes to unload. - public SceneUnloadData(Scene[] scenes) - { - SceneLookupDatas = SceneLookupData.CreateData(scenes); - } - /// - /// - /// - /// Scenes to unload by names. - public SceneUnloadData(string[] sceneNames) - { - SceneLookupDatas = SceneLookupData.CreateData(sceneNames); - } - /// - /// - /// - /// Scenes to unload by handles. - public SceneUnloadData(int[] sceneHandles) - { - SceneLookupDatas = SceneLookupData.CreateData(sceneHandles); - } - /// - /// - /// - /// Scenes to unload by SceneLookupDatas. - public SceneUnloadData(SceneLookupData[] sceneLookupDatas) - { - SceneLookupDatas = sceneLookupDatas; - } - - - /// - /// Returns if any data is invalid, such as null entries. - /// - /// - internal bool DataInvalid() - { - //Null values. - if (Params == null || SceneLookupDatas == null || - Options == null) - return true; - //No lookups. - if (SceneLookupDatas.Length == 0) - return true; - - return false; - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneUnloadData.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneUnloadData.cs.meta deleted file mode 100644 index a4a3d0d..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/SceneUnloadData.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 77cbfeea232e4ab44a4315b003ce6742 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadOptions.cs b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadOptions.cs deleted file mode 100644 index 8224759..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadOptions.cs +++ /dev/null @@ -1,36 +0,0 @@ - -namespace FishNet.Managing.Scened -{ - /// - /// Settings to apply when loading a scene. - /// - public class UnloadOptions - { - /// - /// Conditions to unloading a scene on the server. - /// - public enum ServerUnloadMode - { - /// - /// Unloads the scene if no more connections are within it. - /// - UnloadUnused = 0, - /// - /// Unloads scenes for connections but keeps scene loaded on server even if no connections are within it. - /// - KeepUnused = 1, - } - - /// - /// How to unload scenes on the server. UnloadUnused will unload scenes which have no more clients in them. KeepUnused will not unload a scene even when empty. ForceUnload will unload a scene regardless of if clients are still connected to it. - /// - [System.NonSerialized] - public ServerUnloadMode Mode = ServerUnloadMode.UnloadUnused; - /// - /// True if scenes should be loaded using addressables. This field only exists for optional use so the user may know if their queue data is using addressables. - /// - public bool Addressables; - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadOptions.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadOptions.cs.meta deleted file mode 100644 index 68dcbd5..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadOptions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3de31d76de313bc49aefba61135fdffc -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadParams.cs b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadParams.cs deleted file mode 100644 index ca23c63..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadParams.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace FishNet.Managing.Scened -{ - /// - /// Additional user-crafted data which can be included in scene unload callbacks. - /// - public class UnloadParams - { - /// - /// Objects which are included in callbacks on the server when unloading a scene. Can be useful for including unique information about the scene, such as match id. These are not sent to clients; use ClientParams for this. - /// - [System.NonSerialized] - public object[] ServerParams = new object[0]; - /// - /// Bytes which are sent to clients during scene unloads. Can contain any information. - /// - public byte[] ClientParams = new byte[0]; - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadParams.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadParams.cs.meta deleted file mode 100644 index 90ef393..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadParams.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3bba3fbbe6ffbae4bb18d50c8c9b3b30 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadQueueData.cs b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadQueueData.cs deleted file mode 100644 index f53bee6..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadQueueData.cs +++ /dev/null @@ -1,53 +0,0 @@ -using FishNet.Connection; -using FishNet.Utility.Constant; -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo(UtilityConstants.GENERATED_ASSEMBLY_NAME)] -namespace FishNet.Managing.Scened -{ - - /// - /// Data generated when unloading a scene. - /// - public class UnloadQueueData - { - /// - /// Clients which receive this SceneQueueData. If Networked, all clients do. If Connections, only the specified Connections do. - /// - [System.NonSerialized] - public readonly SceneScopeType ScopeType; - /// - /// Connections to unload scenes for. Only valid on the server and when ScopeType is Connections. - /// - [System.NonSerialized] - public NetworkConnection[] Connections; - /// - /// SceneUnloadData to use. - /// - public SceneUnloadData SceneUnloadData = null; - /// - /// Current global scenes. - /// - public string[] GlobalScenes = new string[0]; - /// - /// True if to iterate this queue data as server. - /// - [System.NonSerialized] - public readonly bool AsServer; - - public UnloadQueueData() { } - internal UnloadQueueData(SceneScopeType scopeType, NetworkConnection[] conns, SceneUnloadData sceneUnloadData, string[] globalScenes, bool asServer) - { - ScopeType = scopeType; - Connections = conns; - SceneUnloadData = sceneUnloadData; - GlobalScenes = globalScenes; - AsServer = asServer; - } - - - } - - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadQueueData.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadQueueData.cs.meta deleted file mode 100644 index 782ce32..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/LoadUnloadDatas/UnloadQueueData.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ea9c20d60381ea74f974fb87a7e78297 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs b/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs deleted file mode 100644 index 72d525d..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs +++ /dev/null @@ -1,322 +0,0 @@ -using FishNet.Managing.Logging; -using FishNet.Serializing.Helping; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.SceneManagement; - -namespace FishNet.Managing.Scened -{ - /// - /// Extensions for SceneLookupData. - /// - internal static class SceneLookupDataExtensions - { - /// - /// Returns Names from SceneLookupData. - /// - /// - /// - public static string[] GetNames(this SceneLookupData[] datas) - { - string[] names = new string[datas.Length]; - for (int i = 0; i < datas.Length; i++) - names[i] = datas[i].Name; - - return names; - } - } - - /// - /// Data container for looking up, loading, or unloading a scene. - /// - public class SceneLookupData - { - /// - /// Handle of the scene. If value is 0, then handle is not used. - /// - public int Handle; - /// - /// Name of the scene. - /// - public string Name = string.Empty; - /// - /// Returns the scene name without a directory path should one exist. - /// - public string NameOnly => System.IO.Path.GetFileNameWithoutExtension(Name); - /// - /// Returns if this data is valid for use. - /// Being valid does not mean that the scene exist, rather that there is enough data to try and lookup a scene. - /// - public bool IsValid => (Name != string.Empty || Handle != 0); - - #region Const - /// - /// String to display when scene data is invalid. - /// - private const string INVALID_SCENE = "One or more scene information entries contain invalid data and have been skipped."; - #endregion - - /// - /// - /// - public SceneLookupData() { } - /// - /// - /// - /// Scene to generate from. - public SceneLookupData(Scene scene) - { - Handle = scene.handle; - Name = scene.name; - } - /// - /// - /// - /// Scene name to generate from. - public SceneLookupData(string name) - { - Name = name; - } - /// - /// - /// - /// Scene handle to generate from. - public SceneLookupData(int handle) - { - Handle = handle; - } - /// - /// - /// - /// Scene handle to generate from. - /// Name to generate from if handle is 0. - public SceneLookupData(int handle, string name) - { - Handle = handle; - Name = name; - } - - #region Comparers. - public static bool operator ==(SceneLookupData sldA, SceneLookupData sldB) - { - //One is null while the other is not. - if ((sldA is null) != (sldB is null)) - return false; - - /*If here both are either null or have value. */ - if (!(sldA is null)) - return sldA.Equals(sldB); - else if (!(sldB is null)) - return sldB.Equals(sldA); - - //Fall through indicates both are null. - return true; - } - - public static bool operator !=(SceneLookupData sldA, SceneLookupData sldB) - { - //One is null while the other is not. - if ((sldA is null) != (sldB is null)) - return true; - - /*If here both are either null or have value. */ - if (!(sldA is null)) - return !sldA.Equals(sldB); - else if (!(sldB is null)) - return !sldB.Equals(sldA); - - //Fall through indicates both are null. - return true; - } - - public bool Equals(SceneLookupData sld) - { - //Comparing instanced against null. - if (sld is null) - return false; - - //True if both handles are empty. - bool bothHandlesEmpty = ( - (this.Handle == 0) && - (sld.Handle == 0) - ); - - //If both have handles and they match. - if (!bothHandlesEmpty && sld.Handle == this.Handle) - return true; - //If neither have handles and name matches. - else if (bothHandlesEmpty && sld.Name == this.Name) - return true; - - //Fall through. - return false; - } - - public override int GetHashCode() - { - int hashCode = 2053068273; - hashCode = hashCode * -1521134295 + Handle.GetHashCode(); - hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Name); - return hashCode; - } - - public override bool Equals(object obj) - { - return base.Equals(obj); - } - - public override string ToString() - { - return base.ToString(); - } - #endregion - - #region CreateData. - /// - /// Returns a new SceneLookupData. - /// - /// Scene to create from. - /// - public static SceneLookupData CreateData(Scene scene) => new SceneLookupData(scene); - /// - /// Returns a new SceneLookupData. - /// - /// Scene name to create from. - /// - public static SceneLookupData CreateData(string name) => new SceneLookupData(name); - /// - /// Returns a new SceneLookupData. - /// - /// Scene handle to create from. - /// - public static SceneLookupData CreateData(int handle) => new SceneLookupData(handle); - /// - /// Returns a SceneLookupData collection. - /// - /// Scenes to create from. - /// - public static SceneLookupData[] CreateData(List scenes) => CreateData(scenes.ToArray()); - /// - /// Returns a SceneLookupData collection. - /// - /// Scene names to create from. - /// - public static SceneLookupData[] CreateData(List names) => CreateData(names.ToArray()); - /// - /// Returns a SceneLookupData collection. - /// - /// Scene handles to create from. - /// - public static SceneLookupData[] CreateData(List handles) => CreateData(handles.ToArray()); - /// - /// Returns a SceneLookupData collection. - /// - /// Scenes to create from. - /// - public static SceneLookupData[] CreateData(Scene[] scenes) - { - bool invalidFound = false; - List result = new List(); - foreach (Scene item in scenes) - { - if (!item.IsValid()) - { - invalidFound = true; - continue; - } - - result.Add(CreateData(item)); - } - - if (invalidFound) - NetworkManager.StaticLogWarning(INVALID_SCENE); - - return result.ToArray(); - } - /// - /// Returns a SceneLookupData collection. - /// - /// Scene names to create from. - /// - public static SceneLookupData[] CreateData(string[] names) - { - bool invalidFound = false; - List result = new List(); - foreach (string item in names) - { - if (string.IsNullOrEmpty(item)) - { - invalidFound = true; - continue; - } - - string nameOnly = System.IO.Path.GetFileNameWithoutExtension(item); - result.Add(CreateData(nameOnly)); - } - - if (invalidFound) - NetworkManager.StaticLogWarning(INVALID_SCENE); - - return result.ToArray(); - } - /// - /// Returns a SceneLookupData collection. - /// - /// Scene handles to create from. - /// - public static SceneLookupData[] CreateData(int[] handles) - { - bool invalidFound = false; - List result = new List(); - foreach (int item in handles) - { - if (item == 0) - { - invalidFound = true; - continue; - } - - result.Add(CreateData(item)); - } - - if (invalidFound) - NetworkManager.StaticLogWarning(INVALID_SCENE); - - return result.ToArray(); - } - #endregion - - /// - /// Returns the first scene found using Handle or Name, preferring Handle. - /// - /// - /// True if scene was found by handle. Handle is always checked first. - public Scene GetScene(out bool foundByHandle) - { - foundByHandle = false; - - if (Handle == 0 && string.IsNullOrEmpty(Name)) - { - NetworkManager.StaticLogWarning("Scene handle and name is unset; scene cannot be returned."); - return default; - } - - Scene result = default; - - //Lookup my handle. - if (Handle != 0) - { - result = SceneManager.GetScene(Handle); - if (result.handle != 0) - foundByHandle = true; - } - - //If couldnt find handle try by string. - if (!foundByHandle) - result = SceneManager.GetScene(NameOnly); - - return result; - } - - } -} diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs.meta deleted file mode 100644 index 2f035f7..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/SceneLookupData.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: df1ac9b164e75da46bc52f4dd4fe30ba -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs b/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs deleted file mode 100644 index 8bd1e10..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs +++ /dev/null @@ -1,2138 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing.Client; -using FishNet.Managing.Logging; -using FishNet.Managing.Server; -using FishNet.Object; -using FishNet.Serializing.Helping; -using FishNet.Transporting; -using FishNet.Utility; -using FishNet.Utility.Extension; -using FishNet.Utility.Performance; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnitySceneManager = UnityEngine.SceneManagement.SceneManager; - -namespace FishNet.Managing.Scened -{ - /// - /// Handles loading, unloading, and scene visibility for clients. - /// - [DisallowMultipleComponent] - [AddComponentMenu("FishNet/Manager/SceneManager")] - public sealed class SceneManager : MonoBehaviour - { - #region Types. - internal enum LightProbeUpdateType - { - Asynchronous = 0, - BlockThread = 1, - Off = 2, - } - #endregion - - #region Public. - /// - /// Called after the active scene has been set, immediately after scene loads. This will occur before NetworkBehaviour callbacks run for the scene's objects. - /// The boolean will indicate if the scene set active was specified by the user. - /// - public event Action OnActiveSceneSet; - /// - /// Called when a client loads initial scenes after connecting. Boolean will be true if asServer. This will invoke even if the SceneManager is not used when the client completes fully connecting to the server. - /// - public event Action OnClientLoadedStartScenes; - /// - /// Called when a scene change queue has begun. This will only call if a scene has succesfully begun to load or unload. The queue may process any number of scene events. For example: if a scene is told to unload while a load is still in progress, then the unload will be placed in the queue. - /// - public event Action OnQueueStart; - /// - /// Called when the scene queue is emptied. - /// - public event Action OnQueueEnd; - /// - /// Called when a scene load starts. - /// - public event Action OnLoadStart; - /// - /// Called when completion percentage changes while loading a scene. Value is between 0f and 1f, while 1f is 100% done. Can be used for custom progress bars when loading scenes. - /// - public event Action OnLoadPercentChange; - /// - /// Called when a scene load ends. - /// - public event Action OnLoadEnd; - /// - /// Called when a scene unload starts. - /// - public event Action OnUnloadStart; - /// - /// Called when a scene unload ends. - /// - public event Action OnUnloadEnd; - /// - /// Called when a client presence changes within a scene, before the server rebuilds observers. - /// - public event Action OnClientPresenceChangeStart; - /// - /// Called when a client presence changes within a scene, after the server rebuilds observers. - /// - public event Action OnClientPresenceChangeEnd; - /// - /// Connections within each scene. - /// - public Dictionary> SceneConnections { get; private set; } = new Dictionary>(); - /// - /// - /// - [Tooltip("Script to handle addressables loading and unloading. This field may be blank if addressables are not being used.")] - [SerializeField] - private SceneProcessorBase _sceneProcessor; - /// - /// Script to handle addressables loading and unloading. This field may be blank if addressables are not being used. - /// - /// - public SceneProcessorBase GetSceneProcessor() => _sceneProcessor; - /// - /// Sets the SceneProcessor to use. - /// - /// - public void SetSceneProcessor(SceneProcessorBase value) => _sceneProcessor = value; - #endregion - - #region Internal. - /// - /// Called after the active scene has been set, immediately after scene loads. - /// - internal event Action OnActiveSceneSetInternal; - #endregion - - #region Serialized. - /// - /// How to update light probes after loading or unloading scenes. - /// - [Tooltip("How to update light probes after loading or unloading scenes.")] - [SerializeField] - private LightProbeUpdateType _lightProbeUpdating = LightProbeUpdateType.Asynchronous; - /// - /// True to move objects visible to clientHost that are within an unloading scene. This ensures the objects are despawned on the client side rather than when the scene is destroyed. - /// - [Tooltip("True to move objects visible to clientHost that are within an unloading scene. This ensures the objects are despawned on the client side rather than when the scene is destroyed.")] - [SerializeField] - private bool _moveClientHostObjects = true; - /// - /// True to automatically set active scenes when loading and unloading scenes. - /// - [Tooltip("True to automatically set active scenes when loading and unloading scenes.")] - [SerializeField] - private bool _setActiveScene = true; - #endregion - - #region Private. - /// - /// NetworkManager for this script. - /// - private NetworkManager _networkManager; - /// - /// ServerManager for this script. - /// - private ServerManager _serverManager => _networkManager.ServerManager; - /// - /// ClientManager for this script. - /// - private ClientManager _clientManager => _networkManager.ClientManager; - /// - /// Scenes which are currently loaded as networked scenes. All players should have networked scenes loaded. - /// - private string[] _globalScenes = new string[0]; - /// - /// Lastest SceneLoadData for a global load. - /// - private SceneLoadData _globalSceneLoadData = new SceneLoadData(); - /// - /// Scenes to load or unload, in order. - /// - private List _queuedOperations = new List(); - /// - /// Scenes which must be manually unloaded, even when emptied. - /// - private HashSet _manualUnloadScenes = new HashSet(); - /// - /// Scene containing moved objects when changing single scene. On client this will contain all objects moved until the server destroys them. - /// The network only sends spawn messages once per-client, per server side scene load. If a scene load is performed only for specific connections - /// then the server is not resetting their single scene, but rather the single scene for those connections only. Because of this, any objects - /// which are to be moved will not receive a second respawn message, as they are never destroyed on server, only on client. - /// While on server only this scene contains objects being moved temporarily, before being moved to the new scene. - /// - private Scene _movedObjectsScene; - /// - /// Scene containing objects awaiting to be destroyed by the client-host. - /// This is required when unloading scenes where the client-host has visibility. - /// Otherwise the objects would become destroyed when the scene unloads on the server - /// which would cause missing networkobjects on clients when receiving despawn messages. - /// - private Scene _delayedDestroyScene; - /// - /// A scene to be set as the active scene where there are no global scenes. - /// This is used to prevent connection scenes and MovedObjectsScene from becoming the active scene. - /// - private Scene _fallbackActiveScene; - /// - /// Becomes true when when a scene first successfully begins to load or unload. Value is reset to false when the scene queue is emptied. - /// - private bool _sceneQueueStartInvoked; - /// - /// Objects being moved from MovedObjects scene to another. - /// - private List _movingObjects = new List(); - /// - /// How many scene load confirmations the server is expecting from a client. - /// Unloads do not need to be checked because server does not require confirmation for those. - /// This is used to prevent attacks. - /// - private Dictionary _pendingClientSceneChanges = new Dictionary(); - #endregion - - #region Consts. - /// - /// String to use when scene data used to load is invalid. - /// - private const string INVALID_SCENELOADDATA = "One or more datas in SceneLoadData are invalid.This generally occurs when calling this method without specifying any scenes or when data fields are null."; - /// - /// String to use when scene data used to unload is invalid. - /// - private const string INVALID_SCENEUNLOADDATA = "One or more datas in SceneLoadData are invalid.This generally occurs when calling this method without specifying any scenes or when data fields are null."; - #endregion - - #region Unity callbacks and initialization. - private void Awake() - { - UnitySceneManager.sceneUnloaded += SceneManager_SceneUnloaded; - if (_sceneProcessor == null) - _sceneProcessor = gameObject.AddComponent(); - _sceneProcessor.Initialize(this); - } - - private void Start() - { - //No need to unregister since managers are on the same object. - _networkManager.ServerManager.OnRemoteConnectionState += ServerManager_OnRemoteConnectionState; - _networkManager.ServerManager.OnServerConnectionState += ServerManager_OnServerConnectionState; - _clientManager.RegisterBroadcast(OnLoadScenes); - _clientManager.RegisterBroadcast(OnUnloadScenes); - _serverManager.RegisterBroadcast(OnClientLoadedScenes); - _serverManager.RegisterBroadcast(OnServerEmptyStartScenes); - _clientManager.RegisterBroadcast(OnClientEmptyStartScenes); - } - - private void OnDestroy() - { - UnitySceneManager.sceneUnloaded -= SceneManager_SceneUnloaded; - } - - /// - /// Called when the server connection state changes. - /// - private void ServerManager_OnServerConnectionState(ServerConnectionStateArgs obj) - { - //If no servers are started. - if (!_networkManager.ServerManager.AnyServerStarted()) - ResetValues(); - - } - /// - /// Resets as if first use. - /// - private void ResetValues() - { - SceneConnections.Clear(); - _globalScenes = new string[0]; - _globalSceneLoadData = new SceneLoadData(); - _queuedOperations.Clear(); - _manualUnloadScenes.Clear(); - _sceneQueueStartInvoked = false; - _movingObjects.Clear(); - } - - /// - /// Called when a connection state changes for a remote client. - /// - private void ServerManager_OnRemoteConnectionState(NetworkConnection arg1, RemoteConnectionStateArgs arg2) - { - if (arg2.ConnectionState == RemoteConnectionState.Stopped) - ClientDisconnected(arg1); - } - - /// - /// Initializes this script for use. - /// - /// - internal void InitializeOnce_Internal(NetworkManager manager) - { - _networkManager = manager; - } - - /// - /// Received when a scene is unloaded. - /// - /// - private void SceneManager_SceneUnloaded(Scene scene) - { - if (!_networkManager.IsServer) - return; - - /* Remove any unloaded scenes from local variables. This shouldn't - * be needed if the user properly utilizes this scene manager, - * but just incase, we don't want a memory leak. */ - SceneConnections.Remove(scene); - _manualUnloadScenes.Remove(scene); - RemoveFromGlobalScenes(scene); - } - #endregion - - #region Initial synchronizing. - /// - /// Invokes OnClientLoadedStartScenes if connection just loaded start scenes. - /// - /// - private void TryInvokeLoadedStartScenes(NetworkConnection connection, bool asServer) - { - if (connection.SetLoadedStartScenes(asServer)) - OnClientLoadedStartScenes?.Invoke(connection, asServer); - } - - /// - /// Called when authenitcator has concluded a result for a connection. Boolean is true if authentication passed, false if failed. This invokes before OnClientAuthenticated so FishNet may run operations on authenticated clients before user code does. - /// - /// - internal void OnClientAuthenticated(NetworkConnection connection) - { - AddPendingLoad(connection); - - //No global scenes to load. - if (_globalScenes.Length == 0) - { - /* Invoke that client had loaded the default scenes immediately, - * since there are no scenes to load. */ - //OnClientLoadedScenes(connection, new ClientScenesLoadedBroadcast()); - //Tell the client there are no scenes to load. - EmptyStartScenesBroadcast msg = new EmptyStartScenesBroadcast(); - connection.Broadcast(msg); - } - else - { - SceneLoadData sld = new SceneLoadData(_globalScenes); - sld.Params = _globalSceneLoadData.Params; - sld.Options = _globalSceneLoadData.Options; - sld.ReplaceScenes = _globalSceneLoadData.ReplaceScenes; - - LoadQueueData qd = new LoadQueueData(SceneScopeType.Global, Array.Empty(), sld, _globalScenes, false); - //Send message to load the networked scenes. - LoadScenesBroadcast msg = new LoadScenesBroadcast() - { - QueueData = qd - }; - - connection.Broadcast(msg, true); - } - } - - /// - /// Received on client when the server has no start scenes. - /// - private void OnClientEmptyStartScenes(EmptyStartScenesBroadcast msg) - { - TryInvokeLoadedStartScenes(_clientManager.Connection, false); - _clientManager.Broadcast(msg); - } - /// - /// Received on server when client confirms there are no start scenes. - /// - private void OnServerEmptyStartScenes(NetworkConnection conn, EmptyStartScenesBroadcast msg) - { - //Already received, shouldn't be happening again. - if (conn.LoadedStartScenes(true)) - conn.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"Received multiple EmptyStartSceneBroadcast from connectionId {conn.ClientId}. Connection will be kicked immediately."); - else - OnClientLoadedScenes(conn, new ClientScenesLoadedBroadcast()); - } - #endregion - - #region Player disconnect. - /// - /// Received when a player disconnects from the server. - /// - /// //finish. - private void ClientDisconnected(NetworkConnection conn) - { - _pendingClientSceneChanges.Remove(conn); - /* Remove connection from all scenes. While doing so check - * if scene should be unloaded provided there are no more clients - * in the scene, and it's set to automatically unload. This situation is a bit - * unique since a client disconnect happens outside the manager, so there - * isn't much code we can re-use to perform this operation. */ - List scenesToUnload = new List(); - //Current active scene. - Scene activeScene = UnitySceneManager.GetActiveScene(); - foreach (KeyValuePair> item in SceneConnections) - { - Scene scene = item.Key; - HashSet hs = item.Value; - - bool removed = hs.Remove(conn); - /* If no more observers for scene, not a global scene, and not to be manually unloaded - * then remove scene from SceneConnections and unload it. */ - if (removed && hs.Count == 0 && - !IsGlobalScene(scene) && !_manualUnloadScenes.Contains(scene) && - (scene != activeScene)) - scenesToUnload.Add(scene); - } - - //If scenes should be unloaded. - if (scenesToUnload.Count > 0) - { - foreach (Scene s in scenesToUnload) - SceneConnections.Remove(s); - SceneUnloadData sud = new SceneUnloadData(SceneLookupData.CreateData(scenesToUnload)); - UnloadConnectionScenes(Array.Empty(), sud); - } - } - #endregion - - #region Server received messages. - /// - /// Received on server when a client loads scenes. - /// - /// - /// - private void OnClientLoadedScenes(NetworkConnection conn, ClientScenesLoadedBroadcast msg) - { - int pendingLoads; - _pendingClientSceneChanges.TryGetValueIL2CPP(conn, out pendingLoads); - - //There's no loads or unloads pending, kick client. - if (pendingLoads == 0) - { - conn.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"Received excessive ClientScenesLoadedBroadcast from connectionId {conn.ClientId}. Connection will be kicked immediately."); - return; - } - //If there is a load pending then update pending count. - else - { - pendingLoads--; - if (pendingLoads == 0) - _pendingClientSceneChanges.Remove(conn); - else - _pendingClientSceneChanges[conn] = pendingLoads; - } - - if (!Comparers.IsDefault(msg)) - { - foreach (SceneLookupData item in msg.SceneLookupDatas) - { - Scene s = item.GetScene(out _); - if (s.IsValid()) - AddConnectionToScene(conn, s); - } - } - - TryInvokeLoadedStartScenes(conn, true); - } - #endregion - - #region Events. - /// - /// Checks if OnQueueStart should invoke, and if so invokes. - /// - private void TryInvokeOnQueueStart() - { - if (_sceneQueueStartInvoked) - return; - - _sceneQueueStartInvoked = true; - OnQueueStart?.Invoke(); - } - /// - /// Checks if OnQueueEnd should invoke, and if so invokes. - /// - private void TryInvokeOnQueueEnd() - { - if (!_sceneQueueStartInvoked) - return; - - _sceneQueueStartInvoked = false; - OnQueueEnd?.Invoke(); - } - /// - /// Invokes that a scene load has started. Only called when valid scenes will be loaded. - /// - /// - private void InvokeOnSceneLoadStart(LoadQueueData qd) - { - TryInvokeOnQueueStart(); - OnLoadStart?.Invoke(new SceneLoadStartEventArgs(qd)); - } - /// - /// Invokes that a scene load has ended. Only called after a valid scene has loaded. - /// - /// - private void InvokeOnSceneLoadEnd(LoadQueueData qd, List requestedLoadScenes, List loadedScenes, string[] unloadedSceneNames) - { - //Make new list to not destroy original data. - List skippedScenes = requestedLoadScenes.ToList(); - //Remove loaded scenes from requested scenes. - for (int i = 0; i < loadedScenes.Count; i++) - skippedScenes.Remove(loadedScenes[i].name); - - SceneLoadEndEventArgs args = new SceneLoadEndEventArgs(qd, skippedScenes.ToArray(), loadedScenes.ToArray(), unloadedSceneNames); - OnLoadEnd?.Invoke(args); - } - /// - /// Invokes that a scene unload has started. Only called when valid scenes will be unloaded. - /// - /// - private void InvokeOnSceneUnloadStart(UnloadQueueData sqd) - { - TryInvokeOnQueueStart(); - OnUnloadStart?.Invoke(new SceneUnloadStartEventArgs(sqd)); - } - /// - /// Invokes that a scene unload has ended. Only called after a valid scene has unloaded. - /// - /// - private void InvokeOnSceneUnloadEnd(UnloadQueueData sqd, List unloadedScenes, List newUnloadedScenes) - { - SceneUnloadEndEventArgs args = new SceneUnloadEndEventArgs(sqd, unloadedScenes, newUnloadedScenes); - OnUnloadEnd?.Invoke(args); - } - /// - /// Invokes when completion percentage changes while unloading or unloading a scene. Value is between 0f and 1f, while 1f is 100% done. - /// - /// - private void InvokeOnScenePercentChange(LoadQueueData qd, float value) - { - value = Mathf.Clamp(value, 0f, 1f); - SceneLoadPercentEventArgs slp = new SceneLoadPercentEventArgs(qd, value); - OnLoadPercentChange?.Invoke(slp); - } - #endregion - - #region Scene queue processing. - /// - /// Queues a load or unload operation and starts queue if needed. - /// - /// - private void QueueOperation(object data) - { - //Add to scene queue data. - _queuedOperations.Add(data); - /* If only one entry then scene operations are not currently in progress. - * Should there be more than one entry then scene operations are already - * occuring. The coroutine will automatically load in order. */ - - if (_queuedOperations.Count == 1) - StartCoroutine(__ProcessSceneQueue()); - } - /// - /// Processes queued scene operations. - /// - /// - /// - private IEnumerator __ProcessSceneQueue() - { - /* Queue start won't invoke unless a scene load or unload actually occurs. - * For example: if a scene is already loaded, and nothing needs to be loaded, - * queue start will not invoke. */ - - while (_queuedOperations.Count > 0) - { - //If a load scene. - if (_queuedOperations[0] is LoadQueueData) - yield return StartCoroutine(__LoadScenes()); - //If an unload scene. - else if (_queuedOperations[0] is UnloadQueueData) - yield return StartCoroutine(__UnloadScenes()); - - if (_queuedOperations.Count > 0) - _queuedOperations.RemoveAt(0); - } - - TryInvokeOnQueueEnd(); - } - #endregion - - #region LoadScenes - /// - /// Loads scenes on the server and for all clients. Future clients will automatically load these scenes. - /// - /// Data about which scenes to load. - public void LoadGlobalScenes(SceneLoadData sceneLoadData) - { - LoadGlobalScenes_Internal(sceneLoadData, _globalScenes, true); - } - /// - /// Adds to load scene queue. - /// - /// - /// - private void LoadGlobalScenes_Internal(SceneLoadData sceneLoadData, string[] globalScenes, bool asServer) - { - if (!CanExecute(asServer, true)) - return; - if (SceneDataInvalid(sceneLoadData, true)) - return; - if (sceneLoadData.Options.AllowStacking) - { - _networkManager.LogError($"Stacking scenes is not allowed with Global scenes."); - return; - } - - LoadQueueData lqd = new LoadQueueData(SceneScopeType.Global, Array.Empty(), sceneLoadData, globalScenes, asServer); - QueueOperation(lqd); - } - - /// - /// Loads scenes on server and tells connections to load them as well. Other connections will not load this scene. - /// - /// Connections to load scenes for. - /// Data about which scenes to load. - public void LoadConnectionScenes(NetworkConnection conn, SceneLoadData sceneLoadData) - { - LoadConnectionScenes(new NetworkConnection[] { conn }, sceneLoadData); - } - /// - /// Loads scenes on server and tells connections to load them as well. Other connections will not load this scene. - /// - /// Connections to load scenes for. - /// Data about which scenes to load. - public void LoadConnectionScenes(NetworkConnection[] conns, SceneLoadData sceneLoadData) - { - LoadConnectionScenes_Internal(conns, sceneLoadData, _globalScenes, true); - } - /// - /// Loads scenes on server without telling clients to load the scenes. - /// - /// Data about which scenes to load. - public void LoadConnectionScenes(SceneLoadData sceneLoadData) - { - LoadConnectionScenes_Internal(Array.Empty(), sceneLoadData, _globalScenes, true); - } - - /// - /// Adds to load scene queue. - /// - /// - /// - private void LoadConnectionScenes_Internal(NetworkConnection[] conns, SceneLoadData sceneLoadData, string[] globalScenes, bool asServer) - { - if (!CanExecute(asServer, true)) - return; - if (SceneDataInvalid(sceneLoadData, true)) - return; - - LoadQueueData lqd = new LoadQueueData(SceneScopeType.Connections, conns, sceneLoadData, globalScenes, asServer); - QueueOperation(lqd); - } - - /// - /// Returns if a NetworkObject can be moved. - /// - /// - /// - private bool CanMoveNetworkObject(NetworkObject nob, bool warn) - { - //Null. - if (nob == null) - return WarnAndReturnFalse($"NetworkObject is null."); - //Not networked. - if (!nob.IsNetworked) - return WarnAndReturnFalse($"NetworkObject {nob.name} cannot be moved as it is not networked."); - //Not spawned. - if (!nob.IsSpawned) - return WarnAndReturnFalse($"NetworkObject {nob.name} canot be moved as it is not spawned."); - //SceneObject. - if (nob.IsSceneObject) - return WarnAndReturnFalse($"NetworkObject {nob.name} cannot be moved as it is a scene object."); - //Not root. - if (nob.transform.parent != null) - return WarnAndReturnFalse($"NetworkObject {nob.name} cannot be moved because it is not the root object. Unity can only move root objects between scenes."); - //In DDOL and IsGlobal. - if (nob.IsGlobal && (nob.gameObject.scene.name == DDOLFinder.GetDDOL().gameObject.scene.name)) - return WarnAndReturnFalse("NetworkObject {nob.name} cannot be moved because it is global. Global objects must remain in the DontDestroyOnLoad scene."); - - //Fall through success. - return true; - - bool WarnAndReturnFalse(string msg) - { - if (warn) - _networkManager.LogWarning(msg); - return false; - } - } - - /// - /// Loads a connection scene queue data. This behaves just like a networked scene load except it sends only to the specified connections, and it always loads as an additive scene on server. - /// - /// - private IEnumerator __LoadScenes() - { - LoadQueueData data = _queuedOperations[0] as LoadQueueData; - SceneLoadData sceneLoadData = data.SceneLoadData; - //True if running as server. - bool asServer = data.AsServer; - //True if running as client, while network server is active. - bool asHost = (!asServer && _networkManager.IsServer); - - //If connection went inactive. - if (!ConnectionActive(asServer)) - yield break; - - /* Scene sanity checks. */ - if (sceneLoadData.SceneLookupDatas.Length == 0) - { - _networkManager.LogWarning($"No scenes specified to load."); - yield break; - } - - //True if replacing scenes with specified ones. - ReplaceOption replaceScenes = sceneLoadData.ReplaceScenes; - - //May be unset if on server, this is fine. - NetworkConnection localConnection = _networkManager.ClientManager.Connection; - /* Immediately set new global scenes. If on client this is whatever - * server passes in. This should be set even if scope type - * is not global because clients might get a connection scene first. - */ - if (!asServer) - { - if (!asHost) - _globalScenes = data.GlobalScenes; - } - /* However, if server, then only update global scenes if scope - * is global. */ - else if (asServer && data.ScopeType == SceneScopeType.Global) - { - _globalSceneLoadData = sceneLoadData; - string[] names = sceneLoadData.SceneLookupDatas.GetNames(); - //If replacing. - if (replaceScenes != ReplaceOption.None) - { - _globalScenes = names; - } - //Add onto. - else - { - int index = _globalScenes.Length; - Array.Resize(ref _globalScenes, _globalScenes.Length + names.Length); - Array.Copy(names, 0, _globalScenes, index, names.Length); - } - - data.GlobalScenes = _globalScenes; - } - - - /* Scene queue data scenes. - * All scenes in the scene queue data whether they will be loaded or not. */ - List requestedLoadSceneNames = new List(); - List requestedLoadSceneHandles = new List(); - - /* Make a null filled array. This will be populated - * using loaded scenes, or already loaded (eg cannot be loaded) scenes. */ - SceneLookupData[] broadcastLookupDatas = new SceneLookupData[sceneLoadData.SceneLookupDatas.Length]; - - /* LoadableScenes and SceneReferenceDatas. - /* Will contain scenes which may be loaded. - * Scenes might not be added to loadableScenes - * if for example loadOnlyUnloaded is true and - * the scene is already loaded. */ - List loadableScenes = new List(); - for (int i = 0; i < sceneLoadData.SceneLookupDatas.Length; i++) - { - SceneLookupData lookupData = sceneLoadData.SceneLookupDatas[i]; - //Scene to load. - bool byHandle; - Scene s = lookupData.GetScene(out byHandle); - //If found then add it to requestedLoadScenes. - if (s.IsValid()) - { - requestedLoadSceneNames.Add(s.name); - if (byHandle) - requestedLoadSceneHandles.Add(s.handle); - } - - if (CanLoadScene(data, lookupData)) - { - //Don't load if as host, server side would have loaded already. - if (!asHost) - loadableScenes.Add(lookupData); - } - //Only the server needs to find scene handles to send to client. Client will send these back to the server. - else if (asServer) - { - /* If here then scene cannot be loaded, which - * can only happen if the scene already exists. - * Find the scene using sld and set to datas. */ - /* Set at the index of i. This way should the current - * SLD not be the first scene it won't fill the - * first slot in broadcastLookupDatas. This is important - * because the first slot is used for the single scene - * when using replace scenes. */ - broadcastLookupDatas[i] = new SceneLookupData(s); - } - } - - /* Move identities - * to holder scene to preserve them. - * Required if a single scene is specified. Cannot rely on - * loadSingleScene since it is only true if the single scene - * must be loaded, which may be false if it's already loaded on - * the server. */ - //Do not run if running as client, and server is active. This would have already run as server. - if (!asHost) - { - foreach (NetworkObject nob in sceneLoadData.MovedNetworkObjects) - { - //NetworkObject might be null if client lost observation of it. - if (nob != null && CanMoveNetworkObject(nob, true)) - UnitySceneManager.MoveGameObjectToScene(nob.gameObject, GetMovedObjectsScene()); - } - } - - //Connection scenes handles prior to ConnectionScenes being modified. - List connectionScenesHandlesCached = new List(); - //If replacing scenes. - if (replaceScenes != ReplaceOption.None) - { - /* Resetting SceneConnections. */ - /* If server and replacing scenes. - * It's important to run this AFTER moving MovedNetworkObjects - * so that they are no longer in the scenes they are leaving. Otherwise - * the scene condition would pick them up as still in the leaving scene. */ - if (asServer) - { - Scene[] sceneConnectionsKeys = SceneConnections.Keys.ToArray(); - for (int i = 0; i < sceneConnectionsKeys.Length; i++) - connectionScenesHandlesCached.Add(sceneConnectionsKeys[i].handle); - - //If global then remove all connections from all scenes. - if (data.ScopeType == SceneScopeType.Global) - { - foreach (Scene s in sceneConnectionsKeys) - RemoveAllConnectionsFromScene(s); - } - //Connections. - else if (data.ScopeType == SceneScopeType.Connections) - { - RemoveConnectionsFromNonGlobalScenes(data.Connections); - } - } - //As client set scenes id cache to local connection scenes. - else - { - foreach (Scene s in _networkManager.ClientManager.Connection.Scenes) - connectionScenesHandlesCached.Add(s.handle); - } - } - - - /* Scene unloading if replacing scenes. - * - * Unload all scenes except MovedObjectsHolder. Also don't - * unload GlobalScenes if loading as connection. */ - List unloadableScenes = new List(); - //Do not run if running as client, and server is active. This would have already run as server. - if ((replaceScenes != ReplaceOption.None) && !asHost) - { - //See what scenes can be unloaded based on replace options. - for (int i = 0; i < UnitySceneManager.sceneCount; i++) - { - Scene s = UnitySceneManager.GetSceneAt(i); - //MovedObjectsScene will never be unloaded. - if (s == GetMovedObjectsScene()) - continue; - /* Scene is in one of the scenes being loaded. - * This can occur when trying to load additional clients - * into an existing scene. */ - if (requestedLoadSceneNames.Contains(s.name)) - continue; - //Same as above but using handles. - if (requestedLoadSceneHandles.Contains(s.handle)) - continue; - /* Cannot unload global scenes. If - * replace scenes was used for a global - * load then global scenes would have been reset - * before this. */ - if (IsGlobalScene(s)) - continue; - //If scene must be manually unloaded then it cannot be unloaded here. - if (_manualUnloadScenes.Contains(s)) - continue; - - bool inScenesCache = connectionScenesHandlesCached.Contains(s.handle); - HashSet conns; - bool inScenesCurrent = SceneConnections.ContainsKey(s); - //If was in scenes previously but isnt now then no connections reside in the scene. - if (inScenesCache && !inScenesCurrent) - { - //Intentionally left blank. - } - //If still in cache see if any connections exist. - else if (SceneConnections.TryGetValueIL2CPP(s, out conns)) - { - //Still has clients in scene. - if (conns != null && conns.Count > 0) - continue; - } - //An offline scene. - else - { - //If not replacing all scenes then skip offline scenes. - if (replaceScenes != ReplaceOption.All) - continue; - } - - unloadableScenes.Add(s); - } - } - - /* Start event. */ - if (unloadableScenes.Count > 0 || loadableScenes.Count > 0) - { - InvokeOnSceneLoadStart(data); - _sceneProcessor.LoadStart(data); - } - //Unloaded scenes by name. Only used for information within callbacks. - string[] unloadedNames = new string[unloadableScenes.Count]; - for (int i = 0; i < unloadableScenes.Count; i++) - unloadedNames[i] = unloadableScenes[i].name; - /* Before unloading if !asServer and !asHost and replacing scenes - * then move all non scene networked objects to the moved - * objects holder. Otherwise network objects would get destroyed - * on the scene change and never respawned if server doesn't - * have a reason to update visibility. */ - if (!data.AsServer && !asHost && (replaceScenes != ReplaceOption.None)) - { - Scene s = GetMovedObjectsScene(); - foreach (NetworkObject nob in _networkManager.ClientManager.Objects.Spawned.Values) - { - if (CanMoveNetworkObject(nob, false)) - UnitySceneManager.MoveGameObjectToScene(nob.gameObject, s); - } - } - /* Unloading scenes. */ - _sceneProcessor.UnloadStart(data); - for (int i = 0; i < unloadableScenes.Count; i++) - { - MoveClientHostObjects(unloadableScenes[i], asServer); - //Unload one at a time. - _sceneProcessor.BeginUnloadAsync(unloadableScenes[i]); - while (!_sceneProcessor.IsPercentComplete()) - yield return null; - } - _sceneProcessor.UnloadEnd(data); - - //Scenes loaded. - List loadedScenes = new List(); - /* Scene loading. - /* Use additive to not thread lock server. */ - for (int i = 0; i < loadableScenes.Count; i++) - { - //Start load async and wait for it to finish. - LoadSceneParameters loadSceneParameters = new LoadSceneParameters() - { - loadSceneMode = LoadSceneMode.Additive, - localPhysicsMode = sceneLoadData.Options.LocalPhysics - }; - - /* How much percentage each scene load can be worth - * at maximum completion. EG: if there are two scenes - * 1f / 2f is 0.5f. */ - float maximumIndexWorth = (1f / (float)loadableScenes.Count); - - _sceneProcessor.BeginLoadAsync(loadableScenes[i].Name, loadSceneParameters); - while (!_sceneProcessor.IsPercentComplete()) - { - float percent = _sceneProcessor.GetPercentComplete(); - InvokePercentageChange(i, maximumIndexWorth, percent); - yield return null; - } - - //Invokes OnScenePercentChange with progress. - void InvokePercentageChange(int index, float maximumWorth, float currentScenePercent) - { - /* Total percent will be how much percentage is complete - * in total. Initialize it with a value based on how many - * scenes are already fully loaded. */ - float totalPercent = (index * maximumWorth); - //Add this scenes progress onto total percent. - totalPercent += Mathf.Lerp(0f, maximumWorth, currentScenePercent); - //Dispatch with total percent. - InvokeOnScenePercentChange(data, totalPercent); - } - - //Add to loaded scenes. - Scene loaded = UnitySceneManager.GetSceneAt(UnitySceneManager.sceneCount - 1); - loadedScenes.Add(loaded); - _sceneProcessor.AddLoadedScene(loaded); - } - //When all scenes are loaded invoke with 100% done. - InvokeOnScenePercentChange(data, 1f); - - /* Add to ManuallyUnloadScenes. */ - if (data.AsServer && !sceneLoadData.Options.AutomaticallyUnload) - { - foreach (Scene s in loadedScenes) - _manualUnloadScenes.Add(s); - } - /* Move identities to first scene. */ - if (!asHost) - { - //Find the first valid scene to move objects to. - Scene firstValidScene = default; - //If to stack scenes. - if (sceneLoadData.Options.AllowStacking) - { - Scene firstScene = sceneLoadData.GetFirstLookupScene(); - /* If the first lookup data contains a handle and the scene - * is found for that handle then use that as the moved to scene. - * Nobs always move to the first specified scene. */ - if (sceneLoadData.SceneLookupDatas[0].Handle != 0 && !string.IsNullOrEmpty(firstScene.name)) - { - firstValidScene = firstScene; - } - //If handle is not specified then used the last scene that has the same name as the first lookupData. - else - { - Scene lastSameSceneName = default; - for (int i = 0; i < UnitySceneManager.sceneCount; i++) - { - Scene s = UnitySceneManager.GetSceneAt(i); - if (s.name == firstScene.name) - lastSameSceneName = s; - } - - /* Shouldn't be possible since the scene will always exist either by - * just being loaded or already loaded. */ - if (string.IsNullOrEmpty(lastSameSceneName.name)) - _networkManager.LogError($"Scene {sceneLoadData.SceneLookupDatas[0].Name} could not be found in loaded scenes."); - else - firstValidScene = lastSameSceneName; - } - } - //Not stacking. - else - { - firstValidScene = sceneLoadData.GetFirstLookupScene(); - //If not found by look then try firstloaded. - if (string.IsNullOrEmpty(firstValidScene.name)) - firstValidScene = GetFirstLoadedScene(); - } - - //Gets first scene loaded this method call. - Scene GetFirstLoadedScene() - { - if (loadedScenes.Count > 0) - return loadedScenes[0]; - else - return default; - } - - //If firstValidScene is still invalid then throw. - if (string.IsNullOrEmpty(firstValidScene.name)) - { - _networkManager.LogError($"Unable to move objects to a new scene because new scene lookup has failed."); - } - //Move objects from movedobejctsscene to first valid scene. - else - { - Scene s = GetMovedObjectsScene(); - s.GetRootGameObjects(_movingObjects); - - foreach (GameObject go in _movingObjects) - UnitySceneManager.MoveGameObjectToScene(go, firstValidScene); - } - } - - _sceneProcessor.ActivateLoadedScenes(); - //Wait until everything is loaded (done). - yield return _sceneProcessor.AsyncsIsDone(); - _sceneProcessor.LoadEnd(data); - - /* Wait until loadedScenes are all marked as done. - * This is an extra precautionary step because on some devices - * the AsyncIsDone returns true before scenes are actually loaded. */ - bool allScenesLoaded = true; - do - { - foreach (Scene s in loadedScenes) - { - if (!s.isLoaded) - { - allScenesLoaded = false; - break; - } - } - yield return null; - } while (!allScenesLoaded); - - SetActiveScene_Local(); - void SetActiveScene_Local() - { - bool byUser; - Scene preferredActiveScene = GetUserPreferredActiveScene(sceneLoadData.PreferredActiveScene, out byUser); - //If preferred still is not set then try to figure it out. - if (!preferredActiveScene.IsValid()) - { - /* Populate preferred scene to first loaded if replacing - * scenes for connection. Does not need to be set for - * global because when a global exist it's always set - * as the active scene. - * - * Do not set preferred scene if server as this could cause - * problems when stacking or connection specific scenes. Let the - * user make those changes. */ - if (sceneLoadData.ReplaceScenes != ReplaceOption.None && data.ScopeType == SceneScopeType.Connections && !_networkManager.IsServer) - preferredActiveScene = sceneLoadData.GetFirstLookupScene(); - } - - SetActiveScene(preferredActiveScene, byUser); - } - - //Only the server needs to find scene handles to send to client. Client will send these back to the server. - if (asServer) - { - //Populate broadcastLookupDatas with any loaded scenes. - foreach (Scene s in loadedScenes) - { - SetInFirstNullIndex(s); - - //Sets scene in the first null index of broadcastLookupDatas. - void SetInFirstNullIndex(Scene scene) - { - for (int i = 0; i < broadcastLookupDatas.Length; i++) - { - if (broadcastLookupDatas[i] == null) - { - broadcastLookupDatas[i] = new SceneLookupData(scene); - return; - } - } - - //If here there are no null entries. - _networkManager.LogError($"Cannot add scene to broadcastLookupDatas, collection is full."); - } - } - } - - /* If running as server and server is - * active then send scene changes to client. - * Making sure server is still active should it maybe - * have dropped during scene loading. */ - if (data.AsServer && _networkManager.IsServer) - { - //Tell clients to load same scenes. - LoadScenesBroadcast msg = new LoadScenesBroadcast() - { - QueueData = data - }; - //Replace scene lookup datas with ones intended to broadcast to client. - msg.QueueData.SceneLoadData.SceneLookupDatas = broadcastLookupDatas; - //If networked scope then send to all. - if (data.ScopeType == SceneScopeType.Global) - { - NetworkConnection[] conns = _serverManager.Clients.Values.ToArray(); - AddPendingLoad(conns); - _serverManager.Broadcast(msg, true); - } - //If connections scope then only send to connections. - else if (data.ScopeType == SceneScopeType.Connections) - { - AddPendingLoad(data.Connections); - for (int i = 0; i < data.Connections.Length; i++) - { - if (data.Connections[i].Authenticated) - data.Connections[i].Broadcast(msg, true); - } - } - } - /* If running as client then send a message - * to the server to tell them the scene was loaded. - * This allows the server to add the client - * to the scene for checkers. */ - else if (!data.AsServer && _networkManager.IsClient) - { - ClientScenesLoadedBroadcast msg = new ClientScenesLoadedBroadcast() - { - SceneLookupDatas = sceneLoadData.SceneLookupDatas - }; - _clientManager.Broadcast(msg); - - //Remove from old scenes. - foreach (Scene item in unloadableScenes) - { - if (item.IsValid()) - localConnection.RemoveFromScene(item); - } - //Add local client to scenes. - foreach (Scene item in loadedScenes) - localConnection.AddToScene(item); - } - - InvokeOnSceneLoadEnd(data, requestedLoadSceneNames, loadedScenes, unloadedNames); - } - - /// - /// Received on client when connection scenes must be loaded. - /// - /// - /// - private void OnLoadScenes(LoadScenesBroadcast msg) - { - //Null data is sent by the server when there are no start scenes to load. - if (msg.QueueData == null) - { - TryInvokeLoadedStartScenes(_clientManager.Connection, false); - return; - } - - LoadQueueData qd = msg.QueueData; - if (qd.ScopeType == SceneScopeType.Global) - LoadGlobalScenes_Internal(qd.SceneLoadData, qd.GlobalScenes, false); - else - LoadConnectionScenes_Internal(Array.Empty(), qd.SceneLoadData, qd.GlobalScenes, false); - } - #endregion - - #region UnloadScenes. - /// - /// Unloads scenes on the server and for all clients. - /// - /// Data about which scenes to unload. - public void UnloadGlobalScenes(SceneUnloadData sceneUnloadData) - { - if (!CanExecute(true, true)) - return; - - UnloadGlobalScenes_Internal(sceneUnloadData, _globalScenes, true); - } - /// - /// - /// - /// - /// - /// - /// - private void UnloadGlobalScenes_Internal(SceneUnloadData sceneUnloadData, string[] globalScenes, bool asServer) - { - UnloadQueueData uqd = new UnloadQueueData(SceneScopeType.Global, Array.Empty(), sceneUnloadData, globalScenes, asServer); - QueueOperation(uqd); - } - - - /// - /// Unloads scenes on server and tells a connection to unload them as well. Other connections will not unload this scene. - /// - /// Connection to unload scenes for. - /// Data about which scenes to unload. - public void UnloadConnectionScenes(NetworkConnection connection, SceneUnloadData sceneUnloadData) - { - UnloadConnectionScenes(new NetworkConnection[] { connection }, sceneUnloadData); - } - /// - /// Unloads scenes on server and tells connections to unload them as well. Other connections will not unload this scene. - /// - /// Connections to unload scenes for. - /// Data about which scenes to unload. - public void UnloadConnectionScenes(NetworkConnection[] connections, SceneUnloadData sceneUnloadData) - { - UnloadConnectionScenes_Internal(connections, sceneUnloadData, _globalScenes, true); - } - - /// - /// Unloads scenes on server without telling any connections to unload them. - /// - /// Data about which scenes to unload. - public void UnloadConnectionScenes(SceneUnloadData sceneUnloadData) - { - UnloadConnectionScenes_Internal(Array.Empty(), sceneUnloadData, _globalScenes, true); - } - /// - /// Unloads scenes for connections. - /// - /// - /// - /// - /// - private void UnloadConnectionScenes_Internal(NetworkConnection[] connections, SceneUnloadData sceneUnloadData, string[] globalScenes, bool asServer) - { - if (!CanExecute(asServer, true)) - return; - if (SceneDataInvalid(sceneUnloadData, true)) - return; - - UnloadQueueData uqd = new UnloadQueueData(SceneScopeType.Connections, connections, sceneUnloadData, globalScenes, asServer); - QueueOperation(uqd); - } - /// - /// Loads scenes within QueuedSceneLoads. - /// - /// - private IEnumerator __UnloadScenes() - { - UnloadQueueData data = _queuedOperations[0] as UnloadQueueData; - SceneUnloadData sceneUnloadData = data.SceneUnloadData; - - //If connection went inactive. - if (!ConnectionActive(data.AsServer)) - yield break; - - /* Some actions should not run as client if server is also active. - * This is to keep things from running twice. */ - bool asClientHost = (!data.AsServer && _networkManager.IsServer); - ///True if running asServer. - bool asServer = data.AsServer; - - //Get scenes to unload. - Scene[] scenes = GetScenes(sceneUnloadData.SceneLookupDatas); - /* No scenes found. Only run this if not asHost. - * While asHost scenes will possibly not exist because - * server side has already unloaded them. But rest of - * the unload should continue. */ - if (scenes.Length == 0 && !asClientHost) - { - _networkManager.LogWarning($"No scenes were found to unload."); - yield break; - } - - /* Remove from global scenes - * if server and scope is global. - * All passed in scenes should be removed from global - * regardless of if they're valid or not. If they are invalid, - * then they shouldn't be in global to begin with. */ - if (asServer && data.ScopeType == SceneScopeType.Global) - { - RemoveFromGlobalScenes(sceneUnloadData.SceneLookupDatas); - //Update queue data. - data.GlobalScenes = _globalScenes; - } - - /* Remove connections. */ - if (asServer) - { - foreach (Scene s in scenes) - { - //If global then remove all connections. - if (data.ScopeType == SceneScopeType.Global) - RemoveAllConnectionsFromScene(s); - //Connections. - else if (data.ScopeType == SceneScopeType.Connections) - RemoveConnectionsFromScene(data.Connections, s); - } - } - - - /* This will contain all scenes which can be unloaded. - * The collection will be modified through various checks. */ - List unloadableScenes = scenes.ToList(); - /* Unloaded scenes manually created to overcome - * the empty names in Scene structs after Unity unloads - * a scene. */ - List unloadedScenes = new List(); - /* If asServer and KeepUnused then clear all unloadables. - * The clients will still unload the scenes. */ - if ((asServer || asClientHost) && sceneUnloadData.Options.Mode == UnloadOptions.ServerUnloadMode.KeepUnused) - unloadableScenes.Clear(); - /* Check to remove global scenes unloadableScenes. - * This will need to be done if scenes are being unloaded - * for connections. Global scenes cannot be unloaded as - * connection. */ - if (data.ScopeType == SceneScopeType.Connections) - RemoveGlobalScenes(unloadableScenes); - //If set to unload unused only. - if (sceneUnloadData.Options.Mode == UnloadOptions.ServerUnloadMode.UnloadUnused) - RemoveOccupiedScenes(unloadableScenes); - - //If there are scenes to unload. - if (unloadableScenes.Count > 0) - { - InvokeOnSceneUnloadStart(data); - _sceneProcessor.UnloadStart(data); - - //Begin unloading. - foreach (Scene s in unloadableScenes) - { - unloadedScenes.Add(new UnloadedScene(s)); - MoveClientHostObjects(s, asServer); - /* Remove from manualUnloadedScenes. - * Scene may not be in this collection - * but removing is one call vs checking - * then removing. */ - _manualUnloadScenes.Remove(s); - - _sceneProcessor.BeginUnloadAsync(s); - while (!_sceneProcessor.IsPercentComplete()) - yield return null; - } - - _sceneProcessor.UnloadEnd(data); - } - - /* Must yield after sceneProcessor handles things. - * This is a Unity bug of sorts. I'm not entirely sure what - * is happening, but without the yield it seems as though - * the processor logic doesn't complete. This doesn't make much - * sense given unity is supposed to be single threaded. Must be - * something to do with the coroutine. */ - yield return null; - - bool byUser; - Scene preferredActiveScene = GetUserPreferredActiveScene(sceneUnloadData.PreferredActiveScene, out byUser); - SetActiveScene(preferredActiveScene, byUser); - - /* If running as server then make sure server - * is still active after the unloads. If so - * send out unloads to clients. */ - if (asServer && ConnectionActive(true)) - { - //Tell clients to unload same scenes. - UnloadScenesBroadcast msg = new UnloadScenesBroadcast() - { - QueueData = data - }; - //Global. - if (data.ScopeType == SceneScopeType.Global) - { - _serverManager.Broadcast(msg, true); - } - //Connections. - else if (data.ScopeType == SceneScopeType.Connections) - { - if (data.Connections != null) - { - for (int i = 0; i < data.Connections.Length; i++) - { - if (data.Connections[i] != null) - data.Connections[i].Broadcast(msg, true); - } - } - } - } - else if (!asServer) - { - NetworkConnection localConnection = _networkManager.ClientManager.Connection; - //Remove from old scenes. - foreach (Scene item in unloadableScenes) - { - if (item.IsValid()) - localConnection.RemoveFromScene(item); - } - } - - InvokeOnSceneUnloadEnd(data, unloadableScenes, unloadedScenes); - } - - - /// - /// Received on clients when networked scenes must be unloaded. - /// - /// - /// - private void OnUnloadScenes(UnloadScenesBroadcast msg) - { - UnloadQueueData qd = msg.QueueData; - if (qd.ScopeType == SceneScopeType.Global) - UnloadGlobalScenes_Internal(qd.SceneUnloadData, qd.GlobalScenes, false); - else - UnloadConnectionScenes_Internal(Array.Empty(), qd.SceneUnloadData, qd.GlobalScenes, false); - } - #endregion - - /// - /// Move objects visible to clientHost that are within an unloading scene.This ensures the objects are despawned on the client side rather than when the scene is destroyed. - /// - /// - private void MoveClientHostObjects(Scene scene, bool asServer) - { - if (!_moveClientHostObjects) - return; - /* The asServer isn't really needed. I could only call - * this method when asServer is true. But for the sake - * of preventing user-error (me being the user this time) - * I've included it into the parameters. */ - if (!asServer) - return; - //Don't need to perform if not host. - if (!_networkManager.IsClient) - return; - - NetworkConnection clientConn = _networkManager.ClientManager.Connection; - /* It would be nice to see if the client wasn't even in the scene - * here using SceneConnections but it's possible that the scene had been - * wiped from SceneConnections earlier depending on how scenes are - * loaded or unloaded. Instead we must iterate through spawned objects. */ - - ListCache movingNobs = ListCaches.GetNetworkObjectCache(); - /* Rather than a get all networkobjects in scene - * let's iterate the spawned objects instead. I imagine - * in most scenarios iterating spawned would be faster. - * That's a long one! */ - foreach (NetworkObject nob in _networkManager.ServerManager.Objects.Spawned.Values) - { - //Not in the scene being destroyed. - if (nob.gameObject.scene != scene) - continue; - //ClientHost doesn't have visibility. - if (!nob.Observers.Contains(clientConn)) - continue; - //Cannot move if not root. - if (nob.transform.root != null) - continue; - - /* If here nob is in the same being - * destroyed and clientHost has visiblity. */ - movingNobs.AddValue(nob); - } - - int count = movingNobs.Written; - if (count > 0) - { - Scene moveScene = GetDelayedDestroyScene(); - List collection = movingNobs.Collection; - - for (int i = 0; i < count; i++) - { - NetworkObject nob = collection[i]; - /* Force as not a scene object - * so that it becomes destroyed - * rather than disabled. */ - nob.ClearRuntimeSceneObject(); - /* If the object is already being despawned then - *just disable and move it. Otherwise despawn it - * on the server then move it. */ - //Not deinitializing, despawn it then. - if (!nob.IsDeinitializing) - nob.Despawn(); - else - nob.gameObject.SetActive(false); - - UnitySceneManager.MoveGameObjectToScene(nob.gameObject, moveScene); - } - } - ListCaches.StoreCache(movingNobs); - } - - /// - /// Returns if a connection is in a scene using SceneConnections. - /// - /// - /// - /// - internal bool InSceneConnections(NetworkConnection conn, Scene scene) - { - if (!SceneConnections.TryGetValueIL2CPP(scene, out HashSet hs)) - return false; - else - return hs.Contains(conn); - } - - /// - /// Adds the owner of nob to the gameObjects scene if there are no global scenes. - /// - public void AddOwnerToDefaultScene(NetworkObject nob) - { - //No owner. - if (!nob.Owner.IsValid) - { - _networkManager.LogWarning($"NetworkObject {nob.name} does not have an owner."); - return; - } - //Won't add to default if there are globals. - if (_globalScenes != null && _globalScenes.Length > 0) - return; - - AddConnectionToScene(nob.Owner, nob.gameObject.scene); - } - - /// - /// Adds a connection to a scene. This will always be called one connection at a time because connections are only added after they invidually validate loading the scene. - /// Exposed for power users, use caution. - /// - /// Connection to add. - /// Scene to add the connection to. - public void AddConnectionToScene(NetworkConnection conn, Scene scene) - { - HashSet hs; - //Scene doesn't have any connections yet. - bool inSceneConnections = SceneConnections.TryGetValueIL2CPP(scene, out hs); - if (!inSceneConnections) - hs = new HashSet(); - - bool added = hs.Add(conn); - if (added) - { - conn.AddToScene(scene); - - //If not yet added to scene connections. - if (!inSceneConnections) - SceneConnections[scene] = hs; - - NetworkConnection[] arrayConn = new NetworkConnection[] { conn }; - InvokeClientPresenceChange(scene, arrayConn, true, true); - RebuildObservers(arrayConn.ToArray()); - InvokeClientPresenceChange(scene, arrayConn, true, false); - - /* Also need to rebuild all networkobjects - * for connection so other players can - * see them. */ - RebuildObservers(conn.Objects.ToArray()); - } - } - - - /// - /// Removes connections from any scene which is not global. - /// Exposed for power users, use caution. - /// - /// - public void RemoveConnectionsFromNonGlobalScenes(NetworkConnection[] conns) - { - List removedScenes = new List(); - - foreach (KeyValuePair> item in SceneConnections) - { - Scene scene = item.Key; - //Cannot remove from globla scenes. - if (IsGlobalScene(scene)) - continue; - - HashSet hs = item.Value; - List connectionsRemoved = new List(); - //Remove every connection from the scene. - foreach (NetworkConnection c in conns) - { - bool removed = hs.Remove(c); - if (removed) - { - c.RemoveFromScene(scene); - connectionsRemoved.Add(c); - } - } - - //If hashset is empty then remove scene from SceneConnections. - if (hs.Count == 0) - removedScenes.Add(scene); - - if (connectionsRemoved.Count > 0) - { - NetworkConnection[] connectionsRemovedArray = connectionsRemoved.ToArray(); - InvokeClientPresenceChange(scene, connectionsRemovedArray, false, true); - RebuildObservers(connectionsRemovedArray); - InvokeClientPresenceChange(scene, connectionsRemovedArray, false, false); - } - } - - foreach (Scene s in removedScenes) - SceneConnections.Remove(s); - - /* Also rebuild observers for objects owned by connection. - * This ensures other connections will lose visibility if - * they no longer share a scene. */ - foreach (NetworkConnection c in conns) - RebuildObservers(c.Objects.ToArray()); - } - - - /// - /// Removes connections from specified scenes. - /// Exposed for power users, use caution. - /// - /// Connections to remove. - /// Scene to remove from. - public void RemoveConnectionsFromScene(NetworkConnection[] conns, Scene scene) - { - HashSet hs; - //No hashset for scene, so no connections are in scene. - if (!SceneConnections.TryGetValueIL2CPP(scene, out hs)) - return; - - List connectionsRemoved = new List(); - //Remove every connection from the scene. - foreach (NetworkConnection c in conns) - { - bool removed = hs.Remove(c); - if (removed) - { - c.RemoveFromScene(scene); - connectionsRemoved.Add(c); - } - } - - //If hashset is empty then remove scene from SceneConnections. - if (hs.Count == 0) - SceneConnections.Remove(scene); - - if (connectionsRemoved.Count > 0) - { - NetworkConnection[] connectionsRemovedArray = connectionsRemoved.ToArray(); - InvokeClientPresenceChange(scene, connectionsRemovedArray, false, true); - RebuildObservers(connectionsRemovedArray); - InvokeClientPresenceChange(scene, connectionsRemovedArray, false, false); - } - - /* Also rebuild observers for objects owned by connection. - * This ensures other connections will lose visibility if - * they no longer share a scene. */ - foreach (NetworkConnection c in conns) - RebuildObservers(c.Objects.ToArray()); - } - - /// - /// Removes all connections from a scene. - /// - /// Scene to remove connections from. - public void RemoveAllConnectionsFromScene(Scene scene) - { - HashSet hs; - //No hashset for scene, so no connections are in scene. - if (!SceneConnections.TryGetValueIL2CPP(scene, out hs)) - return; - - //On each connection remove them from specified scene. - foreach (NetworkConnection c in hs) - c.RemoveFromScene(scene); - //Make hashset into list for presence change. - NetworkConnection[] connectionsRemoved = hs.ToArray(); - - //Clear hashset and remove entry from sceneconnections. - hs.Clear(); - SceneConnections.Remove(scene); - - if (connectionsRemoved.Length > 0) - { - InvokeClientPresenceChange(scene, connectionsRemoved, false, true); - RebuildObservers(connectionsRemoved); - InvokeClientPresenceChange(scene, connectionsRemoved, false, false); - } - - /* Also rebuild observers for objects owned by connection. - * This ensures other connections will lose visibility if - * they no longer share a scene. */ - foreach (NetworkConnection c in connectionsRemoved) - RebuildObservers(c.Objects.ToArray()); - } - - #region Can Load/Unload Scene. - /// - /// Returns if a scene can be loaded locally. - /// - /// - private bool CanLoadScene(LoadQueueData qd, SceneLookupData sld) - { - bool foundByHandle; - Scene s = sld.GetScene(out foundByHandle); - //Try to find if scene is already loaded. - bool alreadyLoaded = !string.IsNullOrEmpty(s.name); - - if (alreadyLoaded) - { - //Only servers can load the same scene multiple times for stacking. - if (!qd.AsServer) - return false; - //If can only load scenes which aren't loaded yet and scene is already loaded. - if (!qd.SceneLoadData.Options.AllowStacking) - return false; - /* Found by handle, this means the user is trying to specify - * exactly which scene to load into. When a handle is specified - * new instances will not be created, so a new scene cannot - * be loaded. */ - if (alreadyLoaded && foundByHandle) - return false; - } - - //Fall through. - return true; - } - #endregion - - #region Helpers. - /// - /// Rebuilds observers for networkObjects. - /// - /// - private void RebuildObservers(NetworkObject[] networkObjects) - { - foreach (NetworkObject nob in networkObjects) - { - if (nob != null && nob.IsSpawned) - _serverManager.Objects.RebuildObservers(nob); - } - } - /// - /// Rebuilds all NetworkObjects for connection. - /// - internal void RebuildObservers(NetworkConnection connection) - { - RebuildObservers(new NetworkConnection[] { connection }); - } - /// - /// Rebuilds all NetworkObjects for connections. - /// - internal void RebuildObservers(NetworkConnection[] connections) - { - foreach (NetworkConnection c in connections) - _serverManager.Objects.RebuildObservers(c); - } - /// - /// Invokes OnClientPresenceChange start or end. - /// - /// - /// - /// - /// - private void InvokeClientPresenceChange(Scene scene, NetworkConnection[] conns, bool added, bool start) - { - foreach (NetworkConnection c in conns) - { - ClientPresenceChangeEventArgs cpc = new ClientPresenceChangeEventArgs(scene, c, added); - if (start) - OnClientPresenceChangeStart?.Invoke(cpc); - else - OnClientPresenceChangeEnd?.Invoke(cpc); - } - } - #endregion - - #region GetScene. - /// - /// Gets scenes from SceneLookupData. - /// - /// - /// - private Scene[] GetScenes(SceneLookupData[] datas) - { - List result = new List(); - foreach (SceneLookupData sld in datas) - { - Scene s = sld.GetScene(out _); - if (!string.IsNullOrEmpty(s.name)) - result.Add(s); - } - - return result.ToArray(); - } - - /// - /// Returns a scene by name. - /// - /// - /// - public static Scene GetScene(string sceneName) - { - return UnitySceneManager.GetSceneByName(sceneName); - } - /// - /// Returns a scene by handle. - /// - /// - /// - public static Scene GetScene(int sceneHandle) - { - int count = UnitySceneManager.sceneCount; - for (int i = 0; i < count; i++) - { - Scene s = UnitySceneManager.GetSceneAt(i); - if (s.handle == sceneHandle) - return s; - } - - return new Scene(); - } - #endregion - - /// - /// Returns if GlobalScenes contains scene. - /// - /// - /// - private bool IsGlobalScene(Scene scene) - { - for (int i = 0; i < _globalScenes.Length; i++) - { - if (_globalScenes[i] == scene.name) - return true; - } - - return false; - } - - /// - /// Removes datas from GlobalScenes. - /// - /// - private void RemoveFromGlobalScenes(Scene scene) - { - RemoveFromGlobalScenes(new SceneLookupData[] { SceneLookupData.CreateData(scene) }); - } - /// - /// Removes datas from GlobalScenes. - /// - /// - private void RemoveFromGlobalScenes(SceneLookupData[] datas) - { - List newGlobalScenes = _globalScenes.ToList(); - int startCount = newGlobalScenes.Count; - //Remove scenes. - for (int i = 0; i < datas.Length; i++) - newGlobalScenes.Remove(datas[i].Name); - - //If any were removed remake globalscenes. - if (startCount != newGlobalScenes.Count) - _globalScenes = newGlobalScenes.ToArray(); - } - - /// - /// Removes GlobalScenes from scenes. - /// - /// - /// - private void RemoveGlobalScenes(List scenes) - { - for (int i = 0; i < scenes.Count; i++) - { - foreach (string gs in _globalScenes) - { - if (gs == scenes[i].name) - { - scenes.RemoveAt(i); - i--; - } - } - } - } - - /// - /// Removes occupied scenes from scenes. - /// - /// - private void RemoveOccupiedScenes(List scenes) - { - for (int i = 0; i < scenes.Count; i++) - { - if (SceneConnections.TryGetValueIL2CPP(scenes[i], out _)) - { - scenes.RemoveAt(i); - i--; - } - } - } - - /// - /// Adds a pending load for a connection. - /// - private void AddPendingLoad(NetworkConnection conn) - { - AddPendingLoad(new NetworkConnection[] { conn }); - } - /// - /// Adds a pending load for a connection. - /// - private void AddPendingLoad(NetworkConnection[] conns) - { - foreach (NetworkConnection c in conns) - { - /* Make sure connection is active. This should always be true - * but perhaps disconnect happened as scene was loading on server - * therefor it cannot be sent to the client. - * Also only authenticated clients can load scenes. */ - if (!c.IsActive || !c.Authenticated) - continue; - - if (_pendingClientSceneChanges.TryGetValue(c, out int result)) - _pendingClientSceneChanges[c] = (result + 1); - else - _pendingClientSceneChanges[c] = 1; - } - } - /// - /// Sets the first global scene as the active scene. - /// If a global scene is not available then FallbackActiveScene is used. - /// - private void SetActiveScene(Scene preferredScene = default, bool byUser = false) - { - //If user specified then skip figuring it out checks. - if (byUser && preferredScene.IsValid()) - { - CompleteSetActive(preferredScene); - } - //Need to figure out which scene to use. - else - { - Scene s = default; - - //Feature is disabled. - if (!_setActiveScene) - { - //Still call complete to invoke events. - CompleteSetActive(s); - } - else - { - if (_globalScenes != null && _globalScenes.Length > 0) - s = GetScene(_globalScenes[0]); - else if (preferredScene.IsValid()) - s = preferredScene; - - /* If scene isn't set from global then make - * sure currently active isn't the movedobjectscene. - * If it is, then use the fallback scene. */ - if (string.IsNullOrEmpty(s.name) && UnitySceneManager.GetActiveScene() == _movedObjectsScene) - s = GetFallbackActiveScene(); - - CompleteSetActive(s); - } - } - - //Completes setting the active scene with specified value. - void CompleteSetActive(Scene scene) - { - bool sceneValid = scene.IsValid(); - if (sceneValid) - UnitySceneManager.SetActiveScene(scene); - - OnActiveSceneSet?.Invoke(byUser); - OnActiveSceneSetInternal?.Invoke(); - - if (sceneValid) - { - //Also update light probes. - if (_lightProbeUpdating == LightProbeUpdateType.Asynchronous) - LightProbes.TetrahedralizeAsync(); - else if (_lightProbeUpdating == LightProbeUpdateType.BlockThread) - LightProbes.Tetrahedralize(); - } - } - } - - /// - /// Returns the FallbackActiveScene. - /// - /// - private Scene GetFallbackActiveScene() - { - if (string.IsNullOrEmpty(_fallbackActiveScene.name)) - _fallbackActiveScene = UnitySceneManager.CreateScene("FallbackActiveScene"); - - return _fallbackActiveScene; - } - - /// - /// Returns the MovedObejctsScene. - /// - /// - private Scene GetMovedObjectsScene() - { - //Create moved objects scene. It will probably be used eventually. If not, no harm either way. - if (string.IsNullOrEmpty(_movedObjectsScene.name)) - _movedObjectsScene = UnitySceneManager.CreateScene("MovedObjectsHolder"); - - return _movedObjectsScene; - } - - /// - /// Returns the DelayedDestroyScene. - /// - /// - private Scene GetDelayedDestroyScene() - { - //Create moved objects scene. It will probably be used eventually. If not, no harm either way. - if (string.IsNullOrEmpty(_delayedDestroyScene.name)) - _delayedDestroyScene = UnitySceneManager.CreateScene("DelayedDestroy"); - - return _delayedDestroyScene; - } - - /// - /// Returns a preferred active scene to use. - /// - private Scene GetUserPreferredActiveScene(SceneLookupData sld, out bool byUser) - { - byUser = false; - if (sld == null) - return default; - - Scene s = sld.GetScene(out _); - if (s.IsValid()) - byUser = true; - return s; - } - - #region Sanity checks. - /// - /// Returns if a SceneLoadData is valid. - /// - /// - /// - /// - private bool SceneDataInvalid(SceneLoadData data, bool error) - { - bool result = data.DataInvalid(); - if (result && error) - _networkManager.LogError(INVALID_SCENELOADDATA); - - return result; - } - /// - /// Returns if a SceneLoadData is valid. - /// - /// - /// - /// - private bool SceneDataInvalid(SceneUnloadData data, bool error) - { - bool result = data.DataInvalid(); - if (result && error) - _networkManager.LogError(INVALID_SCENEUNLOADDATA); - - - return result; - } - /// - /// Returns if connection is active for server or client in association with AsServer. - /// - /// - /// - private bool ConnectionActive(bool asServer) - { - return (asServer) ? _networkManager.IsServer : _networkManager.IsClient; - } - /// - /// Returns if a method can execute. - /// - /// - /// - /// - private bool CanExecute(bool asServer, bool warn) - { - bool result; - if (asServer) - { - result = _networkManager.IsServer; - if (!result && warn) - _networkManager.LogWarning($"Method cannot be called as the server is not active."); - } - else - { - result = _networkManager.IsClient; - if (!result && warn) - _networkManager.LogWarning($"Method cannot be called as the client is not active."); - } - - return result; - } - #endregion - - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs.meta deleted file mode 100644 index 03dd624..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/SceneManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 15895a51081447d46bda466e7e830c08 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneProcessorBase.cs b/Assets/FishNet/Runtime/Managing/Scened/SceneProcessorBase.cs deleted file mode 100644 index a364c84..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/SceneProcessorBase.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityScene = UnityEngine.SceneManagement.Scene; - -namespace FishNet.Managing.Scened -{ - - public abstract class SceneProcessorBase : MonoBehaviour - { - #region Protected. - /// - /// SceneManager for this processor. - /// - protected SceneManager SceneManager; - #endregion - - /// - /// Initializes this script for use. - /// - /// SceneManager which will be utilizing this class. - public virtual void Initialize(SceneManager manager) - { - SceneManager = manager; - } - /// - /// Called when scene loading has begun. - /// - public virtual void LoadStart(LoadQueueData queueData) { } - /// - /// Called when scene loading has ended. - /// - public virtual void LoadEnd(LoadQueueData queueData) { } - /// - /// Called when scene unloading has begun within a load operation. - /// - public virtual void UnloadStart(LoadQueueData queueData) { } - /// - /// Called when scene unloading has ended within a load operation. - /// - public virtual void UnloadEnd(LoadQueueData queueData) { } - /// - /// Called when scene unloading has begun within an unload operation. - /// - public virtual void UnloadStart(UnloadQueueData queueData) { } - /// - /// Called when scene unloading has ended within an unload operation. - /// - public virtual void UnloadEnd(UnloadQueueData queueData) { } - /// - /// Begin loading a scene using an async method. - /// - /// Scene name to load. - public abstract void BeginLoadAsync(string sceneName, LoadSceneParameters parameters); - /// - /// Begin unloading a scene using an async method. - /// - /// Scene name to unload. - public abstract void BeginUnloadAsync(Scene scene); - /// - /// Returns if a scene load or unload percent is done. - /// - /// - public abstract bool IsPercentComplete(); - /// - /// Returns the progress on the current scene load or unload. - /// - /// - public abstract float GetPercentComplete(); - /// - /// Adds a scene to loaded scenes. - /// - /// Scene loaded. - public virtual void AddLoadedScene(Scene scene) { } - /// - /// Returns scenes which were loaded during a load operation. - /// - public abstract List GetLoadedScenes(); - /// - /// Activates scenes which were loaded. - /// - public abstract void ActivateLoadedScenes(); - /// - /// Returns if all asynchronized tasks are considered IsDone. - /// - /// - public abstract IEnumerator AsyncsIsDone(); - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneProcessorBase.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/SceneProcessorBase.cs.meta deleted file mode 100644 index e952beb..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/SceneProcessorBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: de3f29952a63dc341a7542a1f898cb12 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneSpawner.cs b/Assets/FishNet/Runtime/Managing/Scened/SceneSpawner.cs deleted file mode 100644 index a0f3d84..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/SceneSpawner.cs +++ /dev/null @@ -1,356 +0,0 @@ - -//using FishNet.Managing.Scened.Data; -//using System; -//using UnityEngine; -//using UnityEngine.SceneManagement; - -//namespace FishNet.Managing.Scened -//{ - -// public static class SceneSpawner -// { - -// #region Prefab. -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(Scene scene, GameObject prefab) -// { -// return Instantiate(scene, prefab); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(Scene scene, GameObject prefab) -// { -// return Instantiate(scene, prefab, prefab.transform.position, prefab.transform.rotation, null, true); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(SceneReferenceData sceneReferenceData, GameObject prefab) -// { -// return Instantiate(sceneReferenceData, prefab); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(SceneReferenceData sceneReferenceData, GameObject prefab) -// { -// Scene scene = SceneManager.ReturnScene(sceneReferenceData); -// return Instantiate(scene, prefab, prefab.transform.position, prefab.transform.rotation, null, true); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(int sceneHandle, GameObject prefab) -// { -// return Instantiate(sceneHandle, prefab, prefab.transform.position, prefab.transform.rotation, null); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(int sceneHandle, GameObject prefab) -// { -// Scene scene = SceneManager.ReturnScene(sceneHandle); -// return Instantiate(scene, prefab, prefab.transform.position, prefab.transform.rotation, null, true); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(string sceneName, GameObject prefab) -// { -// return Instantiate(sceneName, prefab); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(string sceneName, GameObject prefab) -// { -// Scene scene = SceneManager.ReturnScene(sceneName); -// return Instantiate(scene, prefab, prefab.transform.position, prefab.transform.rotation, null, true); -// } -// #endregion - - - - -// #region Prefab, Parent, WorldSpace -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(Scene scene, GameObject prefab, Transform parent, bool instantiateInWorldSpace = true) -// { -// return Instantiate(scene, prefab, parent, instantiateInWorldSpace); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(Scene scene, GameObject prefab, Transform parent, bool instantiateInWorldSpace = true) -// { -// return Instantiate(scene, prefab, prefab.transform.position, prefab.transform.rotation, parent, instantiateInWorldSpace); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(SceneReferenceData sceneReferenceData, GameObject prefab, Transform parent, bool instantiateInWorldSpace = true) -// { -// return Instantiate(sceneReferenceData, prefab, parent, instantiateInWorldSpace); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(SceneReferenceData sceneReferenceData, GameObject prefab, Transform parent, bool instantiateInWorldSpace = true) -// { -// Scene scene = SceneManager.ReturnScene(sceneReferenceData); -// return Instantiate(scene, prefab, prefab.transform.position, prefab.transform.rotation, parent, instantiateInWorldSpace); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(int sceneHandle, GameObject prefab, Transform parent, bool instantiateInWorldSpace = true) -// { -// return Instantiate(sceneHandle, prefab, parent, instantiateInWorldSpace); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(int sceneHandle, GameObject prefab, Transform parent, bool instantiateInWorldSpace = true) -// { -// Scene scene = SceneManager.ReturnScene(sceneHandle); -// return Instantiate(scene, prefab, prefab.transform.position, prefab.transform.rotation, parent, instantiateInWorldSpace); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(string sceneName, GameObject prefab, Transform parent, bool instantiateInWorldSpace = true) -// { -// return Instantiate(sceneName, prefab, parent, instantiateInWorldSpace); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(string sceneName, GameObject prefab, Transform parent, bool instantiateInWorldSpace = true) -// { -// Scene scene = SceneManager.ReturnScene(sceneName); -// return Instantiate(scene, prefab, prefab.transform.position, prefab.transform.rotation, parent, instantiateInWorldSpace); -// } -// #endregion - - - - -// #region Prefab, Position, Rotation. -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(Scene scene, GameObject prefab, Vector3 position, Quaternion rotation) -// { -// return Instantiate(scene, prefab, position, rotation); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(Scene scene, GameObject prefab, Vector3 position, Quaternion rotation) -// { -// return Instantiate(scene, prefab, position, rotation, null, true); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(SceneReferenceData sceneReferenceData, GameObject prefab, Vector3 position, Quaternion rotation) -// { -// return Instantiate(sceneReferenceData, prefab, position, rotation); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(SceneReferenceData sceneReferenceData, GameObject prefab, Vector3 position, Quaternion rotation) -// { -// Scene scene = SceneManager.ReturnScene(sceneReferenceData); -// return Instantiate(scene, prefab, position, rotation, null, true); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(int sceneHandle, GameObject prefab, Vector3 position, Quaternion rotation) -// { -// return Instantiate(sceneHandle, prefab, position, rotation); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(int sceneHandle, GameObject prefab, Vector3 position, Quaternion rotation) -// { -// Scene scene = SceneManager.ReturnScene(sceneHandle); -// return Instantiate(scene, prefab, position, rotation, null, true); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(string sceneName, GameObject prefab, Vector3 position, Quaternion rotation) -// { -// return Instantiate(sceneName, prefab, position, rotation); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(string sceneName, GameObject prefab, Vector3 position, Quaternion rotation) -// { -// Scene scene = SceneManager.ReturnScene(sceneName); -// return Instantiate(scene, prefab, position, rotation, null, true); -// } -// #endregion - - - - -// #region Prefab, Position, Rotation, Parent. -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(Scene scene, GameObject prefab, Vector3 position, Quaternion rotation, Transform parent) -// { -// return Instantiate(scene, prefab, position, rotation, parent); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(Scene scene, GameObject prefab, Vector3 position, Quaternion rotation, Transform parent) -// { -// return Instantiate(scene, prefab, position, rotation, parent, true); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(SceneReferenceData sceneReferenceData, GameObject prefab, Vector3 position, Quaternion rotation, Transform parent) -// { -// return Instantiate(sceneReferenceData, prefab, position, rotation, parent); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(SceneReferenceData sceneReferenceData, GameObject prefab, Vector3 position, Quaternion rotation, Transform parent) -// { -// Scene scene = SceneManager.ReturnScene(sceneReferenceData); -// return Instantiate(scene, prefab, position, rotation, parent, true); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(int sceneHandle, GameObject prefab, Vector3 position, Quaternion rotation, Transform parent) -// { -// return Instantiate(sceneHandle, prefab, position, rotation, parent); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(int sceneHandle, GameObject prefab, Vector3 position, Quaternion rotation, Transform parent) -// { -// Scene scene = SceneManager.ReturnScene(sceneHandle); -// return Instantiate(scene, prefab, position, rotation, parent, true); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static GameObject Instantiate(string sceneName, GameObject prefab, Vector3 position, Quaternion rotation, Transform parent) -// { -// return Instantiate(sceneName, prefab, position, rotation, parent); -// } -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// public static T Instantiate(string sceneName, GameObject prefab, Vector3 position, Quaternion rotation, Transform parent) -// { -// Scene scene = SceneManager.ReturnScene(sceneName); -// return Instantiate(scene, prefab, position, rotation, parent, true); -// } -// #endregion - - -// #region Instantiator. -// /// -// /// Instantiates a prefab and moves it to a scene. -// /// -// /// Instantiated prefab or script. -// private static T Instantiate(Scene scene, GameObject prefab, Vector3 position, Quaternion rotation, Transform parent, bool instantiateInWorldSpace) -// { -// if (string.IsNullOrEmpty(scene.name)) -// { -// Debug.LogWarning("Scene does not exist. Prefab cannot be instantiated."); -// return default(T); -// } - -// GameObject result = MonoBehaviour.Instantiate(prefab, position, rotation); -// if (result != null) -// { -// //Move to new scene first. -// UnityEngine.SceneManagement.SceneManager.MoveGameObjectToScene(result, scene); - -// //Set parent and spaces. -// if (parent != null) -// { -// result.transform.SetParent(parent); -// //If to not instantiate in world space then update pos/rot to localspace. -// if (!instantiateInWorldSpace) -// { -// result.transform.localPosition = position; -// result.transform.localRotation = rotation; -// } -// } - -// //If was a gameobject then return as GO. -// if (typeof(T) == typeof(GameObject)) -// return (T)Convert.ChangeType(result, typeof(GameObject)); -// //Otherwise use getcomponent on the type. -// else -// return result.GetComponent(); -// } -// //Couldn't be instantiated, return default of T. -// else -// { -// return default(T); -// } - -// } -// #endregion - - -// } - - - - -//} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Scened/SceneSpawner.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/SceneSpawner.cs.meta deleted file mode 100644 index 94dd0f6..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/SceneSpawner.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 405b031a6ef64b346ae8c5ccbf07d8e1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs b/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs deleted file mode 100644 index 14bcab1..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs +++ /dev/null @@ -1,21 +0,0 @@ -using UnityEngine.SceneManagement; - -namespace FishNet.Managing.Scened -{ - public struct UnloadedScene - { - public readonly string Name; - public readonly int Handle; - - public UnloadedScene(Scene s) - { - Name = s.name; - Handle = s.handle; - } - public UnloadedScene(string name, int handle) - { - Name = name; - Handle = handle; - } - } -} diff --git a/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs.meta b/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs.meta deleted file mode 100644 index c1c66be..0000000 --- a/Assets/FishNet/Runtime/Managing/Scened/UnloadedScene.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a51fea764b1081c4ab6308101f160f10 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Server.meta b/Assets/FishNet/Runtime/Managing/Server.meta deleted file mode 100644 index da71fec..0000000 --- a/Assets/FishNet/Runtime/Managing/Server.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 993fee93506dc1a409dfc0d0cb89354d -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Server/ClientConnectionBroadcast.cs b/Assets/FishNet/Runtime/Managing/Server/ClientConnectionBroadcast.cs deleted file mode 100644 index fe7c454..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/ClientConnectionBroadcast.cs +++ /dev/null @@ -1,18 +0,0 @@ -using FishNet.Broadcast; -using FishNet.Utility.Performance; - -namespace FishNet.Managing.Server -{ - public struct ClientConnectionChangeBroadcast : IBroadcast - { - public bool Connected; - public int Id; - } - - public struct ConnectedClientsBroadcast : IBroadcast - { - public ListCache ListCache; - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Server/ClientConnectionBroadcast.cs.meta b/Assets/FishNet/Runtime/Managing/Server/ClientConnectionBroadcast.cs.meta deleted file mode 100644 index 9b30fbf..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/ClientConnectionBroadcast.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a16b83a545be8f8488795783a0fc8648 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Server/Editor.meta b/Assets/FishNet/Runtime/Managing/Server/Editor.meta deleted file mode 100644 index 10e9aa6..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: eef52ab3fdb83f04592a1de5ccb741f5 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Server/Editor/ServerManagerEditor.cs b/Assets/FishNet/Runtime/Managing/Server/Editor/ServerManagerEditor.cs deleted file mode 100644 index d6de662..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/Editor/ServerManagerEditor.cs +++ /dev/null @@ -1,64 +0,0 @@ -#if UNITY_EDITOR -using UnityEditor; -using UnityEngine; - -namespace FishNet.Managing.Server.Editing -{ - - - [CustomEditor(typeof(ServerManager), true)] - [CanEditMultipleObjects] - public class ServerManagerEditor : Editor - { - private SerializedProperty _authenticator; - private SerializedProperty _syncTypeRate; - private SerializedProperty SpawnPacking; - private SerializedProperty _changeFrameRate; - private SerializedProperty _frameRate; - private SerializedProperty _shareIds; - private SerializedProperty _startOnHeadless; - private SerializedProperty _limitClientMTU; - - protected virtual void OnEnable() - { - _authenticator = serializedObject.FindProperty(nameof(_authenticator)); - _syncTypeRate = serializedObject.FindProperty(nameof(_syncTypeRate)); - SpawnPacking = serializedObject.FindProperty(nameof(SpawnPacking)); - _changeFrameRate = serializedObject.FindProperty(nameof(_changeFrameRate)); - _frameRate = serializedObject.FindProperty(nameof(_frameRate)); - _shareIds = serializedObject.FindProperty(nameof(_shareIds)); - _startOnHeadless = serializedObject.FindProperty(nameof(_startOnHeadless)); - _limitClientMTU = serializedObject.FindProperty(nameof(_limitClientMTU)); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - GUI.enabled = false; - EditorGUILayout.ObjectField("Script:", MonoScript.FromMonoBehaviour((ServerManager)target), typeof(ServerManager), false); - GUI.enabled = true; - - - EditorGUILayout.PropertyField(_authenticator); - EditorGUILayout.PropertyField(_syncTypeRate); - EditorGUILayout.PropertyField(SpawnPacking); - EditorGUILayout.PropertyField(_changeFrameRate); - if (_changeFrameRate.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_frameRate); - EditorGUI.indentLevel--; - } - EditorGUILayout.PropertyField(_shareIds); - EditorGUILayout.PropertyField(_startOnHeadless); - EditorGUILayout.PropertyField(_limitClientMTU); - - EditorGUILayout.Space(); - - serializedObject.ApplyModifiedProperties(); - } - - } -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Server/Editor/ServerManagerEditor.cs.meta b/Assets/FishNet/Runtime/Managing/Server/Editor/ServerManagerEditor.cs.meta deleted file mode 100644 index 953fe5a..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/Editor/ServerManagerEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: da6ea97e6b868974e8ac139fe545e986 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Server/KickReasons.cs b/Assets/FishNet/Runtime/Managing/Server/KickReasons.cs deleted file mode 100644 index 69050c8..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/KickReasons.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace FishNet.Managing.Server -{ - - public enum KickReason : short - { - /// - /// No reason was specified. - /// - Unset = 0, - /// - /// Client performed an action which could only be done if trying to exploit the server. - /// - ExploitAttempt = 1, - /// - /// Data received from the client could not be parsed. This rarely indicates an attack. - /// - MalformedData = 2, - /// - /// Client sent more data than should be able to. - /// - ExploitExcessiveData = 3, - /// - /// Client has sent a large amount of data several times in a row. This may not be an attack but there is no way to know with certainty. - /// - ExcessiveData = 4, - /// - /// A problem occurred with the server where the only option was to kick the client. This rarely indicates an exploit attempt. - /// - UnexpectedProblem = 5, - /// - /// Client is behaving unusually, such as providing multiple invalid states. This may not be an attack but there is no way to know with certainty. - /// - UnusualActivity = 6, - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Server/KickReasons.cs.meta b/Assets/FishNet/Runtime/Managing/Server/KickReasons.cs.meta deleted file mode 100644 index af8a9fe..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/KickReasons.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9289a823878c5d1408e7106e6ed5d866 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Server/Object.meta b/Assets/FishNet/Runtime/Managing/Server/Object.meta deleted file mode 100644 index f453896..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/Object.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 272e053307699c84d9787bfd86d3529a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Observers.cs b/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Observers.cs deleted file mode 100644 index 3d66b75..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Observers.cs +++ /dev/null @@ -1,522 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing.Object; -using FishNet.Managing.Transporting; -using FishNet.Object; -using FishNet.Observing; -using FishNet.Serializing; -using FishNet.Transporting; -using FishNet.Utility.Performance; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Managing.Server -{ - public partial class ServerObjects : ManagedObjects - { - #region Private. - /// - /// Cache filled with objects which observers are being updated. - /// This is primarily used to invoke events after all observers are updated, rather than as each is updated. - /// - private List _observerChangedObjectsCache = new List(100); - /// - /// NetworkObservers which require regularly iteration. - /// - private List _timedNetworkObservers = new List(); - /// - /// Index in TimedNetworkObservers to start on next cycle. - /// - private int _nextTimedObserversIndex; - #endregion - - /// - /// Called when MonoBehaviours call Update. - /// - private void Observers_OnUpdate() - { - UpdateTimedObservers(); - } - - /// - /// Progressively updates NetworkObservers with timed conditions. - /// - private void UpdateTimedObservers() - { - if (!base.NetworkManager.IsServer) - return; - //No point in updating if the timemanager isn't going to tick this frame. - if (!base.NetworkManager.TimeManager.FrameTicked) - return; - int observersCount = _timedNetworkObservers.Count; - if (observersCount == 0) - return; - - ServerManager serverManager = base.NetworkManager.ServerManager; - TransportManager transportManager = NetworkManager.TransportManager; - /* Try to iterate all timed observers every half a second. - * This value will increase as there's more observers. */ - int completionTicks = (base.NetworkManager.TimeManager.TickRate * 2); - /* Multiply required ticks based on connection count and nob count. This will - * reduce how quickly observers update slightly but will drastically - * improve performance. */ - float tickMultiplier = 1f + (float)( - (serverManager.Clients.Count * 0.005f) + - (_timedNetworkObservers.Count * 0.0005f) - ); - /* Add an additional iteration to prevent - * 0 iterations */ - int iterations = (observersCount / (int)(completionTicks * tickMultiplier)) + 1; - if (iterations > observersCount) - iterations = observersCount; - - PooledWriter everyoneWriter = WriterPool.GetWriter(); - PooledWriter ownerWriter = WriterPool.GetWriter(); - - //Index to perform a check on. - int observerIndex = 0; - foreach (NetworkConnection conn in serverManager.Clients.Values) - { - int cacheIndex = 0; - using (PooledWriter largeWriter = WriterPool.GetWriter()) - { - //Reset index to start on for every connection. - observerIndex = 0; - /* Run the number of calculated iterations. - * This is spaced out over frames to prevent - * fps spikes. */ - for (int i = 0; i < iterations; i++) - { - observerIndex = _nextTimedObserversIndex + i; - /* Compare actual collection size not cached value. - * This is incase collection is modified during runtime. */ - if (observerIndex >= _timedNetworkObservers.Count) - observerIndex -= _timedNetworkObservers.Count; - - /* If still out of bounds something whack is going on. - * Reset index and exit method. Let it sort itself out - * next iteration. */ - if (observerIndex < 0 || observerIndex >= _timedNetworkObservers.Count) - { - _nextTimedObserversIndex = 0; - break; - } - - NetworkObject nob = _timedNetworkObservers[observerIndex]; - ObserverStateChange osc = nob.RebuildObservers(conn, true); - if (osc == ObserverStateChange.Added) - { - everyoneWriter.Reset(); - ownerWriter.Reset(); - base.WriteSpawn_Server(nob, conn, everyoneWriter, ownerWriter); - CacheObserverChange(nob, ref cacheIndex); - } - else if (osc == ObserverStateChange.Removed) - { - everyoneWriter.Reset(); - WriteDespawn(nob, nob.GetDefaultDespawnType(), everyoneWriter); - - } - else - { - continue; - } - /* Only use ownerWriter if an add, and if owner. Owner - * doesn't matter if not being added because no owner specific - * information would be included. */ - PooledWriter writerToUse = (osc == ObserverStateChange.Added && nob.Owner == conn) ? - ownerWriter : everyoneWriter; - - largeWriter.WriteArraySegment(writerToUse.GetArraySegment()); - } - - if (largeWriter.Length > 0) - { - transportManager.SendToClient( - (byte)Channel.Reliable, - largeWriter.GetArraySegment(), conn); - } - - //Invoke spawn callbacks on nobs. - for (int i = 0; i < cacheIndex; i++) - _observerChangedObjectsCache[i].InvokePostOnServerStart(conn); - } - } - - everyoneWriter.Dispose(); - ownerWriter.Dispose(); - _nextTimedObserversIndex = (observerIndex + 1); - } - - /// - /// Indicates that a networkObserver component should be updated regularly. This is done automatically. - /// - /// NetworkObject to be updated. - public void AddTimedNetworkObserver(NetworkObject networkObject) - { - _timedNetworkObservers.Add(networkObject); - } - - /// - /// Indicates that a networkObserver component no longer needs to be updated regularly. This is done automatically. - /// - /// NetworkObject to be updated. - public void RemoveTimedNetworkObserver(NetworkObject networkObject) - { - _timedNetworkObservers.Remove(networkObject); - } - - /// - /// Caches an observer change. - /// - /// - private void CacheObserverChange(NetworkObject nob, ref int cacheIndex) - { - /* If this spawn would exceed cache size then - * add instead of set value. */ - if (_observerChangedObjectsCache.Count <= cacheIndex) - _observerChangedObjectsCache.Add(nob); - else - _observerChangedObjectsCache[cacheIndex] = nob; - - cacheIndex++; - } - - /// - /// Removes a connection from observers without synchronizing changes. - /// - /// - private void RemoveFromObserversWithoutSynchronization(NetworkConnection connection) - { - int cacheIndex = 0; - - foreach (NetworkObject nob in Spawned.Values) - { - if (nob.RemoveObserver(connection)) - CacheObserverChange(nob, ref cacheIndex); - } - - //Invoke despawn callbacks on nobs. - for (int i = 0; i < cacheIndex; i++) - _observerChangedObjectsCache[i].InvokeOnServerDespawn(connection); - } - - /// - /// Rebuilds observers on all NetworkObjects for all connections. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RebuildObservers() - { - ListCache nobCache = GetOrderedSpawnedObjects(); - ListCache connCache = ListCaches.GetNetworkConnectionCache(); - foreach (NetworkConnection conn in base.NetworkManager.ServerManager.Clients.Values) - connCache.AddValue(conn); - - RebuildObservers(nobCache, connCache); - ListCaches.StoreCache(nobCache); - ListCaches.StoreCache(connCache); - } - - /// - /// Rebuilds observers on NetworkObjects. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RebuildObservers(NetworkObject[] nobs) - { - int count = nobs.Length; - for (int i = 0; i < count; i++) - RebuildObservers(nobs[i]); - } - - /// - /// Rebuilds observers on NetworkObjects. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RebuildObservers(List nobs) - { - int count = nobs.Count; - for (int i = 0; i < count; i++) - RebuildObservers(nobs[i]); - } - - /// - /// Rebuilds observers on NetworkObjects. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RebuildObservers(ListCache nobs) - { - int count = nobs.Written; - List collection = nobs.Collection; - for (int i = 0; i < count; i++) - RebuildObservers(collection[i]); - } - /// - /// Rebuilds observers on NetworkObjects for connections. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RebuildObservers(ListCache nobs, NetworkConnection conn) - { - RebuildObservers(nobs.Collection, conn, nobs.Written); - } - /// - /// Rebuilds observers on NetworkObjects for connections. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RebuildObservers(ListCache nobs, ListCache conns) - { - int count = nobs.Written; - List collection = nobs.Collection; - for (int i = 0; i < count; i++) - RebuildObservers(collection[i], conns); - } - /// - /// Rebuilds observers on all objects for a connections. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RebuildObservers(ListCache connections) - { - int count = connections.Written; - List collection = connections.Collection; - for (int i = 0; i < count; i++) - RebuildObservers(collection[i]); - } - /// - /// Rebuilds observers on all objects for connections. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RebuildObservers(NetworkConnection[] connections) - { - int count = connections.Length; - for (int i = 0; i < count; i++) - RebuildObservers(connections[i]); - } - /// - /// Rebuilds observers on all objects for connections. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RebuildObservers(List connections) - { - int count = connections.Count; - for (int i = 0; i < count; i++) - RebuildObservers(connections[i]); - } - - /// - /// Rebuilds observers on all NetworkObjects for a connection. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RebuildObservers(NetworkConnection connection) - { - ListCache cache = GetOrderedSpawnedObjects(); - RebuildObservers(cache, connection); - ListCaches.StoreCache(cache); - } - - /// - /// Gets all spawned objects with root objects first. - /// - /// - private ListCache GetOrderedSpawnedObjects() - { - ListCache cache = ListCaches.GetNetworkObjectCache(); - foreach (NetworkObject networkObject in Spawned.Values) - { - if (networkObject.IsNested) - continue; - - //Add nob and children recursively. - AddChildNetworkObjects(networkObject); - } - - void AddChildNetworkObjects(NetworkObject n) - { - cache.AddValue(n); - foreach (NetworkObject nob in n.ChildNetworkObjects) - AddChildNetworkObjects(nob); - } - - return cache; - } - - /// - /// Rebuilds observers for a connection on NetworkObjects. - /// - /// NetworkObjects to rebuild. - /// Connection to rebuild for. - /// Number of iterations to perform collection. Entire collection is iterated when value is -1. - public void RebuildObservers(IEnumerable nobs, NetworkConnection connection, int count = -1) - { - PooledWriter everyoneWriter = WriterPool.GetWriter(); - PooledWriter ownerWriter = WriterPool.GetWriter(); - - //If there's no limit on how many can be written set count to the maximum. - if (count == -1) - count = int.MaxValue; - - int iterations; - int observerCacheIndex; - using (PooledWriter largeWriter = WriterPool.GetWriter()) - { - iterations = 0; - observerCacheIndex = 0; - foreach (NetworkObject n in nobs) - { - iterations++; - if (iterations > count) - break; - - //If observer state changed then write changes. - ObserverStateChange osc = n.RebuildObservers(connection, false); - if (osc == ObserverStateChange.Added) - { - everyoneWriter.Reset(); - ownerWriter.Reset(); - base.WriteSpawn_Server(n, connection, everyoneWriter, ownerWriter); - CacheObserverChange(n, ref observerCacheIndex); - } - else if (osc == ObserverStateChange.Removed) - { - connection.LevelOfDetails.Remove(n); - everyoneWriter.Reset(); - WriteDespawn(n, n.GetDefaultDespawnType(), everyoneWriter); - } - else - { - continue; - } - /* Only use ownerWriter if an add, and if owner. Owner //cleanup see if rebuild timed and this can be joined or reuse methods. - * doesn't matter if not being added because no owner specific - * information would be included. */ - PooledWriter writerToUse = (osc == ObserverStateChange.Added && n.Owner == connection) ? - ownerWriter : everyoneWriter; - - largeWriter.WriteArraySegment(writerToUse.GetArraySegment()); - } - - if (largeWriter.Length > 0) - { - NetworkManager.TransportManager.SendToClient( - (byte)Channel.Reliable, - largeWriter.GetArraySegment(), connection); - } - } - - //Dispose of writers created in this method. - everyoneWriter.Dispose(); - ownerWriter.Dispose(); - - //Invoke spawn callbacks on nobs. - for (int i = 0; i < observerCacheIndex; i++) - _observerChangedObjectsCache[i].InvokePostOnServerStart(connection); - } - - /// - /// Rebuilds observers for connections on a NetworkObject. - /// - private void RebuildObservers(NetworkObject nob, ListCache conns) - { - PooledWriter everyoneWriter = WriterPool.GetWriter(); - PooledWriter ownerWriter = WriterPool.GetWriter(); - - int written = conns.Written; - for (int i = 0; i < written; i++) - { - NetworkConnection conn = conns.Collection[i]; - - everyoneWriter.Reset(); - ownerWriter.Reset(); - //If observer state changed then write changes. - ObserverStateChange osc = nob.RebuildObservers(conn, false); - if (osc == ObserverStateChange.Added) - { - base.WriteSpawn_Server(nob, conn, everyoneWriter, ownerWriter); - } - else if (osc == ObserverStateChange.Removed) - { - conn.LevelOfDetails.Remove(nob); - WriteDespawn(nob, nob.GetDefaultDespawnType(), everyoneWriter); - } - else - { - continue; - } - - /* Only use ownerWriter if an add, and if owner. Owner - * doesn't matter if not being added because no owner specific - * information would be included. */ - PooledWriter writerToUse = (osc == ObserverStateChange.Added && nob.Owner == conn) ? - ownerWriter : everyoneWriter; - - if (writerToUse.Length > 0) - { - NetworkManager.TransportManager.SendToClient( - (byte)Channel.Reliable, - writerToUse.GetArraySegment(), conn); - - //If a spawn is being sent. - if (osc == ObserverStateChange.Added) - nob.InvokePostOnServerStart(conn); - } - - } - - //Dispose of writers created in this method. - everyoneWriter.Dispose(); - ownerWriter.Dispose(); - } - - - /// - /// Rebuilds observers for all connections for a NetworkObject. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RebuildObservers(NetworkObject nob) - { - ListCache cache = ListCaches.GetNetworkConnectionCache(); - foreach (NetworkConnection item in NetworkManager.ServerManager.Clients.Values) - cache.AddValue(item); - - RebuildObservers(nob, cache); - ListCaches.StoreCache(cache); - } - /// - /// Rebuilds observers for a connection on NetworkObject. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void RebuildObservers(NetworkObject nob, NetworkConnection conn) - { - ListCache cache = ListCaches.GetNetworkConnectionCache(); - cache.AddValue(conn); - - RebuildObservers(nob, cache); - ListCaches.StoreCache(cache); - } - /// - /// Rebuilds observers for connections on NetworkObject. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RebuildObservers(NetworkObject networkObject, NetworkConnection[] connections) - { - ListCache cache = ListCaches.GetNetworkConnectionCache(); - cache.AddValues(connections); - RebuildObservers(networkObject, cache); - ListCaches.StoreCache(cache); - } - - /// - /// Rebuilds observers for connections on NetworkObject. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RebuildObservers(NetworkObject networkObject, List connections) - { - ListCache cache = ListCaches.GetNetworkConnectionCache(); - cache.AddValues(connections); - RebuildObservers(networkObject, cache); - ListCaches.StoreCache(cache); - } - - - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Observers.cs.meta b/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Observers.cs.meta deleted file mode 100644 index d184e37..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Observers.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 02d93fa4a653dd64da0bb338b82f4740 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Parsing.cs b/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Parsing.cs deleted file mode 100644 index 0b3e199..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Parsing.cs +++ /dev/null @@ -1,45 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing.Object; -using FishNet.Managing.Utility; -using FishNet.Object; -using FishNet.Serializing; -using FishNet.Transporting; -using System.Runtime.CompilerServices; - -namespace FishNet.Managing.Server -{ - public partial class ServerObjects : ManagedObjects - { - - /// - /// Parses a ReplicateRpc. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ParseReplicateRpc(PooledReader reader, NetworkConnection conn, Channel channel) - { - NetworkBehaviour nb = reader.ReadNetworkBehaviour(); - int dataLength = Packets.GetPacketLength((ushort)PacketId.ServerRpc, reader, channel); - - if (nb != null) - nb.OnReplicateRpc(null, reader, conn, channel); - else - SkipDataLength((ushort)PacketId.ServerRpc, reader, dataLength); - } - - /// - /// Parses a ServerRpc. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void ParseServerRpc(PooledReader reader, NetworkConnection conn, Channel channel) - { - NetworkBehaviour nb = reader.ReadNetworkBehaviour(); - int dataLength = Packets.GetPacketLength((ushort)PacketId.ServerRpc, reader, channel); - - if (nb != null) - nb.OnServerRpc(reader, conn, channel); - else - SkipDataLength((ushort)PacketId.ServerRpc, reader, dataLength); - } - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Parsing.cs.meta b/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Parsing.cs.meta deleted file mode 100644 index d684ec7..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.Parsing.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3cb6cef520a4ff44bb8c4814e566c5ff -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.cs b/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.cs deleted file mode 100644 index ff8415d..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.cs +++ /dev/null @@ -1,876 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing.Logging; -using FishNet.Managing.Object; -using FishNet.Managing.Timing; -using FishNet.Object; -using FishNet.Serializing; -using FishNet.Transporting; -using FishNet.Utility; -using FishNet.Utility.Extension; -using FishNet.Utility.Performance; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; -using UnityEngine.SceneManagement; - -namespace FishNet.Managing.Server -{ - /// - /// Handles objects and information about objects for the server. See ManagedObjects for inherited options. - /// - public partial class ServerObjects : ManagedObjects - { - #region Public. - /// - /// Called right before client objects are destroyed when a client disconnects. - /// - public event Action OnPreDestroyClientObjects; - #endregion - - #region Internal. - /// - /// Collection of NetworkObjects recently despawned. - /// Key: objectId. - /// Value: despawn tick. - /// This is used primarily to track if client is sending messages for recently despawned objects. - /// Objects are automatically removed after RECENTLY_DESPAWNED_DURATION seconds. - /// - internal Dictionary RecentlyDespawnedIds = new Dictionary(); - #endregion - - #region Private. - /// - /// Cached ObjectIds which may be used when exceeding available ObjectIds. - /// - private Queue _objectIdCache = new Queue(); - /// - /// Returns the ObjectId cache. - /// - /// - internal Queue GetObjectIdCache() => _objectIdCache; - /// - /// NetworkBehaviours which have dirty SyncVars. - /// - private List _dirtySyncVarBehaviours = new List(20); - /// - /// NetworkBehaviours which have dirty SyncObjects. - /// - private List _dirtySyncObjectBehaviours = new List(20); - /// - /// Objects which need to be destroyed next tick. - /// This is needed when running as host so host client will get any final messages for the object before they're destroyed. - /// - private Dictionary _pendingDestroy = new Dictionary(); - /// - /// Scenes which were loaded that need to be setup. - /// - private List<(int, Scene)> _loadedScenes = new List<(int frame, Scene scene)>(); - /// - /// Cache of spawning objects, used for recursively spawning nested NetworkObjects. - /// - private ListCache _spawnCache = new ListCache(); - /// - /// True if one or more scenes are currently loading through the SceneManager. - /// - private bool _scenesLoading; - /// - /// Number of ticks which must pass to clear a recently despawned. - /// - private uint _cleanRecentlyDespawnedMaxTicks => base.NetworkManager.TimeManager.TimeToTicks(30d, TickRounding.RoundUp); - #endregion - - internal ServerObjects(NetworkManager networkManager) - { - base.Initialize(networkManager); - networkManager.SceneManager.OnLoadStart += SceneManager_OnLoadStart; - networkManager.SceneManager.OnActiveSceneSetInternal += SceneManager_OnActiveSceneSet; - networkManager.TimeManager.OnUpdate += TimeManager_OnUpdate; - } - - /// - /// Called when MonoBehaviours call Update. - /// - private void TimeManager_OnUpdate() - { - if (!base.NetworkManager.IsServer) - { - _scenesLoading = false; - _loadedScenes.Clear(); - return; - } - - CleanRecentlyDespawned(); - - if (!_scenesLoading) - IterateLoadedScenes(false); - Observers_OnUpdate(); - } - - #region Checking dirty SyncTypes. - /// - /// Iterates NetworkBehaviours with dirty SyncTypes. - /// - internal void WriteDirtySyncTypes() - { - /* Tells networkbehaviours to check their - * dirty synctypes. */ - IterateCollection(_dirtySyncVarBehaviours, false); - IterateCollection(_dirtySyncObjectBehaviours, true); - - void IterateCollection(List collection, bool isSyncObject) - { - for (int i = 0; i < collection.Count; i++) - { - bool dirtyCleared = collection[i].WriteDirtySyncTypes(isSyncObject); - if (dirtyCleared) - { - collection.RemoveAt(i); - i--; - } - } - } - } - /// - /// Sets that a NetworkBehaviour has a dirty syncVars. - /// - /// - internal void SetDirtySyncType(NetworkBehaviour nb, bool isSyncObject) - { - if (isSyncObject) - _dirtySyncObjectBehaviours.Add(nb); - else - _dirtySyncVarBehaviours.Add(nb); - } - #endregion - - #region Connection Handling. - /// - /// Called when the connection state changes for the local server. - /// - /// - internal void OnServerConnectionState(ServerConnectionStateArgs args) - { - - //If server just connected. - if (args.ConnectionState == LocalConnectionState.Started) - { - /* If there's no servers started besides the one - * that just started then build Ids and setup scene objects. */ - if (base.NetworkManager.ServerManager.OneServerStarted()) - { - BuildObjectIdCache(); - SetupSceneObjects(); - } - } - //Server in anything but started state. - else - { - //If no servers are started then reset. - if (!base.NetworkManager.ServerManager.AnyServerStarted()) - { - base.DespawnWithoutSynchronization(true); - base.SceneObjects.Clear(); - _objectIdCache.Clear(); - base.NetworkManager.ClearClientsCollection(base.NetworkManager.ServerManager.Clients); - } - } - } - - /// - /// Called when a client disconnects. - /// - /// - internal void ClientDisconnected(NetworkConnection connection) - { - RemoveFromObserversWithoutSynchronization(connection); - - OnPreDestroyClientObjects?.Invoke(connection); - - /* A cache is made because the Objects - * collection would end up modified during - * iteration from removing ownership and despawning. */ - ListCache cache = ListCaches.GetNetworkObjectCache(); - foreach (NetworkObject nob in connection.Objects) - cache.AddValue(nob); - - int written = cache.Written; - List collection = cache.Collection; - for (int i = 0; i < written; i++) - { - /* Objects may already be deinitializing when a client disconnects - * because the root object could have been despawned first, and in result - * all child objects would have been recursively despawned. - * - * EG: object is: - * A (nob) - * B (nob) - * - * Both A and B are owned by the client so they will both be - * in collection. Should A despawn first B will recursively despawn - * from it. Then once that finishes and the next index of collection - * is run, which would B, the object B would have already been deinitialized. */ - if (!collection[i].IsDeinitializing) - base.NetworkManager.ServerManager.Despawn(collection[i]); - } - - ListCaches.StoreCache(cache); - } - #endregion - - #region ObjectIds. - /// - /// Builds the ObjectId cache with all possible Ids. - /// - private void BuildObjectIdCache() - { - _objectIdCache.Clear(); - - /* Shuffle Ids to make it more difficult - * for clients to track spawned object - * count. */ - List shuffledCache = new List(); - //Ignore ushort.maxvalue as that indicates null. - for (int i = 0; i < (ushort.MaxValue - 1); i++) - shuffledCache.Add(i); - /* Only shuffle when NOT in editor and not - * development build. - * Debugging could be easier when Ids are ordered. */ -#if !UNITY_EDITOR && !DEVELOPMENT_BUILD - shuffledCache.Shuffle(); -#endif - //Add shuffled to objectIdCache. - //Build Id cache. - int cacheCount = shuffledCache.Count; - for (int i = 0; i < cacheCount; i++) - _objectIdCache.Enqueue(shuffledCache[i]); - } - /// - /// Caches a NetworkObject ObjectId. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void CacheObjectId(NetworkObject nob) - { - if (nob.ObjectId != NetworkObject.UNSET_OBJECTID_VALUE) - CacheObjectId(nob.ObjectId); - } - /// - /// Adds an ObjectId to objectId cache. - /// - /// - internal void CacheObjectId(int id) - { - _objectIdCache.Enqueue(id); - } - - /// - /// Gets the next ObjectId to use for NetworkObjects. - /// - /// - protected internal override int GetNextNetworkObjectId(bool errorCheck = true) - { - //Either something went wrong or user actually managed to spawn ~64K networked objects. - if (_objectIdCache.Count == 0) - { - base.NetworkManager.LogError($"No more available ObjectIds. How the heck did you manage to have {ushort.MaxValue} objects spawned at once?"); - return -1; - } - else - { - return _objectIdCache.Dequeue(); - } - } - #endregion - - #region Initializing Objects In Scenes. - /// - /// Called when a scene load starts. - /// - private void SceneManager_OnLoadStart(Scened.SceneLoadStartEventArgs obj) - { - _scenesLoading = true; - } - /// - /// Called after the active scene has been scene, immediately after scene loads. - /// - private void SceneManager_OnActiveSceneSet() - { - _scenesLoading = false; - IterateLoadedScenes(true); - } - /// - /// Iterates loaded scenes and sets them up. - /// - /// True to ignore the frame restriction when iterating. - internal void IterateLoadedScenes(bool ignoreFrameRestriction) - { - //Not started, clear loaded scenes. - if (!NetworkManager.ServerManager.Started) - _loadedScenes.Clear(); - - for (int i = 0; i < _loadedScenes.Count; i++) - { - (int frame, Scene scene) value = _loadedScenes[i]; - if (ignoreFrameRestriction || (Time.frameCount > value.frame)) - { - SetupSceneObjects(value.scene); - _loadedScenes.RemoveAt(i); - i--; - } - } - } - - /// - /// Called when a scene loads on the server. - /// - /// - /// - protected internal override void SceneManager_sceneLoaded(Scene s, LoadSceneMode arg1) - { - base.SceneManager_sceneLoaded(s, arg1); - - if (!NetworkManager.ServerManager.Started) - return; - //Add to loaded scenes so that they are setup next frame. - _loadedScenes.Add((Time.frameCount, s)); - } - - /// - /// Setup all NetworkObjects in scenes. Should only be called when server is active. - /// - protected internal void SetupSceneObjects() - { - for (int i = 0; i < SceneManager.sceneCount; i++) - SetupSceneObjects(SceneManager.GetSceneAt(i)); - - Scene ddolScene = DDOLFinder.GetDDOL().gameObject.scene; - if (ddolScene.isLoaded) - SetupSceneObjects(ddolScene); - } - - /// - /// Setup NetworkObjects in a scene. Should only be called when server is active. - /// - /// - private void SetupSceneObjects(Scene s) - { - ListCache nobs; - SceneFN.GetSceneNetworkObjects(s, false, out nobs); - - bool isHost = base.NetworkManager.IsHost; - - for (int i = 0; i < nobs.Written; i++) - { - NetworkObject nob = nobs.Collection[i]; - //Only setup if a scene object and not initialzied. - if (nob.IsNetworked && nob.IsSceneObject && nob.IsDeinitializing) - { - base.UpdateNetworkBehavioursForSceneObject(nob, true); - base.AddToSceneObjects(nob); - /* If was active in the editor (before hitting play), or currently active - * then PreInitialize without synchronizing to clients. There is no reason - * to synchronize to clients because the scene just loaded on server, - * which means clients are not yet in the scene. */ - if (nob.ActiveDuringEdit || nob.gameObject.activeInHierarchy) - { - //If not host then object doesn't need to be spawned until a client joins. - if (!isHost) - SetupWithoutSynchronization(nob); - //Otherwise spawn object so observers update for clientHost. - else - SpawnWithoutChecks(nob); - } - } - } - - ListCaches.StoreCache(nobs); - } - - /// - /// Performs setup on a NetworkObject without synchronizing the actions to clients. - /// - /// Override ObjectId to use. - private void SetupWithoutSynchronization(NetworkObject nob, NetworkConnection ownerConnection = null, int? objectId = null) - { - if (nob.IsNetworked) - { - if (objectId == null) - objectId = GetNextNetworkObjectId(); - nob.Preinitialize_Internal(NetworkManager, objectId.Value, ownerConnection, true); - base.AddToSpawned(nob, true); - nob.gameObject.SetActive(true); - nob.Initialize(true, true); - } - } - #endregion - - #region Spawning. - /// - /// Spawns an object over the network. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void Spawn(NetworkObject networkObject, NetworkConnection ownerConnection = null) - { - //Default as false, will change if needed. - bool predictedSpawn = false; - - if (networkObject == null) - { - base.NetworkManager.LogError($"Specified networkObject is null."); - return; - } - if (!NetworkManager.ServerManager.Started) - { - //Neither server nor client are started. - if (!NetworkManager.ClientManager.Started) - { - base.NetworkManager.LogWarning("Cannot spawn object because server nor client are active."); - return; - } - //Server has predicted spawning disabled. - if (!NetworkManager.PredictionManager.GetAllowPredictedSpawning()) - { - base.NetworkManager.LogWarning("Cannot spawn object because server is not active and predicted spawning is not enabled."); - return; - } - //Various predicted spawn checks. - if (!base.CanPredictedSpawn(networkObject, NetworkManager.ClientManager.Connection, ownerConnection, false)) - return; - - predictedSpawn = true; - } - if (!networkObject.gameObject.scene.IsValid()) - { - base.NetworkManager.LogError($"{networkObject.name} is a prefab. You must instantiate the prefab first, then use Spawn on the instantiated copy."); - return; - } - if (ownerConnection != null && ownerConnection.IsActive && !ownerConnection.LoadedStartScenes(!predictedSpawn)) - { - base.NetworkManager.LogWarning($"{networkObject.name} was spawned but it's recommended to not spawn objects for connections until they have loaded start scenes. You can be notified when a connection loads start scenes by using connection.OnLoadedStartScenes on the connection, or SceneManager.OnClientLoadStartScenes."); - } - if (networkObject.IsSpawned) - { - base.NetworkManager.LogWarning($"{networkObject.name} is already spawned."); - return; - } - if (networkObject.ParentNetworkObject != null && !networkObject.ParentNetworkObject.IsSpawned) - { - base.NetworkManager.LogError($"{networkObject.name} cannot be spawned because it has a parent NetworkObject {networkObject.ParentNetworkObject} which is not spawned."); - return; - } - - if (predictedSpawn) - base.NetworkManager.ClientManager.Objects.PredictedSpawn(networkObject, ownerConnection); - else - SpawnWithoutChecks(networkObject, ownerConnection); - } - - /// - /// Spawns networkObject without any checks. - /// - private void SpawnWithoutChecks(NetworkObject networkObject, NetworkConnection ownerConnection = null, int? objectId = null) - { - /* Setup locally without sending to clients. - * When observers are built for the network object - * during initialization spawn messages will - * be sent. */ - networkObject.SetIsNetworked(true); - _spawnCache.AddValue(networkObject); - SetupWithoutSynchronization(networkObject, ownerConnection, objectId); - - foreach (NetworkObject item in networkObject.ChildNetworkObjects) - { - /* Only spawn recursively if the nob state is unset. - * Unset indicates that the nob has not been */ - if (item.gameObject.activeInHierarchy || item.State == NetworkObjectState.Spawned) - SpawnWithoutChecks(item, ownerConnection); - } - - /* Copy to a new cache then reset _spawnCache - * just incase rebuilding observers would lead to - * more additions into _spawnCache. EG: rebuilding - * may result in additional objects being spawned - * for clients and if _spawnCache were not reset - * the same objects would be rebuilt again. This likely - * would not affect anything other than perf but who - * wants that. */ - ListCache spawnCacheCopy = ListCaches.GetNetworkObjectCache(); - spawnCacheCopy.AddValues(_spawnCache); - _spawnCache.Reset(); - //Also rebuild observers for the object so it spawns for others. - RebuildObservers(spawnCacheCopy); - - /* If also client then we need to make sure the object renderers have correct visibility. - * Set visibility based on if the observers contains the clientHost connection. */ - if (NetworkManager.IsClient) - { - int count = spawnCacheCopy.Written; - List collection = spawnCacheCopy.Collection; - for (int i = 0; i < count; i++) - collection[i].SetRenderersVisible(networkObject.Observers.Contains(NetworkManager.ClientManager.Connection)); - } - - ListCaches.StoreCache(spawnCacheCopy); - } - - /// - /// Reads a predicted spawn. - /// - internal void ReadPredictedSpawn(PooledReader reader, NetworkConnection conn) - { - sbyte initializeOrder; - ushort collectionId; - int prefabId; - int objectId = reader.ReadNetworkObjectForSpawn(out initializeOrder, out collectionId, out _); - //If objectId is not within predicted ids for conn. - if (!conn.PredictedObjectIds.Contains(objectId)) - { - reader.Clear(); - conn.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"Connection {conn.ClientId} used predicted spawning with a non-reserved objectId of {objectId}."); - return; - } - - NetworkConnection owner = reader.ReadNetworkConnection(); - SpawnType st = (SpawnType)reader.ReadByte(); - //Not used at the moment. - byte componentIndex = reader.ReadByte(); - - //Read transform values which differ from serialized values. - Vector3? localPosition; - Quaternion? localRotation; - Vector3? localScale; - base.ReadTransformProperties(reader, out localPosition, out localRotation, out localScale); - - NetworkObject nob; - bool isGlobal = false; - if (SpawnTypeEnum.Contains(st, SpawnType.Scene)) - { - ulong sceneId = reader.ReadUInt64(AutoPackType.Unpacked); - nob = base.GetSceneNetworkObject(sceneId); - if (!base.CanPredictedSpawn(nob, conn, owner, true)) - return; - } - else - { - //Not used right now. - SpawnParentType spt = (SpawnParentType)reader.ReadByte(); - prefabId = reader.ReadNetworkObjectId(); - //Invalid prefabId. - if (prefabId == NetworkObject.UNSET_PREFABID_VALUE) - { - reader.Clear(); - conn.Kick(KickReason.UnusualActivity, LoggingType.Common, $"Spawned object has an invalid prefabId of {prefabId}. Make sure all objects which are being spawned over the network are within SpawnableObjects on the NetworkManager. Connection {conn.ClientId} will be kicked immediately."); - return; - } - - PrefabObjects prefabObjects = NetworkManager.GetPrefabObjects(collectionId, false); - //PrefabObjects not found. - if (prefabObjects == null) - { - reader.Clear(); - conn.Kick(KickReason.UnusualActivity, LoggingType.Common, $"PrefabObjects collection is not found for CollectionId {collectionId}. Be sure to add your addressables NetworkObject prefabs to the collection on server and client before attempting to spawn them over the network. Connection {conn.ClientId} will be kicked immediately."); - return; - } - //Check if prefab allows predicted spawning. - NetworkObject nPrefab = prefabObjects.GetObject(true, prefabId); - if (!base.CanPredictedSpawn(nPrefab, conn, owner, true)) - return; - - nob = NetworkManager.GetPooledInstantiated(prefabId, false); - isGlobal = SpawnTypeEnum.Contains(st, SpawnType.InstantiatedGlobal); - } - - Transform t = nob.transform; - //Parenting predicted spawns is not supported yet. - t.SetParent(null, true); - base.GetTransformProperties(localPosition, localRotation, localScale, t, out Vector3 pos, out Quaternion rot, out Vector3 scale); - t.SetLocalPositionRotationAndScale(pos, rot, scale); - nob.SetIsGlobal(isGlobal); - - //Initialize for prediction. - nob.InitializePredictedObject_Server(base.NetworkManager, conn); - - /* Only read sync types if allowed for the object. - * If the client did happen to send synctypes while not allowed - * this will create a parse error on the server, - * resulting in the client being kicked. */ - if (nob.AllowPredictedSyncTypes) - { - ArraySegment syncValues = reader.ReadArraySegmentAndSize(); - PooledReader syncTypeReader = ReaderPool.GetReader(syncValues, base.NetworkManager); - foreach (NetworkBehaviour nb in nob.NetworkBehaviours) - { - //SyncVars. - int length = syncTypeReader.ReadInt32(); - nb.OnSyncType(syncTypeReader, length, false, true); - //SyncObjects - length = syncTypeReader.ReadInt32(); - nb.OnSyncType(syncTypeReader, length, true, true); - } - syncTypeReader.Dispose(); - } - - SpawnWithoutChecks(nob, owner, objectId); - - //Send the spawner a new reservedId. - WriteResponse(true); - //Writes a predicted spawn result to a client. - void WriteResponse(bool success) - { - PooledWriter writer = WriterPool.GetWriter(); - writer.WritePacketId(PacketId.PredictedSpawnResult); - writer.WriteNetworkObjectId(nob.ObjectId); - writer.WriteBoolean(success); - - if (success) - { - Queue objectIdCache = NetworkManager.ServerManager.Objects.GetObjectIdCache(); - //Write next objectId to use. - int invalidId = NetworkObject.UNSET_OBJECTID_VALUE; - int nextId = (objectIdCache.Count > 0) ? objectIdCache.Dequeue() : invalidId; - writer.WriteNetworkObjectId(nextId); - //If nextId is valid then also add it to spawners local cache. - if (nextId != invalidId) - conn.PredictedObjectIds.Enqueue(nextId); - ////Update RPC links. - //foreach (NetworkBehaviour nb in nob.NetworkBehaviours) - // nb.WriteRpcLinks(writer); - } - - conn.SendToClient((byte)Channel.Reliable, writer.GetArraySegment()); - } - - } - #endregion - - #region Despawning. - /// - /// Cleans recently despawned objects. - /// - private void CleanRecentlyDespawned() - { - //Only iterate if frame ticked to save perf. - if (!base.NetworkManager.TimeManager.FrameTicked) - return; - - ListCache intCache = ListCaches.GetIntCache(); - - uint requiredTicks = _cleanRecentlyDespawnedMaxTicks; - uint currentTick = base.NetworkManager.TimeManager.LocalTick; - //Iterate 20, or 5% of the collection, whichever is higher. - int iterations = Mathf.Max(20, (int)(RecentlyDespawnedIds.Count * 0.05f)); - /* Given this is a dictionary there is no gaurantee which order objects are - * added. Because of this it's possible some objects may take much longer to - * be removed. This is okay so long as a consistent chunk of objects are removed - * at a time; eventually all objects will be iterated. */ - int count = 0; - foreach (KeyValuePair kvp in RecentlyDespawnedIds) - { - long result = (currentTick - kvp.Value); - //If enough ticks have passed to remove. - if (result > requiredTicks) - intCache.AddValue(kvp.Key); - - count++; - if (count == iterations) - break; - } - - //Remove cached entries. - List collection = intCache.Collection; - int cCount = collection.Count; - for (int i = 0; i < cCount; i++) - RecentlyDespawnedIds.Remove(collection[i]); - - ListCaches.StoreCache(intCache); - } - /// - /// Returns if an objectId was recently despawned. - /// - /// ObjectId to check. - /// Passed ticks to be within to be considered recently despawned. - /// True if an objectId was despawned with specified number of ticks. - public bool RecentlyDespawned(int objectId, uint ticks) - { - uint despawnTick; - if (!RecentlyDespawnedIds.TryGetValue(objectId, out despawnTick)) - return false; - - return ((NetworkManager.TimeManager.LocalTick - despawnTick) <= ticks); - } - /// - /// Adds to objects pending destroy due to clientHost environment. - /// - /// - internal void AddToPending(NetworkObject nob) - { - _pendingDestroy[nob.ObjectId] = nob; - } - /// - /// Tries to removes objectId from PendingDestroy and returns if successful. - /// - internal bool RemoveFromPending(int objectId) - { - return _pendingDestroy.Remove(objectId); - } - /// - /// Returns a NetworkObject in PendingDestroy. - /// - internal NetworkObject GetFromPending(int objectId) - { - NetworkObject nob; - _pendingDestroy.TryGetValue(objectId, out nob); - return nob; - } - /// - /// Destroys NetworkObjects pending for destruction. - /// - internal void DestroyPending() - { - foreach (NetworkObject item in _pendingDestroy.Values) - { - if (item != null) - MonoBehaviour.Destroy(item.gameObject); - } - - _pendingDestroy.Clear(); - } - - /// - /// Despawns an object over the network. - /// - internal override void Despawn(NetworkObject networkObject, DespawnType despawnType, bool asServer) - { - //Default as false, will change if needed. - bool predictedDespawn = false; - - if (networkObject == null) - { - base.NetworkManager.LogWarning($"NetworkObject cannot be despawned because it is null."); - return; - } - if (networkObject.IsDeinitializing) - { - base.NetworkManager.LogWarning($"Object {networkObject.name} cannot be despawned because it is already deinitializing."); - return; - } - - if (!NetworkManager.ServerManager.Started) - { - //Neither server nor client are started. - if (!NetworkManager.ClientManager.Started) - { - base.NetworkManager.LogWarning("Cannot despawn object because server nor client are active."); - return; - } - //Server has predicted spawning disabled. - if (!NetworkManager.PredictionManager.GetAllowPredictedSpawning()) - { - base.NetworkManager.LogWarning("Cannot despawn object because server is not active and predicted spawning is not enabled."); - return; - } - //Various predicted despawn checks. - if (!base.CanPredictedDespawn(networkObject, NetworkManager.ClientManager.Connection, false)) - return; - - predictedDespawn = true; - } - if (!networkObject.gameObject.scene.IsValid()) - { - base.NetworkManager.LogError($"{networkObject.name} is a prefab. You must instantiate the prefab first, then use Spawn on the instantiated copy."); - return; - } - - if (predictedDespawn) - { - base.NetworkManager.ClientManager.Objects.PredictedDespawn(networkObject); - } - else - { - FinalizeDespawn(networkObject, despawnType); - RecentlyDespawnedIds[networkObject.ObjectId] = base.NetworkManager.TimeManager.LocalTick; - base.Despawn(networkObject, despawnType, asServer); - } - } - - /// - /// Called when a NetworkObject is destroyed without being deactivated first. - /// - /// - internal override void NetworkObjectUnexpectedlyDestroyed(NetworkObject nob, bool asServer) - { - FinalizeDespawn(nob, DespawnType.Destroy); - base.NetworkObjectUnexpectedlyDestroyed(nob, asServer); - } - - /// - /// Finalizes the despawn process. By the time this is called the object is considered unaccessible. - /// - /// - private void FinalizeDespawn(NetworkObject nob, DespawnType despawnType) - { - if (nob != null && nob.ObjectId != NetworkObject.UNSET_OBJECTID_VALUE) - { - nob.WriteDirtySyncTypes(); - WriteDespawnAndSend(nob, despawnType); - CacheObjectId(nob); - } - } - - /// - /// Writes a despawn and sends it to clients. - /// - /// - private void WriteDespawnAndSend(NetworkObject nob, DespawnType despawnType) - { - PooledWriter everyoneWriter = WriterPool.GetWriter(); - WriteDespawn(nob, despawnType, everyoneWriter); - - ArraySegment despawnSegment = everyoneWriter.GetArraySegment(); - - //Add observers to a list cache. - ListCache cache = ListCaches.GetNetworkConnectionCache(); - cache.Reset(); - cache.AddValues(nob.Observers); - int written = cache.Written; - for (int i = 0; i < written; i++) - { - //Invoke ondespawn and send despawn. - NetworkConnection conn = cache.Collection[i]; - nob.InvokeOnServerDespawn(conn); - NetworkManager.TransportManager.SendToClient((byte)Channel.Reliable, despawnSegment, conn); - //Remove from observers. - //nob.Observers.Remove(conn); - } - - everyoneWriter.Dispose(); - ListCaches.StoreCache(cache); - } - /// - /// Reads a predicted despawn. - /// - internal void ReadPredictedDespawn(Reader reader, NetworkConnection conn) - { - NetworkObject nob = reader.ReadNetworkObject(); - - //Maybe server destroyed the object so don't kick if null. - if (nob == null) - { - reader.Clear(); - return; - } - //Does not allow predicted despawning. - if (!nob.AllowPredictedDespawning) - { - reader.Clear(); - conn.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"Connection {conn.ClientId} used predicted despawning for object {nob.name} when it does not support predicted despawning."); - } - - //Despawn object. - nob.Despawn(); - } - #endregion - } - - -} diff --git a/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.cs.meta b/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.cs.meta deleted file mode 100644 index ba10d54..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/Object/ServerObjects.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d5e7f3005cbc7924f99819311c58651a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Server/ServerManager.Broadcast.cs b/Assets/FishNet/Runtime/Managing/Server/ServerManager.Broadcast.cs deleted file mode 100644 index f3404cd..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/ServerManager.Broadcast.cs +++ /dev/null @@ -1,457 +0,0 @@ -using FishNet.Broadcast; -using FishNet.Broadcast.Helping; -using FishNet.Connection; -using FishNet.Managing.Logging; -using FishNet.Managing.Utility; -using FishNet.Object; -using FishNet.Serializing; -using FishNet.Serializing.Helping; -using FishNet.Transporting; -using FishNet.Utility.Extension; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Managing.Server -{ - public sealed partial class ServerManager : MonoBehaviour - { - #region Private. - /// - /// Delegate to read received broadcasts. - /// - /// - /// - private delegate void ClientBroadcastDelegate(NetworkConnection connection, PooledReader reader); - /// - /// Delegates for each key. - /// - private readonly Dictionary> _broadcastHandlers = new Dictionary>(); - /// - /// Delegate targets for each key. - /// - private Dictionary> _handlerTargets = new Dictionary>(); - /// - /// Connections which can be broadcasted to after having excluded removed. - /// - private HashSet _connectionsWithoutExclusions = new HashSet(); - #endregion - - /// - /// Registers a method to call when a Broadcast arrives. - /// - /// Type of broadcast being registered. - /// Method to call. - /// True if the client must be authenticated for the method to call. - public void RegisterBroadcast(Action handler, bool requireAuthentication = true) where T : struct, IBroadcast - { - ushort key = BroadcastHelper.GetKey(); - - /* Create delegate and add for - * handler method. */ - HashSet handlers; - if (!_broadcastHandlers.TryGetValueIL2CPP(key, out handlers)) - { - handlers = new HashSet(); - _broadcastHandlers.Add(key, handlers); - } - ClientBroadcastDelegate del = CreateBroadcastDelegate(handler, requireAuthentication); - handlers.Add(del); - - /* Add hashcode of target for handler. - * This is so we can unregister the target later. */ - int handlerHashCode = handler.GetHashCode(); - HashSet<(int, ClientBroadcastDelegate)> targetHashCodes; - if (!_handlerTargets.TryGetValueIL2CPP(key, out targetHashCodes)) - { - targetHashCodes = new HashSet<(int, ClientBroadcastDelegate)>(); - _handlerTargets.Add(key, targetHashCodes); - } - - targetHashCodes.Add((handlerHashCode, del)); - } - - /// - /// Unregisters a method call from a Broadcast type. - /// - /// Type of broadcast being unregistered. - /// Method to unregister. - public void UnregisterBroadcast(Action handler) where T : struct, IBroadcast - { - ushort key = BroadcastHelper.GetKey(); - - /* If key is found for T then look for - * the appropriate handler to remove. */ - if (_broadcastHandlers.TryGetValueIL2CPP(key, out HashSet handlers)) - { - HashSet<(int, ClientBroadcastDelegate)> targetHashCodes; - if (_handlerTargets.TryGetValueIL2CPP(key, out targetHashCodes)) - { - int handlerHashCode = handler.GetHashCode(); - ClientBroadcastDelegate result = null; - foreach ((int targetHashCode, ClientBroadcastDelegate del) in targetHashCodes) - { - if (targetHashCode == handlerHashCode) - { - result = del; - targetHashCodes.Remove((targetHashCode, del)); - break; - } - } - //If no more in targetHashCodes then remove from handlerTarget. - if (targetHashCodes.Count == 0) - _handlerTargets.Remove(key); - - if (result != null) - handlers.Remove(result); - } - - //If no more in handlers then remove broadcastHandlers. - if (handlers.Count == 0) - _broadcastHandlers.Remove(key); - } - } - - /// - /// Creates a ClientBroadcastDelegate. - /// - /// - /// - /// - /// - private ClientBroadcastDelegate CreateBroadcastDelegate(Action handler, bool requireAuthentication) - { - void LogicContainer(NetworkConnection connection, PooledReader reader) - { - //If requires authentication and client isn't authenticated. - if (requireAuthentication && !connection.Authenticated) - { - connection.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"ConnectionId {connection.ClientId} sent broadcast {typeof(T).Name} which requires authentication, but client was not authenticated. Client has been disconnected."); - return; - } - - T broadcast = reader.Read(); - handler?.Invoke(connection, broadcast); - } - return LogicContainer; - } - - /// - /// Parses a received broadcast. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ParseBroadcast(PooledReader reader, NetworkConnection conn, Channel channel) - { - ushort key = reader.ReadUInt16(); - int dataLength = Packets.GetPacketLength((ushort)PacketId.Broadcast, reader, channel); - - //Try to invoke the handler for that message - if (_broadcastHandlers.TryGetValueIL2CPP(key, out HashSet handlers)) - { - int readerStartPosition = reader.Position; - /* //muchlater resetting the position could be better by instead reading once and passing in - * the object to invoke with. */ - bool rebuildHandlers = false; - //True if data is read at least once. Otherwise it's length will have to be purged. - bool dataRead = false; - foreach (ClientBroadcastDelegate handler in handlers) - { - if (handler.Target == null) - { - NetworkManager.LogWarning($"A Broadcast handler target is null. This can occur when a script is destroyed but does not unregister from a Broadcast."); - rebuildHandlers = true; - } - else - { - reader.Position = readerStartPosition; - handler.Invoke(conn, reader); - dataRead = true; - } - } - - //If rebuilding handlers... - if (rebuildHandlers) - { - List dels = handlers.ToList(); - handlers.Clear(); - for (int i = 0; i < dels.Count; i++) - { - if (dels[i].Target != null) - handlers.Add(dels[i]); - } - } - //Make sure data was read as well. - if (!dataRead) - reader.Skip(dataLength); - } - else - { - reader.Skip(dataLength); - } - } - - /// - /// Sends a broadcast to a connection. - /// - /// Type of broadcast to send. - /// Connection to send to. - /// Broadcast data being sent; for example: an instance of your broadcast type. - /// True if the client must be authenticated for this broadcast to send. - /// Channel to send on. - public void Broadcast(NetworkConnection connection, T message, bool requireAuthenticated = true, Channel channel = Channel.Reliable) where T : struct, IBroadcast - { - if (!Started) - { - NetworkManager.LogWarning($"Cannot send broadcast to client because server is not active."); - return; - } - if (requireAuthenticated && !connection.Authenticated) - { - NetworkManager.LogWarning($"Cannot send broadcast to client because they are not authenticated."); - return; - } - - using (PooledWriter writer = WriterPool.GetWriter()) - { - Broadcasts.WriteBroadcast(writer, message, channel); - ArraySegment segment = writer.GetArraySegment(); - NetworkManager.TransportManager.SendToClient((byte)channel, segment, connection); - } - } - - - /// - /// Sends a broadcast to connections. - /// - /// Type of broadcast to send. - /// Connections to send to. - /// Broadcast data being sent; for example: an instance of your broadcast type. - /// True if the clients must be authenticated for this broadcast to send. - /// Channel to send on. - public void Broadcast(HashSet connections, T message, bool requireAuthenticated = true, Channel channel = Channel.Reliable) where T : struct, IBroadcast - { - if (!Started) - { - NetworkManager.LogWarning($"Cannot send broadcast to client because server is not active."); - return; - } - - bool failedAuthentication = false; - using (PooledWriter writer = WriterPool.GetWriter()) - { - Broadcasts.WriteBroadcast(writer, message, channel); - ArraySegment segment = writer.GetArraySegment(); - - foreach (NetworkConnection conn in connections) - { - if (requireAuthenticated && !conn.Authenticated) - failedAuthentication = true; - else - NetworkManager.TransportManager.SendToClient((byte)channel, segment, conn); - } - } - - if (failedAuthentication) - { - NetworkManager.LogWarning($"One or more broadcast did not send to a client because they were not authenticated."); - return; - } - } - - - /// - /// Sends a broadcast to connections except excluded. - /// - /// Type of broadcast to send. - /// Connections to send to. - /// Connection to exclude. - /// Broadcast data being sent; for example: an instance of your broadcast type. - /// True if the clients must be authenticated for this broadcast to send. - /// Channel to send on. - public void BroadcastExcept(HashSet connections, NetworkConnection excludedConnection, T message, bool requireAuthenticated = true, Channel channel = Channel.Reliable) where T : struct, IBroadcast - { - if (!Started) - { - NetworkManager.LogWarning($"Cannot send broadcast to client because server is not active."); - return; - } - - //Fast exit if no exclusions. - if (excludedConnection == null || !excludedConnection.IsValid) - { - Broadcast(connections, message, requireAuthenticated, channel); - return; - } - - connections.Remove(excludedConnection); - Broadcast(connections, message, requireAuthenticated, channel); - } - - - /// - /// Sends a broadcast to connections except excluded. - /// - /// Type of broadcast to send. - /// Connections to send to. - /// Connections to exclude. - /// Broadcast data being sent; for example: an instance of your broadcast type. - /// True if the clients must be authenticated for this broadcast to send. - /// Channel to send on. - public void BroadcastExcept(HashSet connections, HashSet excludedConnections, T message, bool requireAuthenticated = true, Channel channel = Channel.Reliable) where T : struct, IBroadcast - { - if (!Started) - { - NetworkManager.LogWarning($"Cannot send broadcast to client because server is not active."); - return; - } - - //Fast exit if no exclusions. - if (excludedConnections == null || excludedConnections.Count == 0) - { - Broadcast(connections, message, requireAuthenticated, channel); - return; - } - - /* I'm not sure if the hashset API such as intersect generates - * GC or not but I'm betting doing remove locally is faster, or - * just as fast. */ - foreach (NetworkConnection ec in excludedConnections) - connections.Remove(ec); - - Broadcast(connections, message, requireAuthenticated, channel); - } - - /// - /// Sends a broadcast to all connections except excluded. - /// - /// Type of broadcast to send. - /// Connection to exclude. - /// Broadcast data being sent; for example: an instance of your broadcast type. - /// True if the clients must be authenticated for this broadcast to send. - /// Channel to send on. - public void BroadcastExcept(NetworkConnection excludedConnection, T message, bool requireAuthenticated = true, Channel channel = Channel.Reliable) where T : struct, IBroadcast - { - if (!Started) - { - NetworkManager.LogWarning($"Cannot send broadcast to client because server is not active."); - return; - } - - //Fast exit if there are no excluded. - if (excludedConnection == null || !excludedConnection.IsValid) - { - Broadcast(message, requireAuthenticated, channel); - return; - } - - _connectionsWithoutExclusions.Clear(); - /* It will be faster to fill the entire list then - * remove vs checking if each connection is contained within excluded. */ - foreach (NetworkConnection c in Clients.Values) - _connectionsWithoutExclusions.Add(c); - //Remove - _connectionsWithoutExclusions.Remove(excludedConnection); - - Broadcast(_connectionsWithoutExclusions, message, requireAuthenticated, channel); - } - - /// - /// Sends a broadcast to all connections except excluded. - /// - /// Type of broadcast to send. - /// Connections to send to. - /// Broadcast data being sent; for example: an instance of your broadcast type. - /// True if the clients must be authenticated for this broadcast to send. - /// Channel to send on. - public void BroadcastExcept(HashSet excludedConnections, T message, bool requireAuthenticated = true, Channel channel = Channel.Reliable) where T : struct, IBroadcast - { - if (!Started) - { - NetworkManager.LogWarning($"Cannot send broadcast to client because server is not active."); - return; - } - - //Fast exit if there are no excluded. - if (excludedConnections == null || excludedConnections.Count == 0) - { - Broadcast(message, requireAuthenticated, channel); - return; - } - - _connectionsWithoutExclusions.Clear(); - /* It will be faster to fill the entire list then - * remove vs checking if each connection is contained within excluded. */ - foreach (NetworkConnection c in Clients.Values) - _connectionsWithoutExclusions.Add(c); - //Remove - foreach (NetworkConnection c in excludedConnections) - _connectionsWithoutExclusions.Remove(c); - - Broadcast(_connectionsWithoutExclusions, message, requireAuthenticated, channel); - } - - /// - /// Sends a broadcast to observers. - /// - /// Type of broadcast to send. - /// NetworkObject to use Observers from. - /// Broadcast data being sent; for example: an instance of your broadcast type. - /// True if the clients must be authenticated for this broadcast to send. - /// Channel to send on. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Broadcast(NetworkObject networkObject, T message, bool requireAuthenticated = true, Channel channel = Channel.Reliable) where T : struct, IBroadcast - { - if (networkObject == null) - { - NetworkManager.LogWarning($"Cannot send broadcast because networkObject is null."); - return; - } - - Broadcast(networkObject.Observers, message, requireAuthenticated, channel); - } - - - /// - /// Sends a broadcast to all clients. - /// - /// Type of broadcast to send. - /// Broadcast data being sent; for example: an instance of your broadcast type. - /// True if the clients must be authenticated for this broadcast to send. - /// Channel to send on. - public void Broadcast(T message, bool requireAuthenticated = true, Channel channel = Channel.Reliable) where T : struct, IBroadcast - { - if (!Started) - { - NetworkManager.LogWarning($"Cannot send broadcast to client because server is not active."); - return; - } - - bool failedAuthentication = false; - using (PooledWriter writer = WriterPool.GetWriter()) - { - Broadcasts.WriteBroadcast(writer, message, channel); - ArraySegment segment = writer.GetArraySegment(); - - foreach (NetworkConnection conn in Clients.Values) - { - // - if (requireAuthenticated && !conn.Authenticated) - failedAuthentication = true; - else - NetworkManager.TransportManager.SendToClient((byte)channel, segment, conn); - } - } - - if (failedAuthentication) - { - NetworkManager.LogWarning($"One or more broadcast did not send to a client because they were not authenticated."); - return; - } - } - - } - - -} diff --git a/Assets/FishNet/Runtime/Managing/Server/ServerManager.Broadcast.cs.meta b/Assets/FishNet/Runtime/Managing/Server/ServerManager.Broadcast.cs.meta deleted file mode 100644 index e0fdef7..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/ServerManager.Broadcast.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1cd9dcd58556e27449ce5cb0d70611cb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Server/ServerManager.LOD.cs b/Assets/FishNet/Runtime/Managing/Server/ServerManager.LOD.cs deleted file mode 100644 index 7829e2a..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/ServerManager.LOD.cs +++ /dev/null @@ -1,231 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing.Logging; -using FishNet.Object; -using FishNet.Serializing; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Managing.Server -{ - public sealed partial class ServerManager : MonoBehaviour - { - #region Private. - /// - /// Cached expected level of detail value. - /// - private uint _cachedLevelOfDetailInterval; - /// - /// Cached value of UseLod. - /// - private bool _cachedUseLod; - #endregion - - /// - /// Parses a received network LOD update. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ParseNetworkLODUpdate(PooledReader reader, NetworkConnection conn) - { - if (!conn.Authenticated) - return; - if (!NetworkManager.ObserverManager.GetUseNetworkLod()) - { - conn.Kick(reader, KickReason.ExploitAttempt, LoggingType.Common, $"Connection [{conn.ClientId}] sent a level of detail update when the feature is not enabled."); - return; - } - - /* If local client then read out entries but do nothing. - * Local client doesn't technically have to send LOD because - * it's set on the client side but this code is kept in - * to simulate actual bandwidth. */ - if (conn.IsLocalClient) - { - int w = reader.ReadInt32(); - for (int i = 0; i < w; i++) - ReadLod(out _, out _); - return; - } - - uint packetTick = conn.LastPacketTick; - //Check if conn can send LOD. - uint lastLod = conn.LastLevelOfDetailUpdate; - //If previously set see if client is potentially exploiting. - if (lastLod != 0) - { - if ((packetTick - lastLod) < _cachedLevelOfDetailInterval) - { - conn.Kick(reader, KickReason.ExploitAttempt, LoggingType.Common, $"Connection [{conn.ClientId}] sent excessive level of detail updates."); - return; - } - } - //Set last recv lod. - conn.LastLevelOfDetailUpdate = packetTick; - - //Get server objects to save calls. - Dictionary serverObjects = Objects.Spawned; - //Get level of details for this connection and reset them. - Dictionary levelOfDetails = conn.LevelOfDetails; - - int written = reader.ReadInt32(); - - /* //TODO There is still an instance where client could simply say no LODs need - * updating and never update for their objects in the first place. This can be resolved - * by adding an observed object count to each connection and compare that to - * the size of the LOD collection. */ - - //Only process if some are written. - if (written > 0) - { - //Maximum infractions before a kick. - const int maximumInfractions = 15; - int currentInfractions = conn.LevelOfDetailInfractions; - int infractionsCounted = 0; - - /* If the connection has no objects then LOD isn't capable - * of being calculated. It's possible the players object was destroyed after - * the LOD sent but we don't know for sure without adding extra checks. - * Rather than add recently destroyed player object checks if there are - * no player objects then just add an infraction. The odds of this happening regularly - * are pretty slim. */ - if (conn.Objects.Count == 0) - { - if (AddInfraction(3)) - { - conn.Kick(reader, KickReason.UnusualActivity, LoggingType.Common, $"Connection [{conn.ClientId}] has sent an excessive number of level of detail updates without having any player objects spawned."); - return; - } - } - - /* If written is more than spawned + recently despawned then - * the client is likely trying to exploit. */ - if (written > (Objects.Spawned.Count + Objects.RecentlyDespawnedIds.Count)) - { - conn.Kick(reader, KickReason.UnusualActivity, LoggingType.Common, $"Connection [{conn.ClientId}] sent a level of detail update for {written} items which exceeds spawned and recently despawned count."); - return; - } - - Vector3 connObjectPosition = Vector3.zero; - //Pick a random object from the player to sample. - int objectIndex = UnityEngine.Random.Range(0, conn.Objects.Count); - int connObjectIteration = 0; - foreach (NetworkObject n in conn.Objects) - { - if (connObjectIteration == objectIndex) - { - connObjectPosition = n.transform.position; - //Flag to indicate found. - objectIndex = -1; - break; - } - } - //Server somehow messed up. Should not be possible. - if (objectIndex != -1) - { - NetworkManager.LogError($"An object index of {objectIndex} could not be populated. Connection [{conn.ClientId}] object count is {conn.Objects.Count}."); - return; - } - - //Sample at most x entries per update. - int samplesRemaining = 10; - //Chance to sample an update. - const float sampleChance = 0.05f; - - List lodDistances = NetworkManager.ObserverManager.GetLevelOfDetailDistances(); - int lodDistancesCount = lodDistances.Count; - for (int i = 0; i < written; i++) - { - int objectId; - byte lod; - ReadLod(out objectId, out lod); - - //Lod is not possible. - if (lod >= lodDistancesCount) - { - conn.Kick(reader, KickReason.ExploitAttempt, LoggingType.Common, $"Connection [{conn.ClientId}] provided a level of detail index which is out of bounds."); - return; - } - - //Found in spawned, update lod. - if (serverObjects.TryGetValue(objectId, out NetworkObject nob)) - { - //Value is unchanged. - if (levelOfDetails.TryGetValue(nob, out byte oldLod)) - { - bool oldMatches = (oldLod == lod); - if (oldMatches && AddInfraction()) - { - conn.Kick(reader, KickReason.UnusualActivity, LoggingType.Common, $"Connection [{conn.ClientId}] has excessively sent unchanged LOD information."); - return; - } - } - //If to sample. - if (samplesRemaining > 0 && UnityEngine.Random.Range(0f, 1f) <= sampleChance) - { - samplesRemaining--; - /* Only check if lod is less than maximum. - * If the client is hacking lods to specify maximum - * they are only doing the server a favor and hurting - * themselves with slower updates. */ - if (lod < (lodDistancesCount - 1)) - { - float specifiedLodDistance = lodDistances[lod]; - float sqrMag = Vector3.SqrMagnitude(connObjectPosition - nob.transform.position); - /* If the found distance is actually larger than what client specified - * then it's possible client may be sending fake LODs. */ - if (sqrMag > specifiedLodDistance) - { - if (AddInfraction()) - { - conn.Kick(reader, KickReason.UnusualActivity, LoggingType.Common, $"Connection [{conn.ClientId}] provided an excessive number of incorrect LOD values."); - return; - } - } - } - } - - levelOfDetails[nob] = lod; - } - //Not found in spawn; validate that client isn't trying to exploit. - else - { - //Too many infractions. - if (AddInfraction()) - { - conn.Kick(reader, KickReason.UnusualActivity, LoggingType.Common, $"Connection [{conn.ClientId}] has accumulated excessive level of detail infractions."); - return; - } - } - } - - //Adds an infraction returning if maximum infractions have been exceeded. - bool AddInfraction(int count = 1) - { - /* Only increase infractions at most 3 per iteration. - * This is to prevent a kick if the client perhaps had - * a massive lag spike. */ - if (infractionsCounted < 3) - infractionsCounted += count; - - bool overLimit = ((currentInfractions + infractionsCounted) >= maximumInfractions); - return overLimit; - } - } - - //Reads a LOD. - void ReadLod(out int lObjectId, out byte lLod) - { - lObjectId = reader.ReadNetworkObjectId(); - lLod = reader.ReadByte(); - } - - //Remove an infraction. This will steadily remove infractions over time. - if (conn.LevelOfDetailInfractions > 0) - conn.LevelOfDetailInfractions--; - } - - - } - - -} diff --git a/Assets/FishNet/Runtime/Managing/Server/ServerManager.LOD.cs.meta b/Assets/FishNet/Runtime/Managing/Server/ServerManager.LOD.cs.meta deleted file mode 100644 index 1868733..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/ServerManager.LOD.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e472255008ae291498f55f5f2a704ab2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Server/ServerManager.QOL.cs b/Assets/FishNet/Runtime/Managing/Server/ServerManager.QOL.cs deleted file mode 100644 index 66da54b..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/ServerManager.QOL.cs +++ /dev/null @@ -1,199 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing.Logging; -using FishNet.Managing.Transporting; -using FishNet.Object; -using FishNet.Serializing; -using FishNet.Transporting; -using FishNet.Transporting.Multipass; -using System; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Managing.Server -{ - public sealed partial class ServerManager : MonoBehaviour - { - #region Public. - /// - /// Called when a client is removed from the server using Kick. This is invoked before the client is disconnected. - /// NetworkConnection when available, clientId, and KickReason are provided. - /// - public event Action OnClientKick; - #endregion - - /// - /// Returns true if only one server is started. - /// - /// - public bool OneServerStarted() - { - int startedCount = 0; - TransportManager tm = NetworkManager.TransportManager; - //If using multipass check all transports. - if (tm.Transport is Multipass mp) - { - - foreach (Transport t in mp.Transports) - { - //Another transport is started, no need to load start scenes again. - if (t.GetConnectionState(true) == LocalConnectionState.Started) - startedCount++; - } - } - //Not using multipass. - else - { - if (tm.Transport.GetConnectionState(true) == LocalConnectionState.Started) - startedCount = 1; - } - - return (startedCount == 1); - } - - /// - /// Returns true if any server socket is in the started state. - /// - /// When set the transport on this index will be ignored. This value is only used with Multipass. - /// - public bool AnyServerStarted(int? excludedIndex = null) - { - TransportManager tm = NetworkManager.TransportManager; - //If using multipass check all transports. - if (tm.Transport is Multipass mp) - { - //Get transport which had state changed. - Transport excludedTransport = (excludedIndex == null) ? null : mp.GetTransport(excludedIndex.Value); - - foreach (Transport t in mp.Transports) - { - /* Skip t if is the transport that had it's state changed. - * We are looking for other transports already in started. */ - if (t == excludedTransport) - continue; - //Another transport is started, no need to load start scenes again. - if (t.GetConnectionState(true) == LocalConnectionState.Started) - return true; - } - } - //Not using multipass. - else - { - return (tm.Transport.GetConnectionState(true) == LocalConnectionState.Started); - } - - //Fall through, none started. - return false; - } - - /// - /// Spawns an object over the network. Can only be called on the server. - /// - /// GameObject instance to spawn. - /// Connection to give ownership to. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Spawn(GameObject go, NetworkConnection ownerConnection = null) - { - if (go == null) - { - NetworkManager.LogWarning($"GameObject cannot be spawned because it is null."); - return; - } - - NetworkObject nob = go.GetComponent(); - Spawn(nob, ownerConnection); - } - - - /// - /// Spawns an object over the network. Can only be called on the server. - /// - /// MetworkObject instance to spawn. - /// Connection to give ownership to. - public void Spawn(NetworkObject nob, NetworkConnection ownerConnection = null) - { - Objects.Spawn(nob, ownerConnection); - } - - /// - /// Despawns an object over the network. Can only be called on the server. - /// - /// GameObject instance to despawn. - /// Overrides the default DisableOnDespawn value for this single despawn. Scene objects will never be destroyed. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Despawn(GameObject go, DespawnType? despawnType = null) - { - if (go == null) - { - NetworkManager.LogWarning($"GameObject cannot be despawned because it is null."); - return; - } - - NetworkObject nob = go.GetComponent(); - Despawn(nob, despawnType); - } - - /// - /// Despawns an object over the network. Can only be called on the server. - /// - /// NetworkObject instance to despawn. - /// Despawn override type. - public void Despawn(NetworkObject networkObject, DespawnType? despawnType = null) - { - DespawnType resolvedDespawnType = (despawnType == null) - ? networkObject.GetDefaultDespawnType() - : despawnType.Value; - Objects.Despawn(networkObject, resolvedDespawnType, true); - } - - /// - /// Kicks a connection immediately while invoking OnClientKick. - /// - /// Client to kick. - /// Reason client is being kicked. - /// How to print logging as. - /// Optional message to be debug logged. - public void Kick(NetworkConnection conn, KickReason kickReason, LoggingType loggingType = LoggingType.Common, string log = "") - { - if (!conn.IsValid) - return; - - OnClientKick?.Invoke(conn, conn.ClientId, kickReason); - if (conn.IsActive) - conn.Disconnect(true); - - if (!string.IsNullOrEmpty(log)) - NetworkManager.Log(loggingType, log); - } - - /// - /// Kicks a connection immediately while invoking OnClientKick. - /// - /// ClientId to kick. - /// Reason client is being kicked. - /// How to print logging as. - /// Optional message to be debug logged. - public void Kick(int clientId, KickReason kickReason, LoggingType loggingType = LoggingType.Common, string log = "") - { - OnClientKick?.Invoke(null, clientId, kickReason); - NetworkManager.TransportManager.Transport.StopConnection(clientId, true); - if (!string.IsNullOrEmpty(log)) - NetworkManager.Log(loggingType, log); - } - - /// - /// Kicks a connection immediately while invoking OnClientKick. - /// - /// Client to kick. - /// Reader to clear before kicking. - /// Reason client is being kicked. - /// How to print logging as. - /// Optional message to be debug logged. - public void Kick(NetworkConnection conn, Reader reader, KickReason kickReason, LoggingType loggingType = LoggingType.Common, string log = "") - { - reader.Clear(); - Kick(conn, kickReason, loggingType, log); - } - } - - -} diff --git a/Assets/FishNet/Runtime/Managing/Server/ServerManager.QOL.cs.meta b/Assets/FishNet/Runtime/Managing/Server/ServerManager.QOL.cs.meta deleted file mode 100644 index 2ff8199..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/ServerManager.QOL.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f2a07d9984be21648bc714ea03bd0d70 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Server/ServerManager.RpcLinks.cs b/Assets/FishNet/Runtime/Managing/Server/ServerManager.RpcLinks.cs deleted file mode 100644 index b258950..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/ServerManager.RpcLinks.cs +++ /dev/null @@ -1,78 +0,0 @@ -using FishNet.Object; -using FishNet.Transporting; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.Managing.Server -{ - - public sealed partial class ServerManager : MonoBehaviour - { - - - #region Internal - /// - /// Current RPCLinks. - /// - internal Dictionary RpcLinks = new Dictionary(); - /// - /// RPCLink indexes which can be used. - /// - private Queue _availableRpcLinkIndexes = new Queue(); - #endregion - - /// - /// Initializes RPC Links for NetworkBehaviours. - /// - private void InitializeRpcLinks() - { - /* Brute force enum values. - * Linq Last/Max lookup throws for IL2CPP. */ - ushort highestValue = 0; - Array pidValues = Enum.GetValues(typeof(PacketId)); - foreach (PacketId pid in pidValues) - highestValue = Math.Max(highestValue, (ushort)pid); - - highestValue += 1; - for (ushort i = highestValue; i < ushort.MaxValue; i++) - _availableRpcLinkIndexes.Enqueue(i); - } - - /// - /// Sets the next RPC Link to use. - /// - /// True if a link was available and set. - internal bool GetRpcLink(out ushort value) - { - if (_availableRpcLinkIndexes.Count > 0) - { - value = _availableRpcLinkIndexes.Dequeue(); - return true; - } - else - { - value = 0; - return false; - } - } - - /// - /// Sets data to RpcLinks for linkIndex. - /// - internal void SetRpcLink(ushort linkIndex, RpcLink data) - { - RpcLinks[linkIndex] = data; - } - - /// - /// Returns RPCLinks to availableRpcLinkIndexes. - /// - internal void StoreRpcLinks(Dictionary links) - { - foreach (RpcLinkType rlt in links.Values) - _availableRpcLinkIndexes.Enqueue(rlt.LinkIndex); - } - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Server/ServerManager.RpcLinks.cs.meta b/Assets/FishNet/Runtime/Managing/Server/ServerManager.RpcLinks.cs.meta deleted file mode 100644 index 00ff24f..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/ServerManager.RpcLinks.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b9f0a4620d06f5c41b01f20af3f90634 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Server/ServerManager.cs b/Assets/FishNet/Runtime/Managing/Server/ServerManager.cs deleted file mode 100644 index a474dd3..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/ServerManager.cs +++ /dev/null @@ -1,759 +0,0 @@ -using FishNet.Authenticating; -using FishNet.Component.Observing; -using FishNet.Connection; -using FishNet.Managing.Debugging; -using FishNet.Managing.Logging; -using FishNet.Managing.Predicting; -using FishNet.Managing.Transporting; -using FishNet.Object; -using FishNet.Serializing; -using FishNet.Transporting; -using FishNet.Utility.Extension; -using FishNet.Utility.Performance; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine; - -namespace FishNet.Managing.Server -{ - /// - /// A container for server data and actions. - /// - [DisallowMultipleComponent] - [AddComponentMenu("FishNet/Manager/ServerManager")] - public sealed partial class ServerManager : MonoBehaviour - { - #region Public. - /// - /// Called after the local server connection state changes. - /// - public event Action OnServerConnectionState; - /// - /// Called when authenticator has concluded a result for a connection. Boolean is true if authentication passed, false if failed. - /// - public event Action OnAuthenticationResult; - /// - /// Called when a remote client state changes with the server. - /// - public event Action OnRemoteConnectionState; - /// - /// True if the server connection has started. - /// - public bool Started { get; private set; } - /// - /// Handling and information for objects on the server. - /// - public ServerObjects Objects { get; private set; } - /// - /// Authenticated and non-authenticated connected clients. - /// - [HideInInspector] - public Dictionary Clients = new Dictionary(); - /// - /// NetworkManager for server. - /// - [HideInInspector] - public NetworkManager NetworkManager { get; private set; } - #endregion - - #region Serialized. - /// - /// Authenticator for this ServerManager. May be null if not using authentication. - /// - [Obsolete("Use GetAuthenticator and SetAuthenticator.")] //Remove on 2023/06/01 - public Authenticator Authenticator - { - get => GetAuthenticator(); - set => SetAuthenticator(value); - } - /// - /// Gets the Authenticator for this manager. - /// - /// - public Authenticator GetAuthenticator() => _authenticator; - /// - /// Gets the Authenticator for this manager, and initializes it. - /// - /// - public void SetAuthenticator(Authenticator value) - { - _authenticator = value; - InitializeAuthenticator(); - } - [Tooltip("Authenticator for this ServerManager. May be null if not using authentication.")] - [SerializeField] - private Authenticator _authenticator; - /// - /// Default send rate for SyncTypes. A value of 0f will send changed values every tick. - /// SyncTypeRate cannot yet be changed at runtime because this would require recalculating rates on SyncBase, which is not yet implemented. - /// - /// - internal float GetSynctypeRate() => _syncTypeRate; - [Tooltip("Default send rate for SyncTypes. A value of 0f will send changed values every tick.")] - [Range(0f, 60f)] - [SerializeField] - private float _syncTypeRate = 0.1f; - /// - /// How to pack object spawns. - /// - [Tooltip("How to pack object spawns.")] - [SerializeField] - internal TransformPackingData SpawnPacking = new TransformPackingData() - { - Position = AutoPackType.Unpacked, - Rotation = AutoPackType.PackedLess, - Scale = AutoPackType.PackedLess - }; - /// - /// True to automatically set the frame rate when the client connects. - /// - [Tooltip("True to automatically set the frame rate when the client connects.")] - [SerializeField] - private bool _changeFrameRate = true; - /// - /// Maximum frame rate the server may run at. When as host this value runs at whichever is higher between client and server. - /// - internal ushort FrameRate => (_changeFrameRate) ? _frameRate : (ushort)0; - [Tooltip("Maximum frame rate the server may run at. When as host this value runs at whichever is higher between client and server.")] - [Range(1, NetworkManager.MAXIMUM_FRAMERATE)] - [SerializeField] - private ushort _frameRate = NetworkManager.MAXIMUM_FRAMERATE; - /// - /// True to share the Ids of clients and the objects they own with other clients. No sensitive information is shared. - /// - internal bool ShareIds => _shareIds; - [Tooltip("True to share the Ids of clients and the objects they own with other clients. No sensitive information is shared.")] - [SerializeField] - private bool _shareIds = true; - /// - /// Gets StartOnHeadless value. - /// - public bool GetStartOnHeadless() => _startOnHeadless; - /// - /// Sets StartOnHeadless value. - /// - /// New value to use. - public void SetStartOnHeadless(bool value) => _startOnHeadless = value; - [Tooltip("True to automatically start the server connection when running as headless.")] - [SerializeField] - private bool _startOnHeadless = true; - /// - /// True to kick clients which send data larger than the MTU. - /// - internal bool LimitClientMTU => _limitClientMTU; - [Tooltip("True to kick clients which send data larger than the MTU.")] - [SerializeField] - private bool _limitClientMTU = true; - #endregion - - #region Private. - /// - /// Used to read splits. - /// - private SplitReader _splitReader = new SplitReader(); -#if UNITY_EDITOR || DEVELOPMENT_BUILD - /// - /// Logs data about parser to help debug. - /// - private ParseLogger _parseLogger = new ParseLogger(); -#endif - #endregion - - private void OnDestroy() - { - Objects?.SubscribeToSceneLoaded(false); - } - - /// - /// Initializes this script for use. - /// - /// - internal void InitializeOnce_Internal(NetworkManager manager) - { - NetworkManager = manager; - Objects = new ServerObjects(manager); - Objects.SubscribeToSceneLoaded(true); - InitializeRpcLinks(); - //Unsubscribe first incase already subscribed. - SubscribeToTransport(false); - SubscribeToTransport(true); - NetworkManager.ClientManager.OnClientConnectionState += ClientManager_OnClientConnectionState; - NetworkManager.SceneManager.OnClientLoadedStartScenes += SceneManager_OnClientLoadedStartScenes; - - if (_authenticator == null) - _authenticator = GetComponent(); - if (_authenticator != null) - InitializeAuthenticator(); - - _cachedLevelOfDetailInterval = NetworkManager.ClientManager.LevelOfDetailInterval; - _cachedUseLod = NetworkManager.ObserverManager.GetUseNetworkLod(); - } - - /// - /// Initializes the authenticator to this manager. - /// - private void InitializeAuthenticator() - { - Authenticator auth = GetAuthenticator(); - if (auth == null || auth.Initialized) - return; - if (NetworkManager == null) - return; - - auth.InitializeOnce(NetworkManager); - auth.OnAuthenticationResult += _authenticator_OnAuthenticationResult; - } - - /// - /// Starts the server if configured to for headless. - /// - internal void StartForHeadless() - { - if (GetStartOnHeadless()) - { - //Wrapping logic in check instead of everything so _startOnHeadless doesnt warn as unused in editor. -#if UNITY_SERVER - StartConnection(); -#endif - } - } - - /// - /// Stops the local server connection. - /// - /// True to send a disconnect message to all clients first. - public bool StopConnection(bool sendDisconnectMessage) - { - if (sendDisconnectMessage) - SendDisconnectMessages(Clients.Values.ToList(), true); - - //Return stop connection result. - return NetworkManager.TransportManager.Transport.StopConnection(true); - } - - /// - /// Sends a disconnect messge to connectionIds. - /// This does not iterate outgoing automatically. - /// - /// - internal void SendDisconnectMessages(int[] connectionIds) - { - List conns = new List(); - foreach (int item in connectionIds) - { - if (Clients.TryGetValueIL2CPP(item, out NetworkConnection c)) - conns.Add(c); - } - - if (conns.Count > 0) - SendDisconnectMessages(conns, false); - } - /// - /// Sends a disconnect message to all clients and immediately iterates outgoing. - /// - private void SendDisconnectMessages(List conns, bool iterate) - { - PooledWriter writer = WriterPool.GetWriter(); - writer.WritePacketId(PacketId.Disconnect); - ArraySegment segment = writer.GetArraySegment(); - //Send segment to each client, authenticated or not. - foreach (NetworkConnection c in conns) - c.SendToClient((byte)Channel.Reliable, segment); - //Recycle writer. - writer.Dispose(); - - if (iterate) - NetworkManager.TransportManager.IterateOutgoing(true); - } - - /// - /// Starts the local server connection. - /// - public bool StartConnection() - { - return NetworkManager.TransportManager.Transport.StartConnection(true); - } - /// - /// Starts the local server using port. - /// - /// Port to start on. - /// - public bool StartConnection(ushort port) - { - Transport t = NetworkManager.TransportManager.Transport; - t.SetPort(port); - return t.StartConnection(true); - } - - /// - /// Called after the local client connection state changes. - /// - private void ClientManager_OnClientConnectionState(ClientConnectionStateArgs obj) - { - /* If client is doing anything but started destroy pending. - * Pending is only used for host mode. */ - if (obj.ConnectionState != LocalConnectionState.Started) - Objects.DestroyPending(); - } - - /// - /// Called when a client loads initial scenes after connecting. - /// - private void SceneManager_OnClientLoadedStartScenes(NetworkConnection conn, bool asServer) - { - if (asServer) - { - Objects.RebuildObservers(conn); - /* If connection is host then renderers must be hidden - * for all objects not visible to the host. The observer system - * does handle this but only after an initial state is set. - * If the clientHost joins without observation of an object - * then the initial state will never be set. */ - if (conn.IsLocalClient) - { - foreach (NetworkObject nob in Objects.Spawned.Values) - { - if (!nob.Observers.Contains(conn)) - nob.SetRenderersVisible(false); - } - } - } - } - - /// - /// Changes subscription status to transport. - /// - /// - private void SubscribeToTransport(bool subscribe) - { - if (NetworkManager == null || NetworkManager.TransportManager == null || NetworkManager.TransportManager.Transport == null) - return; - - if (subscribe) - { - NetworkManager.TransportManager.Transport.OnServerReceivedData += Transport_OnServerReceivedData; - NetworkManager.TransportManager.Transport.OnServerConnectionState += Transport_OnServerConnectionState; - NetworkManager.TransportManager.Transport.OnRemoteConnectionState += Transport_OnRemoteConnectionState; - } - else - { - NetworkManager.TransportManager.Transport.OnServerReceivedData -= Transport_OnServerReceivedData; - NetworkManager.TransportManager.Transport.OnServerConnectionState -= Transport_OnServerConnectionState; - NetworkManager.TransportManager.Transport.OnRemoteConnectionState -= Transport_OnRemoteConnectionState; - } - } - - /// - /// Called when authenticator has concluded a result for a connection. Boolean is true if authentication passed, false if failed. - /// Server listens for this event automatically. - /// - private void _authenticator_OnAuthenticationResult(NetworkConnection conn, bool authenticated) - { - if (!authenticated) - conn.Disconnect(false); - else - ClientAuthenticated(conn); - } - - /// - /// Called when a connection state changes for the local server. - /// - private void Transport_OnServerConnectionState(ServerConnectionStateArgs args) - { - /* Let the client manager know the server state is changing first. - * This gives the client an opportunity to clean-up or prepare - * before the server completes it's actions. */ - Started = AnyServerStarted(); - NetworkManager.ClientManager.Objects.OnServerConnectionState(args); - //If no servers are started then reset match conditions. - if (!Started) - { - MatchCondition.ClearMatchesWithoutRebuilding(); - //Despawn without synchronizing network objects. - Objects.DespawnWithoutSynchronization(true); - } - Objects.OnServerConnectionState(args); - - LocalConnectionState state = args.ConnectionState; - - if (NetworkManager.CanLog(LoggingType.Common)) - { - Transport t = NetworkManager.TransportManager.GetTransport(args.TransportIndex); - string tName = (t == null) ? "Unknown" : t.GetType().Name; - Debug.Log($"Local server is {state.ToString().ToLower()} for {tName}."); - } - - NetworkManager.UpdateFramerate(); - OnServerConnectionState?.Invoke(args); - } - - /// - /// Called when a connection state changes for a remote client. - /// - private void Transport_OnRemoteConnectionState(RemoteConnectionStateArgs args) - { - //Sanity check to make sure transports are following proper types/ranges. - int id = args.ConnectionId; - int maxIdValue = short.MaxValue; - if (id < 0 || id > maxIdValue) - { - Kick(args.ConnectionId, KickReason.UnexpectedProblem, LoggingType.Error, $"The transport you are using supplied an invalid connection Id of {id}. Connection Id values must range between 0 and {maxIdValue}. The client has been disconnected."); - return; - } - //Valid Id. - else - { - //If started then add to authenticated clients. - if (args.ConnectionState == RemoteConnectionState.Started) - { - NetworkManager.Log($"Remote connection started for Id {id}."); - NetworkConnection conn = new NetworkConnection(NetworkManager, id, true); - Clients.Add(args.ConnectionId, conn); - OnRemoteConnectionState?.Invoke(conn, args); - //Connection is no longer valid. This can occur if the user changes the state using the OnRemoteConnectionState event. - if (!conn.IsValid) - return; - /* If there is an authenticator - * and the transport is not a local transport. */ - Authenticator auth = GetAuthenticator(); - if (auth != null && !NetworkManager.TransportManager.IsLocalTransport(id)) - auth.OnRemoteConnection(conn); - else - ClientAuthenticated(conn); - } - //If stopping. - else if (args.ConnectionState == RemoteConnectionState.Stopped) - { - /* If client's connection is found then clean - * them up from server. */ - if (Clients.TryGetValueIL2CPP(id, out NetworkConnection conn)) - { - conn.SetDisconnecting(true); - OnRemoteConnectionState?.Invoke(conn, args); - Clients.Remove(id); - MatchCondition.RemoveFromMatchWithoutRebuild(conn, NetworkManager); - Objects.ClientDisconnected(conn); - BroadcastClientConnectionChange(false, conn); - //Return predictedObjectIds. - Queue pqId = conn.PredictedObjectIds; - while (pqId.Count > 0) - Objects.CacheObjectId(pqId.Dequeue()); - - conn.Reset(); - NetworkManager.Log($"Remote connection stopped for Id {id}."); - } - } - } - } - - /// - /// Sends client their connectionId. - /// - /// - private void SendAuthenticated(NetworkConnection conn) - { - using (PooledWriter writer = WriterPool.GetWriter()) - { - writer.WritePacketId(PacketId.Authenticated); - writer.WriteNetworkConnection(conn); - /* If predicted spawning is enabled then also send - * reserved objectIds. */ - ; - PredictionManager pm = NetworkManager.PredictionManager; - if (pm.GetAllowPredictedSpawning()) - { - int count = Mathf.Min(Objects.GetObjectIdCache().Count, pm.GetReservedObjectIds()); - writer.WriteByte((byte)count); - - for (int i = 0; i < count; i++) - { - ushort val = (ushort)Objects.GetNextNetworkObjectId(false); - writer.WriteNetworkObjectId(val); - conn.PredictedObjectIds.Enqueue(val); - } - } - - NetworkManager.TransportManager.SendToClient((byte)Channel.Reliable, writer.GetArraySegment(), conn); - } - } - /// - /// Called when the server socket receives data. - /// - private void Transport_OnServerReceivedData(ServerReceivedDataArgs args) - { - args.Data = NetworkManager.TransportManager.ProcessIntermediateIncoming(args.Data, false); - ParseReceived(args); - } - - /// - /// Called when the server receives data. - /// - /// - private void ParseReceived(ServerReceivedDataArgs args) - { -#if UNITY_EDITOR || DEVELOPMENT_BUILD - _parseLogger.Reset(); -#endif - - //Not from a valid connection. - if (args.ConnectionId < 0) - return; - ArraySegment segment = args.Data; - NetworkManager.StatisticsManager.NetworkTraffic.LocalServerReceivedData((ulong)segment.Count); - if (segment.Count <= TransportManager.TICK_BYTES) - return; - - //FishNet internally splits packets so nothing should ever arrive over MTU. - int channelMtu = NetworkManager.TransportManager.GetMTU(args.TransportIndex, (byte)args.Channel); - //If over MTU kick client immediately. - if (segment.Count > channelMtu && !NetworkManager.TransportManager.IsLocalTransport(args.ConnectionId)) - { - ExceededMTUKick(); - return; - } - - PacketId packetId = PacketId.Unset; -#if !UNITY_EDITOR && !DEVELOPMENT_BUILD - try - { -#endif - using (PooledReader reader = ReaderPool.GetReader(segment, NetworkManager)) - { - uint tick = reader.ReadUInt32(AutoPackType.Unpacked); - NetworkManager.TimeManager.LastPacketTick = tick; - /* This is a special condition where a message may arrive split. - * When this occurs buffer each packet until all packets are - * received. */ - if (reader.PeekPacketId() == PacketId.Split) - { - //Skip packetId. - reader.ReadPacketId(); - - int expectedMessages; - _splitReader.GetHeader(reader, out expectedMessages); - //If here split message can be written. - _splitReader.Write(NetworkManager.TimeManager.LastPacketTick, reader, expectedMessages); - - /* If fullMessage returns 0 count then the split - * has not written fully yet. Otherwise, if there is - * data within then reinitialize reader with the - * full message. */ - ArraySegment fullMessage = _splitReader.GetFullMessage(); - if (fullMessage.Count == 0) - return; - - /* If here then all data has been received. - * It's possible the client could have exceeded - * maximum MTU but not the maximum number of splits. - * This is because the length of each split - * is not written, so we don't know how much data of the - * final message actually belonged to the split vs - * unrelated data added afterwards. We're going to cut - * the client some slack in this situation for the sake - * of keeping things simple. */ - //Initialize reader with full message. - reader.Initialize(fullMessage, NetworkManager); - } - - //Parse reader. - while (reader.Remaining > 0) - { - packetId = reader.ReadPacketId(); -#if UNITY_EDITOR || DEVELOPMENT_BUILD - _parseLogger.AddPacket(packetId); -#endif - NetworkConnection conn; - - /* Connection isn't available. This should never happen. - * Force an immediate disconnect. */ - if (!Clients.TryGetValueIL2CPP(args.ConnectionId, out conn)) - { - Kick(args.ConnectionId, KickReason.UnexpectedProblem, LoggingType.Error, $"ConnectionId {conn.ClientId} not found within Clients. Connection will be kicked immediately."); - return; - } - conn.SetLastPacketTick(tick); - /* If connection isn't authenticated and isn't a broadcast - * then disconnect client. If a broadcast then process - * normally; client may still become disconnected if the broadcast - * does not allow to be called while not authenticated. */ - if (!conn.Authenticated && packetId != PacketId.Broadcast) - { - conn.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"ConnectionId {conn.ClientId} sent a Broadcast without being authenticated. Connection will be kicked immediately."); - return; - } - - //Only check if not developer build because users pay pause editor. -#if !DEVELOPMENT_BUILD && !UNITY_EDITOR - /* If hasn't sent LOD recently enough. LODs are sent every half a second, so - * by multiplaying interval by 60 this gives the client a 30 second window. */ - if (_cachedUseLod && conn.IsLateForLevelOfDetail(_cachedLevelOfDetailInterval * 60)) - { - conn.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"ConnectionId {conn.ClientId} has gone too long without sending a level of detail update. Connection will be kicked immediately."); - return; - } -#endif - if (packetId == PacketId.Replicate) - { - Objects.ParseReplicateRpc(reader, conn, args.Channel); - } - else if (packetId == PacketId.ServerRpc) - { - Objects.ParseServerRpc(reader, conn, args.Channel); - } - else if (packetId == PacketId.ObjectSpawn) - { - if (!NetworkManager.PredictionManager.GetAllowPredictedSpawning()) - { - conn.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"ConnectionId {conn.ClientId} sent a predicted spawn while predicted spawning is not enabled. Connection will be kicked immediately."); - return; - } - Objects.ReadPredictedSpawn(reader, conn); - } - else if (packetId == PacketId.ObjectDespawn) - { - if (!NetworkManager.PredictionManager.GetAllowPredictedSpawning()) - { - conn.Kick(KickReason.ExploitAttempt, LoggingType.Common, $"ConnectionId {conn.ClientId} sent a predicted spawn while predicted spawning is not enabled. Connection will be kicked immediately."); - return; - } - Objects.ReadPredictedDespawn(reader, conn); - } - else if (packetId == PacketId.NetworkLODUpdate) - { - ParseNetworkLODUpdate(reader, conn); - } - else if (packetId == PacketId.Broadcast) - { - ParseBroadcast(reader, conn, args.Channel); - } - else if (packetId == PacketId.PingPong) - { - ParsePingPong(reader, conn); - } - else - { -#if UNITY_EDITOR || DEVELOPMENT_BUILD - NetworkManager.LogError($"Server received an unhandled PacketId of {(ushort)packetId} from connectionId {args.ConnectionId}. Remaining data has been purged."); - _parseLogger.Print(NetworkManager); -#else - NetworkManager.LogError($"Server received an unhandled PacketId of {(ushort)packetId} from connectionId {args.ConnectionId}. Connection will be kicked immediately."); - NetworkManager.TransportManager.Transport.StopConnection(args.ConnectionId, true); -#endif - return; - } - } - } -#if !UNITY_EDITOR && !DEVELOPMENT_BUILD - } - catch (Exception e) - { - Kick(args.ConnectionId, KickReason.MalformedData, LoggingType.Error, $"Server encountered an error while parsing data for packetId {packetId} from connectionId {args.ConnectionId}. Connection will be kicked immediately. Message: {e.Message}."); - } -#endif - - //Kicks connection for exceeding MTU. - void ExceededMTUKick() - { - Kick(args.ConnectionId, KickReason.ExploitExcessiveData, LoggingType.Common, $"ConnectionId {args.ConnectionId} sent a message larger than allowed amount. Connection will be kicked immediately."); - } - - } - - /// - /// Parses a received PingPong. - /// - /// - /// - private void ParsePingPong(PooledReader reader, NetworkConnection conn) - { - /* //security limit how often clients can send pings. - * have clients use a stopwatch rather than frame time - * for checks to ensure it's not possible to send - * excessively should their game stutter then catch back up. */ - uint clientTick = reader.ReadUInt32(AutoPackType.Unpacked); - if (conn.CanPingPong()) - NetworkManager.TimeManager.SendPong(conn, clientTick); - } - - - /// - /// Called when a remote client authenticates with the server. - /// - /// - private void ClientAuthenticated(NetworkConnection connection) - { - /* Immediately send connectionId to client. Some transports - * don't give clients their remoteId, therefor it has to be sent - * by the ServerManager. This packet is very simple and can be built - * on the spot. */ - connection.ConnectionAuthenticated(); - /* Send client Ids before telling the client - * they are authenticated. This is important because when the client becomes - * authenticated they set their LocalConnection using Clients field in ClientManager, - * which is set after getting Ids. */ - BroadcastClientConnectionChange(true, connection); - SendAuthenticated(connection); - - OnAuthenticationResult?.Invoke(connection, true); - NetworkManager.SceneManager.OnClientAuthenticated(connection); - } - - /// - /// Sends a client connection state change to owner and other clients if applicable. - /// - private void BroadcastClientConnectionChange(bool connected, NetworkConnection conn) - { - //If sharing Ids then send all connected client Ids first if is a connected state. - if (ShareIds) - { - /* Send a broadcast to all authenticated clients with the clientId - * that just connected. The conn client will also get this. */ - ClientConnectionChangeBroadcast changeMsg = new ClientConnectionChangeBroadcast() - { - Connected = connected, - Id = conn.ClientId - }; - Broadcast(changeMsg); - - /* If state is connected then the conn client - * must also receive all currently connected client ids. */ - if (connected) - { - //Send already connected clients to the connection that just joined. - ListCache lc = ListCaches.GetIntCache(); - foreach (int key in Clients.Keys) - lc.AddValue(key); - - ConnectedClientsBroadcast allMsg = new ConnectedClientsBroadcast() - { - ListCache = lc - }; - conn.Broadcast(allMsg); - ListCaches.StoreCache(lc); - } - } - //If not sharing Ids then only send ConnectionChange to conn. - else - { - if (connected) - { - /* Send broadcast only to the client which just disconnected. - * Only send if connecting. If the client is disconnected there's no reason - * to send them a disconnect msg. */ - ClientConnectionChangeBroadcast changeMsg = new ClientConnectionChangeBroadcast() - { - Connected = connected, - Id = conn.ClientId - }; - Broadcast(conn, changeMsg, true, Channel.Reliable); - } - } - - } - - } - - -} diff --git a/Assets/FishNet/Runtime/Managing/Server/ServerManager.cs.meta b/Assets/FishNet/Runtime/Managing/Server/ServerManager.cs.meta deleted file mode 100644 index 9a70fbe..0000000 --- a/Assets/FishNet/Runtime/Managing/Server/ServerManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 68828c85278210948b9d50a8db3aab74 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Statistic.meta b/Assets/FishNet/Runtime/Managing/Statistic.meta deleted file mode 100644 index 5fdb9ab..0000000 --- a/Assets/FishNet/Runtime/Managing/Statistic.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: c554690fa24f652408df67e97c3a0e5f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficArgs.cs b/Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficArgs.cs deleted file mode 100644 index 9f9a5f2..0000000 --- a/Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficArgs.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace FishNet.Managing.Statistic -{ - - public struct NetworkTrafficArgs - { - /// - /// Number of bytes sent to the server. - /// - public readonly ulong ToServerBytes; - /// - /// Number of bytes sent by the server. - /// - public readonly ulong FromServerBytes; - - public NetworkTrafficArgs(ulong toServerBytes, ulong fromServerBytes) - { - ToServerBytes = toServerBytes; - FromServerBytes = fromServerBytes; - } - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficArgs.cs.meta b/Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficArgs.cs.meta deleted file mode 100644 index ff42599..0000000 --- a/Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficArgs.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1fb953771006e0541ba76e564a90c21d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficStatistics.cs b/Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficStatistics.cs deleted file mode 100644 index f50b1c7..0000000 --- a/Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficStatistics.cs +++ /dev/null @@ -1,203 +0,0 @@ - - -using System; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Managing.Statistic -{ - [System.Serializable] - public class NetworkTraficStatistics - { - #region Public. - /// - /// Called when NetworkTraffic is updated for the client. - /// - public event Action OnClientNetworkTraffic; - /// - /// Called when NetworkTraffic is updated for the server. - /// - public event Action OnServerNetworkTraffic; - #endregion - - #region Serialized. - /// - /// How often to update traffic statistics. - /// - [Tooltip("How often to update traffic statistics.")] - [SerializeField] - [Range(0f, 10f)] - private float _updateInteval = 1f; - /// - /// - /// - [Tooltip("True to update client statistics.")] - [SerializeField] - private bool _updateClient; - /// - /// True to update client statistics. - /// - public bool UpdateClient - { - get => _updateClient; - private set => _updateClient = value; - } - /// - /// Sets UpdateClient value. - /// - /// - public void SetUpdateClient(bool update) - { - UpdateClient = update; - } - /// - /// - /// - [Tooltip("True to update server statistics.")] - [SerializeField] - private bool _updateServer; - /// - /// True to update client statistics. - /// - public bool UpdateServer - { - get => _updateServer; - private set => _updateServer = value; - } - /// - /// Sets UpdateServer value. - /// - /// - public void SetUpdateServer(bool update) - { - UpdateServer = update; - } - #endregion - - #region Private. - /// - /// NetworkManager for this statistics. - /// - private NetworkManager _networkManager; - /// - /// Bytes sent to the server from local client. - /// - private ulong _client_toServerBytes; - /// - /// Bytes received on the local client from the server. - /// - private ulong _client_fromServerBytes; - /// - /// Bytes sent to all clients from the local server. - /// - private ulong _server_toClientsBytes; - /// - /// Bytes received on the local server from all clients. - /// - private ulong _server_fromClientsBytes; - /// - /// Next time network traffic updates may invoke. - /// - private float _nextUpdateTime; - /// - /// Size suffixes as text. - /// - private static readonly string[] _sizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; - #endregion - - internal void InitializeOnce_Internal(NetworkManager manager) - { - _networkManager = manager; - manager.TimeManager.OnPreTick += TimeManager_OnPreTick; - } - - /// - /// Called before the TimeManager ticks. - /// - private void TimeManager_OnPreTick() - { - if (Time.unscaledTime < _nextUpdateTime) - return; - _nextUpdateTime = Time.unscaledTime + _updateInteval; - - if (UpdateClient && _networkManager.IsClient) - OnClientNetworkTraffic?.Invoke(new NetworkTrafficArgs(_client_toServerBytes, _client_fromServerBytes)); - if (UpdateServer && _networkManager.IsServer) - OnServerNetworkTraffic?.Invoke(new NetworkTrafficArgs(_server_fromClientsBytes, _server_toClientsBytes)); - - _client_toServerBytes = 0; - _client_fromServerBytes = 0; - _server_toClientsBytes = 0; - _server_fromClientsBytes = 0; - } - - /// - /// Called when the local client sends data. - /// - internal void LocalClientSentData(ulong dataLength) - { - _client_toServerBytes = Math.Min(_client_toServerBytes + dataLength, ulong.MaxValue); - } - /// - /// Called when the local client receives data. - /// - public void LocalClientReceivedData(ulong dataLength) - { - _client_fromServerBytes = Math.Min(_client_fromServerBytes + dataLength, ulong.MaxValue); - } - - - /// - /// Called when the local client sends data. - /// - internal void LocalServerSentData(ulong dataLength) - { - _server_toClientsBytes = Math.Min(_server_toClientsBytes + dataLength, ulong.MaxValue); - } - /// - /// Called when the local client receives data. - /// - public void LocalServerReceivedData(ulong dataLength) - { - _server_fromClientsBytes = Math.Min(_server_fromClientsBytes + dataLength, ulong.MaxValue); - } - - - //Attribution: https://stackoverflow.com/questions/14488796/does-net-provide-an-easy-way-convert-bytes-to-kb-mb-gb-etc - /// - /// Formats passed in bytes value to the largest possible data type with 2 decimals. - /// - public static string FormatBytesToLargest(ulong bytes) - { - int decimalPlaces = 2; - if (bytes == 0) - { - decimalPlaces = 0; - return string.Format("{0:n" + decimalPlaces + "} bytes", 0); - } - - // mag is 0 for bytes, 1 for KB, 2, for MB, etc. - int mag = (int)Math.Log(bytes, 1024); - - // 1L << (mag * 10) == 2 ^ (10 * mag) - // [i.e. the number of bytes in the unit corresponding to mag] - decimal adjustedSize = (decimal)bytes / (1L << (mag * 10)); - - // make adjustment when the value is large enough that - // it would round up to 1000 or more - if (Math.Round(adjustedSize, decimalPlaces) >= 1000) - { - mag += 1; - adjustedSize /= 1024; - } - - //Don't show decimals for bytes. - if (mag == 0) - decimalPlaces = 0; - - return string.Format("{0:n" + decimalPlaces + "} {1}", adjustedSize, _sizeSuffixes[mag]); - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficStatistics.cs.meta b/Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficStatistics.cs.meta deleted file mode 100644 index 77c4fbc..0000000 --- a/Assets/FishNet/Runtime/Managing/Statistic/NetworkTrafficStatistics.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9cc04f6ae0339c94e9153396dce3f46e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Statistic/StatisticsManager.cs b/Assets/FishNet/Runtime/Managing/Statistic/StatisticsManager.cs deleted file mode 100644 index 3570745..0000000 --- a/Assets/FishNet/Runtime/Managing/Statistic/StatisticsManager.cs +++ /dev/null @@ -1,22 +0,0 @@ -using UnityEngine; - -namespace FishNet.Managing.Statistic -{ - - [DisallowMultipleComponent] - [AddComponentMenu("FishNet/Manager/StatisticsManager")] - public class StatisticsManager : MonoBehaviour - { - /// - /// Statistics for NetworkTraffic. - /// - public NetworkTraficStatistics NetworkTraffic = new NetworkTraficStatistics(); - - internal void InitializeOnce_Internal(NetworkManager manager) - { - NetworkTraffic.InitializeOnce_Internal(manager); - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Statistic/StatisticsManager.cs.meta b/Assets/FishNet/Runtime/Managing/Statistic/StatisticsManager.cs.meta deleted file mode 100644 index f50fb2f..0000000 --- a/Assets/FishNet/Runtime/Managing/Statistic/StatisticsManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 756c28cd3141c4140ae776188ee26729 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Timing.meta b/Assets/FishNet/Runtime/Managing/Timing.meta deleted file mode 100644 index 35f0ef3..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: edf228892c89f3d4694213cba4a584fd -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Timing/Editor.meta b/Assets/FishNet/Runtime/Managing/Timing/Editor.meta deleted file mode 100644 index f5e62ae..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 142c456200062324b95ea95078a9c38f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Timing/Editor/TimeManagerEditor.cs b/Assets/FishNet/Runtime/Managing/Timing/Editor/TimeManagerEditor.cs deleted file mode 100644 index fafb77c..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/Editor/TimeManagerEditor.cs +++ /dev/null @@ -1,79 +0,0 @@ -#if UNITY_EDITOR -using UnityEditor; -using UnityEngine; - -namespace FishNet.Managing.Timing.Editing -{ - - - [CustomEditor(typeof(TimeManager), true)] - [CanEditMultipleObjects] - public class TimeManagerEditor : Editor - { - private SerializedProperty _updateOrder; - private SerializedProperty _timingType; - private SerializedProperty _tickRate; - private SerializedProperty _allowTickDropping; - private SerializedProperty _maximumFrameTicks; - private SerializedProperty _pingInterval; - private SerializedProperty _timingInterval; - private SerializedProperty _physicsMode; - - protected virtual void OnEnable() - { - _updateOrder = serializedObject.FindProperty("_updateOrder"); - _timingType = serializedObject.FindProperty("_timingType"); - _tickRate = serializedObject.FindProperty("_tickRate"); - _allowTickDropping = serializedObject.FindProperty("_allowTickDropping"); - _maximumFrameTicks = serializedObject.FindProperty("_maximumFrameTicks"); - _pingInterval = serializedObject.FindProperty("_pingInterval"); - _timingInterval = serializedObject.FindProperty("_timingInterval"); - _physicsMode = serializedObject.FindProperty("_physicsMode"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - GUI.enabled = false; - EditorGUILayout.ObjectField("Script:", MonoScript.FromMonoBehaviour((TimeManager)target), typeof(TimeManager), false); - GUI.enabled = true; - - //Timing. - EditorGUILayout.LabelField("Timing", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_updateOrder); - EditorGUILayout.PropertyField(_timingType); - EditorGUILayout.PropertyField(_allowTickDropping); - if (_allowTickDropping.boolValue == true) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_maximumFrameTicks); - EditorGUI.indentLevel--; - } - EditorGUILayout.PropertyField(_tickRate); - EditorGUILayout.PropertyField(_pingInterval); - EditorGUILayout.PropertyField(_timingInterval); - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - - //Physics. - EditorGUILayout.LabelField("Physics", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(_physicsMode); - if (_physicsMode.intValue != (int)FishNet.Managing.Timing.PhysicsMode.TimeManager) - EditorGUILayout.HelpBox("If you are using physics interactions be sure to change the PhysicsMode to TimeManager and implement physics within the TimeManager tick events.", MessageType.None); - EditorGUI.indentLevel--; - - ////Prediction. - //EditorGUILayout.LabelField("Prediction", EditorStyles.boldLabel); - //EditorGUI.indentLevel++; - //EditorGUILayout.PropertyField(_maximumBufferedInputs); - //EditorGUI.indentLevel--; - - serializedObject.ApplyModifiedProperties(); - } - } - -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Timing/Editor/TimeManagerEditor.cs.meta b/Assets/FishNet/Runtime/Managing/Timing/Editor/TimeManagerEditor.cs.meta deleted file mode 100644 index cb15067..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/Editor/TimeManagerEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 12987a8c0302190489ecb55f6fbd494e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Timing/MovingAverage.cs b/Assets/FishNet/Runtime/Managing/Timing/MovingAverage.cs deleted file mode 100644 index a410716..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/MovingAverage.cs +++ /dev/null @@ -1,81 +0,0 @@ -using FishNet.Documenting; -using System; -using UnityEngine; - -namespace FishNet.Managing.Timing -{ - - [APIExclude] - public class MovingAverage - { - #region Public. - /// - /// Average from samples favoring the most recent sample. - /// - public float Average { get; private set; } - #endregion - - /// - /// Next index to write a sample to. - /// - private int _writeIndex; - /// - /// Collected samples. - /// - private float[] _samples; - /// - /// Number of samples written. Will be at most samples size. - /// - private int _writtenSamples; - /// - /// Samples accumulated over queue. - /// - private float _sampleAccumulator; - - public MovingAverage(int sampleSize) - { - if (sampleSize < 0) - sampleSize = 0; - else if (sampleSize < 2) - NetworkManager.StaticLogWarning("Using a sampleSize of less than 2 will always return the most recent value as Average."); - - _samples = new float[sampleSize]; - } - - - /// - /// Computes a new windowed average each time a new sample arrives - /// - /// - public void ComputeAverage(float newSample) - { - if (_samples.Length <= 1) - { - Average = newSample; - return; - } - - _sampleAccumulator += newSample; - _samples[_writeIndex] = newSample; - - //Increase writeIndex. - _writeIndex++; - _writtenSamples = Math.Max(_writtenSamples, _writeIndex); - if (_writeIndex >= _samples.Length) - _writeIndex = 0; - - Average = _sampleAccumulator / _writtenSamples; - - /* If samples are full then drop off - * the oldest sample. This will always be - * the one just after written. The entry isn't - * actually removed from the array but will - * be overwritten next sample. */ - if (_writtenSamples >= _samples.Length) - _sampleAccumulator -= _samples[_writeIndex]; - - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Timing/MovingAverage.cs.meta b/Assets/FishNet/Runtime/Managing/Timing/MovingAverage.cs.meta deleted file mode 100644 index 941fad9..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/MovingAverage.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 03d05f88778c5c744810e48f251f2d3b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Timing/PhysicsMode.cs b/Assets/FishNet/Runtime/Managing/Timing/PhysicsMode.cs deleted file mode 100644 index 6a77670..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/PhysicsMode.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace FishNet.Managing.Timing -{ - /// - /// How to simulate physics. - /// - public enum PhysicsMode - { - /// - /// Unity performs physics every FixedUpdate. - /// - Unity = 0, - /// - /// TimeManager performs physics each tick. - /// - TimeManager = 1, - /// - /// Physics will be disabled. - /// - Disabled = 2 - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Timing/PhysicsMode.cs.meta b/Assets/FishNet/Runtime/Managing/Timing/PhysicsMode.cs.meta deleted file mode 100644 index 6b21845..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/PhysicsMode.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 502e9f31bebd41f4f9088a19eae53735 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Timing/PreciseTick.cs b/Assets/FishNet/Runtime/Managing/Timing/PreciseTick.cs deleted file mode 100644 index f940a70..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/PreciseTick.cs +++ /dev/null @@ -1,47 +0,0 @@ -using FishNet.Serializing; -using FishNet.Utility.Extension; -using System; -using UnityEngine; - -namespace FishNet.Managing.Timing -{ - - public struct PreciseTick - { - /// - /// The current tick. - /// - public uint Tick; - /// - /// Percentage into the next tick. - /// - public double Percent; - - public PreciseTick(uint tick, double percent) - { - Tick = tick; - Percent = percent; - } - } - - public static class PreciseTickSerializer - { - public static void WritePreciseTick(this Writer writer, PreciseTick value) - { - writer.WriteUInt32(value.Tick, AutoPackType.Unpacked); - /* No reason percent should exist beyond these values, but better to be safe. - * There is also no double clamp in Unity so... */ - double percent = MathFN.ClampDouble(value.Percent, 0d, 1f); - byte percentByte = (byte)(percent * 100); - writer.WriteByte(percentByte); - } - - public static PreciseTick ReadPreciseTick(this Reader reader) - { - uint tick = reader.ReadUInt32(AutoPackType.Unpacked); - byte percentByte = reader.ReadByte(); - double percent = MathFN.ClampDouble((percentByte / 100f), 0d, 1d); - return new PreciseTick(tick, percent); - } - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Timing/PreciseTick.cs.meta b/Assets/FishNet/Runtime/Managing/Timing/PreciseTick.cs.meta deleted file mode 100644 index 4d9406a..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/PreciseTick.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a96dd6b21066a424199583b80746464f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Timing/TickRounding.cs b/Assets/FishNet/Runtime/Managing/Timing/TickRounding.cs deleted file mode 100644 index a3800d3..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/TickRounding.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace FishNet.Managing.Timing -{ - /// - /// How ticks are rounded when using time. - /// - public enum TickRounding - { - /// - /// Rounds up. - /// - RoundUp, - /// - /// Rounds down. - /// - RoundDown, - /// - /// Rounds to the nearest whole. - /// - RoundNearest - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Timing/TickRounding.cs.meta b/Assets/FishNet/Runtime/Managing/Timing/TickRounding.cs.meta deleted file mode 100644 index 02d1339..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/TickRounding.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d12f8894fc7343b4bbe332464dc4bce5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Timing/TickType.cs b/Assets/FishNet/Runtime/Managing/Timing/TickType.cs deleted file mode 100644 index 0726324..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/TickType.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace FishNet.Managing.Timing -{ - public enum TickType : byte - { - Tick = 0, - LocalTick = 1, - LastPacketTick = 2 - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Timing/TickType.cs.meta b/Assets/FishNet/Runtime/Managing/Timing/TickType.cs.meta deleted file mode 100644 index cebcd6e..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/TickType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 489fba8b0da3c9b4b9ff4e7a46804473 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs b/Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs deleted file mode 100644 index 8624e31..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs +++ /dev/null @@ -1,1054 +0,0 @@ -using FishNet.Connection; -using FishNet.Documenting; -using FishNet.Object; -using FishNet.Serializing; -using FishNet.Serializing.Helping; -using FishNet.Transporting; -using FishNet.Utility; -using FishNet.Utility.Extension; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; -using SystemStopwatch = System.Diagnostics.Stopwatch; -using UnityScene = UnityEngine.SceneManagement.Scene; - -namespace FishNet.Managing.Timing -{ - - /// - /// Provides data and actions for network time and tick based systems. - /// - [DisallowMultipleComponent] - [AddComponentMenu("FishNet/Manager/TimeManager")] - public sealed partial class TimeManager : MonoBehaviour - { - #region Types. - /// - /// How networking timing is performed. - /// - private enum TimingType - { - /// - /// Send and read data on tick. - /// - Tick = 0, - /// - /// Send and read data as soon as possible. This does not include built-in components, which will still run on tick. - /// - Variable = 1 - } - private enum UpdateOrder : byte - { - BeforeTick = 0, - AfterTick = 1, - } - #endregion - - #region Public. - /// - /// Called when the local clients ping is updated. - /// - public event Action OnRoundTripTimeUpdated; - /// - /// Called right before a tick occurs, as well before data is read. - /// - public event Action OnPreTick; - /// - /// Called when a tick occurs. - /// - public event Action OnTick; - /// - /// When using TimeManager for physics timing, this is called immediately before physics simulation will occur for the tick. - /// While using Unity for physics timing, this is called during FixedUpdate. - /// This may be useful if you wish to run physics differently for stacked scenes. - /// - public event Action OnPrePhysicsSimulation; - /// - /// When using TimeManager for physics timing, this is called immediately after the physics simulation has occured for the tick. - /// While using Unity for physics timing, this is called during Update, only if a physics frame. - /// This may be useful if you wish to run physics differently for stacked scenes. - /// - public event Action OnPostPhysicsSimulation; - /// - /// Called after a tick occurs; physics would have simulated if using PhysicsMode.TimeManager. - /// - public event Action OnPostTick; - /// - /// Called when MonoBehaviours call Update. - /// - public event Action OnUpdate; - /// - /// Called when MonoBehaviours call LateUpdate. - /// - public event Action OnLateUpdate; - /// - /// Called when MonoBehaviours call FixedUpdate. - /// - public event Action OnFixedUpdate; - /// - /// RoundTripTime in milliseconds. This value includes latency from the tick rate. - /// - public long RoundTripTime { get; private set; } - /// - /// True if the number of frames per second are less than the number of expected ticks per second. - /// - internal bool LowFrameRate => ((Time.unscaledTime - _lastMultipleTicksTime) < 1f); - /// - /// Tick on the last received packet, be it from server or client. - /// - public uint LastPacketTick { get; internal set; } - /// - /// Current approximate network tick as it is on server. - /// When running as client only this is an approximation to what the server tick is. - /// The value of this field may increase and decrease as timing adjusts. - /// This value is reset upon disconnecting. - /// Tick can be used to get the server time by using TicksToTime(). - /// Use LocalTick for values that only increase. - /// - public uint Tick { get; internal set; } - /// - /// A fixed deltaTime for TickRate. - /// - [HideInInspector] - public double TickDelta { get; private set; } - /// - /// True if the TimeManager will or has ticked this frame. - /// - public bool FrameTicked { get; private set; } - /// - /// How long the local server has been connected. - /// - public float ServerUptime { get; private set; } - /// - /// How long the local client has been connected. - /// - public float ClientUptime { get; private set; } - #endregion - - #region Serialized. - /// - /// When to invoke OnUpdate and other Unity callbacks relayed by the TimeManager. - /// - [Tooltip("When to invoke OnUpdate and other Unity callbacks relayed by the TimeManager.")] - [SerializeField] - private UpdateOrder _updateOrder = UpdateOrder.BeforeTick; - /// - /// Timing for sending and receiving data. - /// - [Tooltip("Timing for sending and receiving data.")] - [SerializeField] - private TimingType _timingType = TimingType.Tick; - /// - /// While true clients may drop local ticks if their devices are unable to maintain the tick rate. - /// This could result in a temporary desynchronization but will prevent the client falling further behind on ticks by repeatedly running the logic cycle multiple times per frame. - /// - [Tooltip("While true clients may drop local ticks if their devices are unable to maintain the tick rate. This could result in a temporary desynchronization but will prevent the client falling further behind on ticks by repeatedly running the logic cycle multiple times per frame.")] - [SerializeField] - private bool _allowTickDropping; - /// - /// Maximum number of ticks which may occur in a single frame before remainder are dropped for the frame. - /// - [Tooltip("Maximum number of ticks which may occur in a single frame before remainder are dropped for the frame.")] - [Range(1, 25)] - [SerializeField] - private byte _maximumFrameTicks = 2; - /// - /// - /// - [Tooltip("How many times per second the server will simulate. This does not limit server frame rate.")] - [Range(1, 240)] - [SerializeField] - private ushort _tickRate = 30; - /// - /// How many times per second the server will simulate. This does not limit server frame rate. - /// - public ushort TickRate { get => _tickRate; private set => _tickRate = value; } - /// - /// - /// - [Tooltip("How often in seconds to a connections ping. This is also responsible for approximating server tick. This value does not affect prediction.")] - [Range(1, 15)] - [SerializeField] - private byte _pingInterval = 1; - /// - /// How often in seconds to a connections ping. This is also responsible for approximating server tick. This value does not affect prediction. - /// - internal byte PingInterval => _pingInterval; - /// - /// How often in seconds to update prediction timing. Lower values will result in marginally more accurate timings at the cost of bandwidth. - /// - [Tooltip("How often in seconds to update prediction timing. Lower values will result in marginally more accurate timings at the cost of bandwidth.")] - [Range(1, 15)] - [SerializeField] - private byte _timingInterval = 2; - /// - /// - /// - [Tooltip("How to perform physics.")] - [SerializeField] - private PhysicsMode _physicsMode = PhysicsMode.Unity; - /// - /// How to perform physics. - /// - public PhysicsMode PhysicsMode => _physicsMode; - #endregion - - #region Private. - /// - /// Ticks that have passed on client since the last time server sent an UpdateTicksBroadcast. - /// - private uint _clientTicks = 0; - /// - /// Last Tick the server sent out UpdateTicksBroadcast. - /// - private uint _lastUpdateTicks = 0; - /// - /// - /// - private uint _localTick; - /// - /// A tick that is not synchronized. This value will only increment. May be used for indexing or Ids with custom logic. - /// When called on the server Tick is returned, otherwise LocalTick is returned. - /// This value resets upon disconnecting. - /// - public uint LocalTick - { - get => (_networkManager.IsServer) ? Tick : _localTick; - private set => _localTick = value; - } - /// - /// Stopwatch used for pings. - /// - SystemStopwatch _pingStopwatch = new SystemStopwatch(); - /// - /// Ticks passed since last ping. - /// - private uint _pingTicks; - /// - /// MovingAverage instance used to calculate mean ping. - /// - private MovingAverage _pingAverage = new MovingAverage(5); - /// - /// Accumulating frame time to determine when to increase tick. - /// - private double _elapsedTickTime; - /// - /// NetworkManager used with this. - /// - private NetworkManager _networkManager; - /// - /// Internal deltaTime for clients. Controlled by the server. - /// - private double _adjustedTickDelta; - /// - /// Range which client timing may reside within. - /// - private double[] _clientTimingRange; - /// - /// Last frame an iteration occurred for incoming. - /// - private int _lastIncomingIterationFrame = -1; - /// - /// True if client received Pong since last ping. - /// - private bool _receivedPong = true; - /// - /// Last unscaledTime multiple ticks occurred in a single frame. - /// - private float _lastMultipleTicksTime; - /// - /// Number of TimeManagers open which are using manual physics. - /// - private static uint _manualPhysics; - #endregion - - #region Const. - /// - /// Maximum percentage timing may vary from SimulationInterval for clients. - /// - private const float CLIENT_TIMING_PERCENT_RANGE = 0.5f; - /// - /// Percentage of TickDelta client will adjust when needing to speed up. - /// - private const double CLIENT_SPEEDUP_PERCENT = 0.003d; - /// - /// Percentage of TickDelta client will adjust when needing to slow down. - /// - private const double CLIENT_SLOWDOWN_PERCENT = 0.005d; - /// - /// When steps to be sent to clients are equal to or higher than this value in either direction a reset steps will be sent. - /// - private const byte RESET_STEPS_THRESHOLD = 5; - /// - /// Playerprefs string to load and save user fixed time. - /// - private const string SAVED_FIXED_TIME_TEXT = "SavedFixedTimeFN"; - #endregion - -#if UNITY_EDITOR - private void OnDisable() - { - //If closing/stopping. - if (ApplicationState.IsQuitting()) - { - _manualPhysics = 0; - UnsetSimulationSettings(); - } - else if (PhysicsMode == PhysicsMode.TimeManager) - { - _manualPhysics = Math.Max(0, _manualPhysics - 1); - } - } -#endif - - /// - /// Called when FixedUpdate ticks. This is called before any other script. - /// - internal void TickFixedUpdate() - { - OnFixedUpdate?.Invoke(); - /* Invoke onsimulation if using Unity time. - * Otherwise let the tick cycling part invoke. */ - if (PhysicsMode == PhysicsMode.Unity) - OnPrePhysicsSimulation?.Invoke(Time.fixedDeltaTime); - } - - /// - /// Called when Update ticks. This is called before any other script. - /// - internal void TickUpdate() - { - if (_networkManager.IsServer) - ServerUptime += Time.deltaTime; - if (_networkManager.IsClient) - ClientUptime += Time.deltaTime; - - bool beforeTick = (_updateOrder == UpdateOrder.BeforeTick); - if (beforeTick) - { - OnUpdate?.Invoke(); - MethodLogic(); - } - else - { - MethodLogic(); - OnUpdate?.Invoke(); - } - - void MethodLogic() - { - IncreaseTick(); - /* Invoke onsimulation if using Unity time. - * Otherwise let the tick cycling part invoke. */ - if (PhysicsMode == PhysicsMode.Unity && Time.inFixedTimeStep) - OnPostPhysicsSimulation?.Invoke(Time.fixedDeltaTime); - } - } - - /// - /// Called when LateUpdate ticks. This is called after all other scripts. - /// - internal void TickLateUpdate() - { - OnLateUpdate?.Invoke(); - } - - - /// - /// Initializes this script for use. - /// - internal void InitializeOnce_Internal(NetworkManager networkManager) - { - _networkManager = networkManager; - SetInitialValues(); - _networkManager.ServerManager.OnServerConnectionState += ServerManager_OnServerConnectionState; - _networkManager.ClientManager.OnClientConnectionState += ClientManager_OnClientConnectionState; - - AddNetworkLoops(); - } - - /// - /// Adds network loops to gameObject. - /// - private void AddNetworkLoops() - { - //Writer. - if (!gameObject.TryGetComponent(out _)) - gameObject.AddComponent(); - //Reader. - if (!gameObject.TryGetComponent(out _)) - gameObject.AddComponent(); - } - - - /// - /// Called after the local client connection state changes. - /// - private void ClientManager_OnClientConnectionState(ClientConnectionStateArgs obj) - { - if (obj.ConnectionState != LocalConnectionState.Started) - { - _pingStopwatch.Stop(); - ClientUptime = 0f; - - //Only reset ticks if also not server. - if (!_networkManager.IsServer) - { - LocalTick = 0; - Tick = 0; - } - } - //Started. - else - { - _pingStopwatch.Restart(); - } - } - - /// - /// Called after the local server connection state changes. - /// - private void ServerManager_OnServerConnectionState(ServerConnectionStateArgs obj) - { - //If no servers are running. - if (!_networkManager.ServerManager.AnyServerStarted()) - { - ServerUptime = 0f; - Tick = 0; - } - } - - /// - /// Sets values to use based on settings. - /// - private void SetInitialValues() - { - SetTickRate(TickRate); - InitializePhysicsMode(PhysicsMode); - } - - /// - /// Sets simulation settings to Unity defaults. - /// - private void UnsetSimulationSettings() - { - Physics.autoSimulation = true; -#if !UNITY_2020_2_OR_NEWER - Physics2D.autoSimulation = true; -#else - Physics2D.simulationMode = SimulationMode2D.FixedUpdate; -#endif - - float simulationTime = PlayerPrefs.GetFloat(SAVED_FIXED_TIME_TEXT, float.MinValue); - if (simulationTime != float.MinValue) - Time.fixedDeltaTime = simulationTime; - } - - /// - /// Initializes physics mode when starting. - /// - /// - private void InitializePhysicsMode(PhysicsMode mode) - { - //Disable. - if (mode == PhysicsMode.Disabled) - { - SetPhysicsMode(mode); - } - //Do not automatically simulate. - else if (mode == PhysicsMode.TimeManager) - { -#if UNITY_EDITOR - //Preserve user tick rate. - PlayerPrefs.SetFloat(SAVED_FIXED_TIME_TEXT, Time.fixedDeltaTime); - //Let the player know. - if (Time.fixedDeltaTime != (float)TickDelta) - Debug.LogWarning("Time.fixedDeltaTime is being overriden with TimeManager.TickDelta"); -#endif - Time.fixedDeltaTime = (float)TickDelta; - /* Only check this if network manager - * is not null. It would be null via - * OnValidate. */ - if (_networkManager != null) - { - //If at least one time manager is already running manual physics. - if (_manualPhysics > 0) - _networkManager.LogError($"There are multiple TimeManagers instantiated which are using manual physics. Manual physics with multiple TimeManagers is not supported."); - - _manualPhysics++; - } - - SetPhysicsMode(mode); - } - //Automatically simulate. - else - { -#if UNITY_EDITOR - float savedTime = PlayerPrefs.GetFloat(SAVED_FIXED_TIME_TEXT, float.MinValue); - if (savedTime != float.MinValue && Time.fixedDeltaTime != savedTime) - { - Debug.LogWarning("Time.fixedDeltaTime has been set back to user values."); - Time.fixedDeltaTime = savedTime; - } - - PlayerPrefs.DeleteKey(SAVED_FIXED_TIME_TEXT); -#endif - SetPhysicsMode(mode); - } - } - - /// - /// Updates physics based on which physics mode to use. - /// - /// - public void SetPhysicsMode(PhysicsMode mode) - { - _physicsMode = mode; - - //Disable. - if (mode == PhysicsMode.Disabled || mode == PhysicsMode.TimeManager) - { - Physics.autoSimulation = false; -#if !UNITY_2020_2_OR_NEWER - Physics2D.autoSimulation = false; -#else - Physics2D.simulationMode = SimulationMode2D.Script; -#endif - } - //Automatically simulate. - else - { - Physics.autoSimulation = true; -#if !UNITY_2020_2_OR_NEWER - Physics2D.autoSimulation = true; -#else - Physics2D.simulationMode = SimulationMode2D.FixedUpdate; -#endif - } - } - - #region PingPong. - /// - /// Modifies client ping based on LocalTick and clientTIck. - /// - /// - internal void ModifyPing(uint clientTick) - { - uint tickDifference = (LocalTick - clientTick); - _pingAverage.ComputeAverage(tickDifference); - double averageInTime = (_pingAverage.Average * TickDelta * 1000); - RoundTripTime = (long)Math.Round(averageInTime); - _receivedPong = true; - - OnRoundTripTimeUpdated?.Invoke(RoundTripTime); - } - - /// - /// Sends a ping to the server. - /// - private void TrySendPing(uint? tickOverride = null) - { - byte pingInterval = PingInterval; - - /* How often client may send ping is based on if - * the server responded to the last ping. - * A response may not be received if the server - * believes the client is pinging too fast, or if the - * client is having difficulties reaching the server. */ - long requiredTime = (pingInterval * 1000); - float multiplier = (_receivedPong) ? 1f : 1.5f; - - requiredTime = (long)(requiredTime * multiplier); - uint requiredTicks = TimeToTicks(pingInterval * multiplier); - - _pingTicks++; - /* We cannot just consider time because ticks might run slower - * from adjustments. We also cannot only consider ticks because - * they might run faster from adjustments. Therefor require both - * to have pass checks. */ - if (_pingTicks < requiredTicks || _pingStopwatch.ElapsedMilliseconds < requiredTime) - return; - - _pingTicks = 0; - _pingStopwatch.Restart(); - //Unset receivedPong, wait for new response. - _receivedPong = false; - - uint tick = (tickOverride == null) ? LocalTick : tickOverride.Value; - using (PooledWriter writer = WriterPool.GetWriter()) - { - writer.WritePacketId(PacketId.PingPong); - writer.WriteUInt32(tick, AutoPackType.Unpacked); - _networkManager.TransportManager.SendToServer((byte)Channel.Unreliable, writer.GetArraySegment()); - } - } - - /// - /// Sends a pong to a client. - /// - internal void SendPong(NetworkConnection conn, uint clientTick) - { - if (!conn.IsActive || !conn.Authenticated) - return; - - using (PooledWriter writer = WriterPool.GetWriter()) - { - writer.WritePacketId(PacketId.PingPong); - writer.WriteUInt32(clientTick, AutoPackType.Unpacked); - conn.SendToClient((byte)Channel.Unreliable, writer.GetArraySegment()); - } - } - #endregion - - /// - /// Increases the tick based on simulation rate. - /// - private void IncreaseTick() - { - bool isClient = _networkManager.IsClient; - bool isServer = _networkManager.IsServer; - - double tickDelta = TickDelta; - double timePerSimulation = (isServer) ? tickDelta : _adjustedTickDelta; - double time = Time.unscaledDeltaTime; - _elapsedTickTime += time; - FrameTicked = (_elapsedTickTime >= timePerSimulation); - - //Number of ticks to occur this frame. - int ticksCount = Mathf.FloorToInt((float)(_elapsedTickTime / timePerSimulation)); - if (ticksCount > 1) - _lastMultipleTicksTime = Time.unscaledDeltaTime; - - if (_allowTickDropping && !_networkManager.IsServer) - { - //If ticks require dropping. Set exactly to maximum ticks. - if (ticksCount > _maximumFrameTicks) - _elapsedTickTime = (timePerSimulation * (double)_maximumFrameTicks); - } - - bool variableTiming = (_timingType == TimingType.Variable); - bool frameTicked = FrameTicked; - - do - { - if (frameTicked) - { - _elapsedTickTime -= timePerSimulation; - OnPreTick?.Invoke(); - } - - /* This has to be called inside the loop because - * OnPreTick promises data hasn't been read yet. - * Therefor iterate must occur after OnPreTick. - * Iteration will only run once per frame. */ - if (frameTicked || variableTiming) - TryIterateData(true); - - if (frameTicked) - { - OnTick?.Invoke(); - - if (PhysicsMode == PhysicsMode.TimeManager) - { - float tick = (float)TickDelta; - OnPrePhysicsSimulation?.Invoke(tick); - Physics.Simulate(tick); - Physics2D.Simulate(tick); - OnPostPhysicsSimulation?.Invoke(tick); - } - - OnPostTick?.Invoke(); - /* If isClient this is the - * last tick during this loop. */ - if (isClient && (_elapsedTickTime < timePerSimulation)) - { - _networkManager.ClientManager.SendLodUpdate(false); - TrySendPing(LocalTick + 1); - } - - if (_networkManager.IsServer) - SendTimingAdjustment(); - } - - //Send out data. - if (frameTicked || variableTiming) - TryIterateData(false); - - if (frameTicked) - { - if (_networkManager.IsClient) - _clientTicks++; - - Tick++; - LocalTick++; - - _networkManager.ObserverManager.CalculateLevelOfDetail(LocalTick); - } - - } while (_elapsedTickTime >= timePerSimulation); - } - - - - #region Tick conversions. - /// - /// Returns the percentage of how far the TimeManager is into the next tick. - /// - /// - public double GetTickPercent() - { - if (_networkManager == null) - return default; - - double delta = (_networkManager.IsServer) ? TickDelta : _adjustedTickDelta; - double percent = (_elapsedTickTime / delta) * 100d; - return percent; - } - /// - /// Returns a PreciseTick. - /// - /// Tick to set within the returned PreciseTick. - /// - public PreciseTick GetPreciseTick(uint tick) - { - if (_networkManager == null) - return default; - - double delta = (_networkManager.IsServer) ? TickDelta : _adjustedTickDelta; - double percent = (_elapsedTickTime / delta) * 100; - - return new PreciseTick(tick, percent); - } - /// - /// Returns a PreciseTick. - /// - /// Tick to use within PreciseTick. - /// - public PreciseTick GetPreciseTick(TickType tickType) - { - if (_networkManager == null) - return default; - - if (tickType == TickType.Tick) - { - return GetPreciseTick(Tick); - } - else if (tickType == TickType.LocalTick) - { - return GetPreciseTick(LocalTick); - } - else if (tickType == TickType.LastPacketTick) - { - return GetPreciseTick(LastPacketTick); - } - else - { - _networkManager.LogError($"TickType {tickType.ToString()} is unhandled."); - return default; - } - } - - - /// - /// Converts current ticks to time. - /// - /// TickType to compare against. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double TicksToTime(TickType tickType = TickType.LocalTick) - { - if (tickType == TickType.LocalTick) - { - return TicksToTime(LocalTick); - } - else if (tickType == TickType.Tick) - { - return TicksToTime(Tick); - } - else if (tickType == TickType.LastPacketTick) - { - return TicksToTime(LastPacketTick); - } - else - { - _networkManager.LogError($"TickType {tickType} is unhandled."); - return 0d; - } - } - - /// - /// Converts a number ticks to time. - /// - /// Ticks to convert. - /// - public double TicksToTime(uint ticks) - { - return (TickDelta * (double)ticks); - } - - /// - /// Gets time passed from currentTick to previousTick. - /// - /// The current tick. - /// The previous tick. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double TimePassed(uint currentTick, uint previousTick) - { - double multiplier; - double result; - if (currentTick >= previousTick) - { - multiplier = 1f; - result = TicksToTime(currentTick - previousTick); - } - else - { - multiplier = -1f; - result = TicksToTime(previousTick - currentTick); - } - - return (result * multiplier); - } - - /// - /// Gets time passed from Tick to preciseTick. - /// - /// PreciseTick value to compare against. - /// True to allow negative values. When false and value would be negative 0 is returned. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double TimePassed(PreciseTick preciseTick, bool allowNegative = false) - { - PreciseTick currentPt = GetPreciseTick(TickType.Tick); - - long tickDifference = (currentPt.Tick - preciseTick.Tick); - double percentDifference = (currentPt.Percent - preciseTick.Percent); - - /* If tickDifference is less than 0 or tickDifference and percentDifference are 0 or less - * then the result would be negative. */ - bool negativeValue = (tickDifference < 0 || (tickDifference <= 0 && percentDifference <= 0)); - - if (!allowNegative && negativeValue) - return 0d; - - double tickTime = TimePassed(preciseTick.Tick, true); - double percent = (percentDifference / 100); - double percentTime = (percent * TickDelta); - - return (tickTime + percentTime); - } - /// - /// Gets time passed from Tick to previousTick. - /// - /// The previous tick. - /// True to allow negative values. When false and value would be negative 0 is returned. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double TimePassed(uint previousTick, bool allowNegative = false) - { - uint currentTick = Tick; - //Difference will be positive. - if (currentTick >= previousTick) - { - return TicksToTime(currentTick - previousTick); - } - //Difference would be negative. - else - { - if (!allowNegative) - { - return 0d; - } - else - { - double difference = TicksToTime(previousTick - currentTick); - return (difference * -1d); - } - } - } - - /// - /// Converts time to ticks. - /// - /// Time to convert. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public uint TimeToTicks(double time, TickRounding rounding = TickRounding.RoundNearest) - { - double result = (time / TickDelta); - - if (rounding == TickRounding.RoundNearest) - return (uint)Math.Round(result); - else if (rounding == TickRounding.RoundDown) - return (uint)Math.Floor(result); - else - return (uint)Math.Ceiling(result); - } - - /// - /// Estimatedly converts a synchronized tick to what it would be for the local tick. - /// - /// Synchronized tick to convert. - /// - public uint TickToLocalTick(uint tick) - { - //Server will always have local and tick aligned. - if (_networkManager.IsServer) - return tick; - - long difference = (Tick - tick); - //If no ticks have passed then return current local tick. - if (difference <= 0) - return LocalTick; - - long result = (LocalTick - difference); - if (result <= 0) - result = 0; - - return (uint)result; - } - /// - /// Estimatedly converts a local tick to what it would be for the synchronized tick. - /// - /// Local tick to convert. - /// - public uint LocalTickToTick(uint localTick) - { - //Server will always have local and tick aligned. - if (_networkManager.IsServer) - return localTick; - - long difference = (LocalTick - localTick); - //If no ticks have passed then return current local tick. - if (difference <= 0) - return Tick; - - long result = (Tick - difference); - if (result <= 0) - result = 0; - - return (uint)result; - - } - #endregion - - - /// - /// Tries to iterate incoming or outgoing data. - /// - /// True to iterate incoming. - private void TryIterateData(bool incoming) - { - if (incoming) - { - /* It's not possible for data to come in - * more than once per frame but there could - * be new data going out each tick, since - * movement is often based off the tick system. - * Because of this don't iterate incoming if - * it's the same frame but the outgoing - * may iterate multiple times per frame. */ - int frameCount = Time.frameCount; - if (frameCount == _lastIncomingIterationFrame) - return; - _lastIncomingIterationFrame = frameCount; - - _networkManager.TransportManager.IterateIncoming(true); - _networkManager.TransportManager.IterateIncoming(false); - } - else - { - _networkManager.TransportManager.IterateOutgoing(true); - _networkManager.TransportManager.IterateOutgoing(false); - } - } - - - #region Timing adjusting. - /// - /// Sends a TimingUpdate packet to clients. - /// - private void SendTimingAdjustment() - { - uint requiredTicks = TimeToTicks(_timingInterval); - uint tick = Tick; - if (tick - _lastUpdateTicks >= requiredTicks) - { - //Now send using a packetId. - PooledWriter writer = WriterPool.GetWriter(); - writer.WritePacketId(PacketId.TimingUpdate); - _networkManager.TransportManager.SendToClients((byte)Channel.Unreliable, writer.GetArraySegment()); - writer.Dispose(); - - _lastUpdateTicks = tick; - } - } - - /// - /// Called on client when server sends a timing update. - /// - /// - internal void ParseTimingUpdate() - { - //Don't adjust timing on server. - if (_networkManager.IsServer) - return; - - //Add half of rtt onto tick. - uint rttTicks = TimeToTicks((RoundTripTime / 2) / 1000f); - Tick = LastPacketTick + rttTicks; - uint expected = (uint)(TickRate * _timingInterval); - long difference; - //If ticking too fast. - if (_clientTicks > expected) - difference = (long)(_clientTicks - expected); - //Not ticking fast enough. - else - difference = (long)((expected - _clientTicks) * -1); - - //If difference is unusually off then reset timings. - if (Mathf.Abs(difference) >= RESET_STEPS_THRESHOLD) - { - _adjustedTickDelta = TickDelta; - } - else - { - sbyte steps = (sbyte)Mathf.Clamp(difference, sbyte.MinValue, sbyte.MaxValue); - double percent = (steps < 0) ? CLIENT_SPEEDUP_PERCENT : CLIENT_SLOWDOWN_PERCENT; - double change = (steps * (percent * TickDelta)); - - _adjustedTickDelta = MathFN.ClampDouble(_adjustedTickDelta + change, _clientTimingRange[0], _clientTimingRange[1]); - } - - _clientTicks = 0; - } - #endregion - - /// - /// Sets the TickRate to use. This value is not synchronized, it must be set on client and server independently. - /// - /// New TickRate to use. - public void SetTickRate(ushort value) - { - TickRate = value; - TickDelta = (1d / TickRate); - _adjustedTickDelta = TickDelta; - _clientTimingRange = new double[] - { - TickDelta * (1f - CLIENT_TIMING_PERCENT_RANGE), - TickDelta * (1f + CLIENT_TIMING_PERCENT_RANGE) - }; - } - - #region UNITY_EDITOR - private void OnValidate() - { - SetInitialValues(); - } - #endregion - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs.meta b/Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs.meta deleted file mode 100644 index 5f8b64f..0000000 --- a/Assets/FishNet/Runtime/Managing/Timing/TimeManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3fdaae44044276a49a52229c1597e33b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Transporting.meta b/Assets/FishNet/Runtime/Managing/Transporting.meta deleted file mode 100644 index 089da21..0000000 --- a/Assets/FishNet/Runtime/Managing/Transporting.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: dadeb2231e0f13b418e05dfc6c4321f6 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Transporting/IntermediateLayer.cs b/Assets/FishNet/Runtime/Managing/Transporting/IntermediateLayer.cs deleted file mode 100644 index 2836b59..0000000 --- a/Assets/FishNet/Runtime/Managing/Transporting/IntermediateLayer.cs +++ /dev/null @@ -1,36 +0,0 @@ - -using System; -using UnityEngine; - -namespace FishNet.Managing.Transporting -{ - - /// - /// When inherited from this may be used with the TransportManager to alter messages before they are sent and received. - /// - public abstract class IntermediateLayer : MonoBehaviour - { - /// - /// TransportManager associated with this script. - /// - public TransportManager TransportManager { get; private set; } - - /// - /// Called when data is received. - /// - /// Original data. - /// True if receiving from the server, false if from a client. - /// Modified data. - public abstract ArraySegment HandleIncoming(ArraySegment src, bool fromServer); - /// - /// Called when data is sent. - /// - /// Original data. - /// True if sending to the server, false if to a client. - /// Modified data. - public abstract ArraySegment HandleOutoing(ArraySegment src, bool toServer); - - internal void InitializeOnce(TransportManager manager) => TransportManager = manager; - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Transporting/IntermediateLayer.cs.meta b/Assets/FishNet/Runtime/Managing/Transporting/IntermediateLayer.cs.meta deleted file mode 100644 index c6a1f1c..0000000 --- a/Assets/FishNet/Runtime/Managing/Transporting/IntermediateLayer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3f8a2e0f9aaea614887f5f7b15350e46 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Transporting/LatencySimulator.cs b/Assets/FishNet/Runtime/Managing/Transporting/LatencySimulator.cs deleted file mode 100644 index ef252f9..0000000 --- a/Assets/FishNet/Runtime/Managing/Transporting/LatencySimulator.cs +++ /dev/null @@ -1,376 +0,0 @@ -using FishNet.Connection; -using FishNet.Transporting; -using FishNet.Utility.Performance; -using System; -using System.Collections.Generic; -using UnityEngine; - -//Thanks to TiToMoskito originally creating this as a Transport. -//https://github.com/TiToMoskito/FishyLatency -namespace FishNet.Managing.Transporting -{ - [System.Serializable] - public class LatencySimulator - { - #region Types. - /// - /// A message affected by latency. - /// - private struct Message - { - public readonly int ConnectionId; - public readonly byte[] Data; - public readonly int Length; - public readonly float SendTime; - - public Message(int connectionId, ArraySegment segment, float latency) - { - this.ConnectionId = connectionId; - this.SendTime = (Time.unscaledTime + latency); - this.Length = segment.Count; - this.Data = ByteArrayPool.Retrieve(this.Length); - Buffer.BlockCopy(segment.Array, segment.Offset, this.Data, 0, this.Length); - } - - public ArraySegment GetSegment() - { - return new ArraySegment(Data, 0, Length); - } - } - #endregion - - #region Internal. - /// - /// True if latency can be simulated. - /// - internal bool CanSimulate => (GetEnabled() && (GetLatency() > 0 || GetPacketLost() > 0 || GetOutOfOrder() > 0)); - #endregion - - #region Serialized - [Header("Settings")] - /// - /// - /// - [Tooltip("True if latency simulator is enabled.")] - [SerializeField] - private bool _enabled; - /// - /// Gets the enabled value of simulator. - /// - public bool GetEnabled() => _enabled; - /// - /// Sets the enabled value of simulator. - /// - /// New value. - public void SetEnabled(bool value) - { - if (value == _enabled) - return; - - _enabled = value; - Reset(); - } - /// - /// - /// - [Tooltip("True to add latency on clientHost as well.")] - [SerializeField] - private bool _simulateHost = true; - /// - /// Milliseconds to add between packets. When acting as host this value will be doubled. Added latency will be a minimum of tick rate. - /// - [Tooltip("Milliseconds to add between packets. When acting as host this value will be doubled. Added latency will be a minimum of tick rate.")] - [Range(0, 60000)] - [SerializeField] - private long _latency = 0; - /// - /// Gets the latency value. - /// - /// - public long GetLatency() => _latency; - /// - /// Sets a new latency value. - /// - /// Latency as milliseconds. - public void SetLatency(long value) => _latency = value; - - [Header("Unreliable")] - /// - /// Percentage of unreliable packets which should arrive out of order. - /// - [Tooltip("Percentage of unreliable packets which should arrive out of order.")] - [Range(0f, 1f)] - [SerializeField] - private double _outOfOrder = 0; - /// - /// Out of order chance, 1f is a 100% chance to occur. - /// - /// - public double GetOutOfOrder() => _outOfOrder; - /// - /// Sets out of order chance. 1f is a 100% chance to occur. - /// - /// New Value. - public void SetOutOfOrder(double value) => _outOfOrder = value; - /// - /// Percentage of packets which should drop. - /// - [Tooltip("Percentage of packets which should drop.")] - [Range(0, 1)] - [SerializeField] - private double _packetLoss = 0; - /// - /// Gets packet loss chance. 1f is a 100% chance to occur. - /// - /// - public double GetPacketLost() => _packetLoss; - /// - /// Sets packet loss chance. 1f is a 100% chance to occur. - /// - /// New Value. - public void SetPacketLoss(double value) => _packetLoss = value; - #endregion - - #region Private - /// - /// Transport to send data on. - /// - private Transport _transport; - /// - /// Reliable messages to the server. - /// - private List _toServerReliable = new List(); - /// - /// Unreliable messages to the server. - /// - private List _toServerUnreliable = new List(); - /// - /// Reliable messages to clients. - /// - private List _toClientReliable = new List(); - /// - /// Unreliable messages to clients. - /// - private List _toClientUnreliable = new List(); - /// - /// NetworkManager for this instance. - /// - private NetworkManager _networkManager; - /// - /// Used to generate chances of latency. - /// - private readonly System.Random _random = new System.Random(); - #endregion - - #region Initialization and Unity - public void Initialize(NetworkManager manager, Transport transport) - { - _networkManager = manager; - _transport = transport; - } - #endregion - - /// - /// Stops both client and server. - /// - public void Reset() - { - bool enabled = GetEnabled(); - if (_transport != null && enabled) - { - IterateAndStore(_toServerReliable); - IterateAndStore(_toServerUnreliable); - IterateAndStore(_toClientReliable); - IterateAndStore(_toClientUnreliable); - } - - void IterateAndStore(List messages) - { - foreach (Message m in messages) - { - _transport.SendToServer((byte)Channel.Reliable, m.GetSegment()); - ByteArrayPool.Store(m.Data); - } - } - - _toServerReliable.Clear(); - _toServerUnreliable.Clear(); - _toClientReliable.Clear(); - _toClientUnreliable.Clear(); - } - - /// - /// Removes pending or held packets for a connection. - /// - /// Connection to remove pending packets for. - public void RemovePendingForConnection(int connectionId) - { - RemoveFromCollection(_toServerUnreliable); - RemoveFromCollection(_toServerUnreliable); - RemoveFromCollection(_toClientReliable); - RemoveFromCollection(_toClientUnreliable); - - void RemoveFromCollection(List c) - { - for (int i = 0; i < c.Count; i++) - { - if (c[i].ConnectionId == connectionId) - { - c.RemoveAt(i); - i--; - } - } - } - } - - #region Simulation - /// - /// Returns long latency as a float. - /// - /// - /// - private float GetLatencyAsFloat() - { - return (float)(_latency / 1000f); - } - - /// - /// Adds a packet for simulation. - /// - public void AddOutgoing(byte channelId, ArraySegment segment, bool toServer = true, int connectionId = -1) - { - /* If to not simulate for host see if this packet - * should be sent normally. */ - if (!_simulateHost && _networkManager != null && _networkManager.IsHost) - { - /* If going to the server and is host then - * it must be sent from clientHost. */ - if (toServer) - { - _transport.SendToServer(channelId, segment); - return; - } - //Not to server, see if going to clientHost. - else - { - //If connId is the same as clientHost id. - if (_networkManager.ClientManager.Connection.ClientId == connectionId) - { - _transport.SendToClient(channelId, segment, connectionId); - return; - } - } - } - - List collection; - Channel c = (Channel)channelId; - - if (toServer) - collection = (c == Channel.Reliable) ? _toServerReliable : _toServerUnreliable; - else - collection = (c == Channel.Reliable) ? _toClientReliable : _toClientUnreliable; - - float latency = GetLatencyAsFloat(); - //If dropping check to add extra latency if reliable, or discard if not. - if (DropPacket()) - { - if (c == Channel.Reliable) - { - latency += (latency * 0.3f); //add extra for resend. - } - //If not reliable then return the segment array to pool. - else - { - return; - } - } - - Message msg = new Message(connectionId, segment, latency); - int count = collection.Count; - if (c == Channel.Unreliable && count > 0 && OutOfOrderPacket(c)) - collection.Insert(count - 1, msg); - else - collection.Add(msg); - } - - /// - /// Simulates pending outgoing packets. - /// - /// True if sending to the server. - public void IterateOutgoing(bool toServer) - { - if (_transport == null) - { - Reset(); - return; - } - - if (toServer) - { - IterateCollection(_toServerReliable, Channel.Reliable); - IterateCollection(_toServerUnreliable, Channel.Unreliable); - } - else - { - IterateCollection(_toClientReliable, Channel.Reliable); - IterateCollection(_toClientUnreliable, Channel.Unreliable); - } - - void IterateCollection(List collection, Channel channel) - { - byte cByte = (byte)channel; - float unscaledTime = Time.unscaledTime; - - int count = collection.Count; - int iterations = 0; - for (int i = 0; i < count; i++) - { - Message msg = collection[i]; - //Not enough time has passed. - if (unscaledTime < msg.SendTime) - break; - - if (toServer) - _transport.SendToServer(cByte, msg.GetSegment()); - else - _transport.SendToClient(cByte, msg.GetSegment(), msg.ConnectionId); - - iterations++; - } - - if (iterations > 0) - { - for (int i = 0; i < iterations; i++) - ByteArrayPool.Store(collection[i].Data); - collection.RemoveRange(0, iterations); - } - } - - _transport.IterateOutgoing(toServer); - } - - /// - /// Returns if a packet should drop. - /// - /// - private bool DropPacket() - { - return (_packetLoss > 0d && (_random.NextDouble() < _packetLoss)); - } - - /// - /// Returns if a packet should be out of order. - /// - /// - /// - private bool OutOfOrderPacket(Channel c) - { - if (c == Channel.Reliable) - return false; - - return (_outOfOrder > 0d && (_random.NextDouble() < _outOfOrder)); - } - #endregion - } -} - diff --git a/Assets/FishNet/Runtime/Managing/Transporting/LatencySimulator.cs.meta b/Assets/FishNet/Runtime/Managing/Transporting/LatencySimulator.cs.meta deleted file mode 100644 index 7eb5b8b..0000000 --- a/Assets/FishNet/Runtime/Managing/Transporting/LatencySimulator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 82bfafe804acb534fbf04c88de6eeed1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Transporting/SplitReader.cs b/Assets/FishNet/Runtime/Managing/Transporting/SplitReader.cs deleted file mode 100644 index 704f859..0000000 --- a/Assets/FishNet/Runtime/Managing/Transporting/SplitReader.cs +++ /dev/null @@ -1,99 +0,0 @@ -using FishNet.Serializing; -using System; -using UnityEngine; - -namespace FishNet.Managing.Transporting -{ - - internal class SplitReader - { - #region Private. - /// - /// Tick split is for. - /// Tick must be a negative value so that it's impossible for the first tick to align. - /// - private long _tick = -1; - /// - /// Expected number of splits. - /// - private int _expectedMessages; - /// - /// Number of splits received so far. - /// - private ushort _receivedMessages; - /// - /// Writer containing split packet combined. - /// - private PooledWriter _writer = WriterPool.GetWriter(); - #endregion - - internal SplitReader() - { - //Increase capacity to reduce the chance of resizing. - _writer.EnsureBufferCapacity(20000); - } - - /// - /// Gets split header values. - /// - internal void GetHeader(PooledReader reader, out int expectedMessages) - { - expectedMessages = reader.ReadInt32(); - } - - /// - /// Combines split data. - /// - internal void Write(uint tick, PooledReader reader, int expectedMessages) - { - //New tick which means new split. - if (tick != _tick) - Reset(tick, expectedMessages); - - /* This is just a guess as to how large the end - * message could be. If the writer is not the minimum - * of this length then resize it. */ - int estimatedBufferSize = (expectedMessages * 1500); - if (_writer.Capacity < estimatedBufferSize) - _writer.EnsureBufferCapacity(estimatedBufferSize); - /* Empty remainder of reader into the writer. - * It does not matter if parts of the reader - * contain data added after the split because - * once the split is fully combined the data - * is parsed as though it came in as one message, - * which is how data is normally read. */ - ArraySegment data = reader.ReadArraySegment(reader.Remaining); - _writer.WriteArraySegment(data); - _receivedMessages++; - } - - /// - /// Returns if all split messages have been received. - /// - /// - internal ArraySegment GetFullMessage() - { - if (_receivedMessages < _expectedMessages) - { - return default(ArraySegment); - } - else - { - ArraySegment segment = _writer.GetArraySegment(); - Reset(); - return segment; - } - } - - private void Reset(uint tick = 0, int expectedMessages = 0) - { - _tick = tick; - _receivedMessages = 0; - _expectedMessages = expectedMessages; - _writer.Reset(); - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Transporting/SplitReader.cs.meta b/Assets/FishNet/Runtime/Managing/Transporting/SplitReader.cs.meta deleted file mode 100644 index 3c123e3..0000000 --- a/Assets/FishNet/Runtime/Managing/Transporting/SplitReader.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a1c06be1540b77842be35823aa54b19b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Transporting/TransportManager.QOL.cs b/Assets/FishNet/Runtime/Managing/Transporting/TransportManager.QOL.cs deleted file mode 100644 index 3cf8b76..0000000 --- a/Assets/FishNet/Runtime/Managing/Transporting/TransportManager.QOL.cs +++ /dev/null @@ -1,65 +0,0 @@ -using FishNet.Transporting; -using FishNet.Transporting.Multipass; -using UnityEngine; - -namespace FishNet.Managing.Transporting -{ - - /// - /// Communicates with the Transport to send and receive data. - /// - public sealed partial class TransportManager : MonoBehaviour - { - #region Public. - /// - /// Returns IsLocalTransport for the current transport. - /// - public bool IsLocalTransport(int connectionId) => (Transport == null) ? false : Transport.IsLocalTransport(connectionId); - #endregion - - - /// - /// Gets transport on index. - /// Commonly index will be 0 unless using Multipass. - /// - /// - public Transport GetTransport(int index) - { - //If using multipass try to find the correct transport. - if (Transport is Multipass mp) - { - return mp.GetTransport(index); - } - //Not using multipass. - else - { - return Transport; - } - } - - /// - /// Gets transport of type T. - /// - /// Returns the found transport which is of type T. Returns default of T if not found. - public T GetTransport() where T : Transport - { - //If using multipass try to find the correct transport. - if (Transport is Multipass mp) - { - if (typeof(T) == typeof(Multipass)) - return (T)(object)mp; - else - return mp.GetTransport(); - } - //Not using multipass. - else - { - if (Transport.GetType() == typeof(T)) - return (T)(object)Transport; - else - return default(T); - } - } - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Transporting/TransportManager.QOL.cs.meta b/Assets/FishNet/Runtime/Managing/Transporting/TransportManager.QOL.cs.meta deleted file mode 100644 index 21ee1b3..0000000 --- a/Assets/FishNet/Runtime/Managing/Transporting/TransportManager.QOL.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: aac8eab4e511d7e4dbc81eb74aea7f23 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Transporting/TransportManager.cs b/Assets/FishNet/Runtime/Managing/Transporting/TransportManager.cs deleted file mode 100644 index b09545b..0000000 --- a/Assets/FishNet/Runtime/Managing/Transporting/TransportManager.cs +++ /dev/null @@ -1,668 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing.Timing; -using FishNet.Serializing; -using FishNet.Transporting; -using FishNet.Transporting.Multipass; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Managing.Transporting -{ - - /// - /// Communicates with the Transport to send and receive data. - /// - [DisallowMultipleComponent] - [AddComponentMenu("FishNet/Manager/TransportManager")] - public sealed partial class TransportManager : MonoBehaviour - { - #region Types. - private struct DisconnectingClient - { - public uint Tick; - public NetworkConnection Connection; - - public DisconnectingClient(uint tick, NetworkConnection connection) - { - Tick = tick; - Connection = connection; - } - } - #endregion - - #region Public. - /// - /// Called before IterateOutgoing has started. - /// - internal event Action OnIterateOutgoingStart; - /// - /// Called after IterateOutgoing has completed. - /// - internal event Action OnIterateOutgoingEnd; - /// - /// Called before IterateIncoming has started. True for on server, false for on client. - /// - internal event Action OnIterateIncomingStart; - /// - /// Called after IterateIncoming has completed. True for on server, false for on client. - /// - internal event Action OnIterateIncomingEnd; - /// - /// The current Transport being used. - /// - [Tooltip("The current Transport being used.")] - public Transport Transport; - #endregion - - #region Serialized. - /// - /// Layer used to modify data before it is sent or received. - /// - [Tooltip("Layer used to modify data before it is sent or received.")] - [SerializeField] - private IntermediateLayer _intermediateLayer; - /// - /// - /// - [Tooltip("Latency simulation settings.")] - [SerializeField] - private LatencySimulator _latencySimulator = new LatencySimulator(); - /// - /// Latency simulation settings. - /// - public LatencySimulator LatencySimulator - { - get - { - //Shouldn't ever be null unless the user nullifies it. - if (_latencySimulator == null) - _latencySimulator = new LatencySimulator(); - return _latencySimulator; - } - } - #endregion - - #region Private. - /// - /// NetworkConnections on the server which have to send data to clients. - /// - private List _dirtyToClients = new List(); - /// - /// PacketBundles to send to the server. - /// - private List _toServerBundles = new List(); - /// - /// NetworkManager handling this TransportManager. - /// - private NetworkManager _networkManager; - /// - /// Clients which are pending disconnects. - /// - private List _disconnectingClients = new List(); - /// - /// Lowest MTU of all transports for channels. - /// - private int[] _lowestMtu; - #endregion - - #region Consts. - /// - /// Number of bytes sent for PacketId. - /// - public const byte PACKET_ID_BYTES = 2; - /// - /// Number of bytes sent for ObjectId. - /// - public const byte OBJECT_ID_BYTES = 2; - /// - /// Number of bytes sent for ComponentIndex. - /// - public const byte COMPONENT_INDEX_BYTES = 1; - /// - /// Number of bytes sent for Tick. - /// - public const byte TICK_BYTES = 4; - /// - /// Number of bytes sent to indicate split count. - /// - private const byte SPLIT_COUNT_BYTES = 4; - /// - /// Number of bytes required for split data. - /// - public const byte SPLIT_INDICATOR_SIZE = (PACKET_ID_BYTES + SPLIT_COUNT_BYTES); - /// - /// Number of channels supported. - /// - public const byte CHANNEL_COUNT = 2; - #endregion - - /// - /// Initializes this script for use. - /// - internal void InitializeOnce_Internal(NetworkManager manager) - { - _networkManager = manager; - /* If transport isn't specified then add default - * transport. */ - if (Transport == null && !gameObject.TryGetComponent(out Transport)) - Transport = gameObject.AddComponent(); - - Transport.Initialize(_networkManager, 0); - //Cache lowest Mtus. - _lowestMtu = new int[CHANNEL_COUNT]; - for (byte i = 0; i < CHANNEL_COUNT; i++) - _lowestMtu[i] = GetLowestMTU(i); - - InitializeToServerBundles(); - if (_intermediateLayer != null) - _intermediateLayer.InitializeOnce(this); -#if UNITY_EDITOR || DEVELOPMENT_BUILD - _latencySimulator.Initialize(manager, Transport); -#endif - } - - /// - /// Sets a connection from server to client dirty. - /// - /// - internal void ServerDirty(NetworkConnection conn) - { - _dirtyToClients.Add(conn); - } - - /// - /// Initializes ToServerBundles for use. - /// - private void InitializeToServerBundles() - { - /* For ease of use FishNet will always have - * only two channels, reliable and unreliable. - * Even if the transport only supports reliable - * also setup for unreliable. */ - for (byte i = 0; i < CHANNEL_COUNT; i++) - { - int mtu = GetLowestMTU(i); - _toServerBundles.Add(new PacketBundle(_networkManager, mtu)); - } - } - - #region GetMTU. - /* Returned MTUs are always -1 to allow an extra byte - * to specify channel where certain transports do - * not allow or provide channel information. */ - /// - /// Returns the lowest MTU for a channel. When using multipass this will evaluate all transports within Multipass. - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetLowestMTU(byte channel) - { - //Use cached if available. - if (_lowestMtu[channel] > 0) - return _lowestMtu[channel]; - - if (Transport is Multipass mp) - { - int? lowestMtu = null; - foreach (Transport t in mp.Transports) - { - int thisMtu = t.GetMTU(channel); - if (lowestMtu == null || thisMtu < lowestMtu.Value) - lowestMtu = thisMtu; - } - - //If lowest was not changed return unset. - if (lowestMtu == null) - { - return -1; - } - else - { - int mtu = lowestMtu.Value; - if (mtu >= 0) - mtu -= 1; - return mtu; - } - } - else - { - return GetMTU(channel); - } - } - /// - /// Gets MTU on the current transport for channel. - /// - /// Channel to get MTU of. - /// - public int GetMTU(byte channel) - { - int mtu = Transport.GetMTU(channel); - if (mtu >= 0) - mtu -= 1; - return mtu; - } - /// - /// Gets MTU on the transportIndex for channel. This requires use of Multipass. - /// - /// Index of the transport to get the MTU on. - /// Channel to get MTU of. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetMTU(int transportIndex, byte channel) - { - if (Transport is Multipass mp) - { - int mtu = mp.GetMTU(channel, transportIndex); - if (mtu >= 0) - mtu -= 1; - return mtu; - } - //Using first/only transport. - else if (transportIndex == 0) - { - return GetMTU(channel); - } - //Unhandled. - else - { - _networkManager.LogWarning($"MTU cannot be returned with transportIndex because {typeof(Multipass).Name} is not in use."); - return -1; - } - } - /// - /// Gets MTU on the transport type for channel. This requires use of Multipass. - /// - /// Tyep of transport to use. - /// Channel to get MTU of. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetMTU(byte channel) where T : Transport - { - Transport transport = GetTransport(); - if (transport != null) - { - int mtu = transport.GetMTU(channel); - if (mtu >= 0) - mtu -= 1; - return mtu; - } - - //Fall through. - return -1; - } - #endregion - - /// - /// Passes received to the intermediate layer. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal ArraySegment ProcessIntermediateIncoming(ArraySegment src, bool fromServer) - { - return (_intermediateLayer == null) ? src : _intermediateLayer.HandleIncoming(src, fromServer); - } - /// - /// Passes sent to the intermediate layer. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private ArraySegment ProcessIntermediateOutgoing(ArraySegment src, bool toServer) - { - return (_intermediateLayer == null) ? src : _intermediateLayer.HandleOutoing(src, toServer); - } - - /// - /// Sends data to a client. - /// - /// Channel to send on. - /// Data to send. - /// Connection to send to. Use null for all clients. - /// True to split large packets which exceed MTU and send them in order on the reliable channel. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void SendToClient(byte channelId, ArraySegment segment, NetworkConnection connection, bool splitLargeMessages = true) - { - segment = ProcessIntermediateOutgoing(segment, false); - SetSplitValues(channelId, segment, splitLargeMessages, out int requiredSplitMessages, out int maxSplitMessageSize); - SendToClient_Internal(channelId, segment, connection, requiredSplitMessages, maxSplitMessageSize); - } - private void SendToClient_Internal(byte channelId, ArraySegment segment, NetworkConnection connection, int requiredSplitMessages, int maxSplitMessageSize) - { - if (connection == null) - return; - - if (requiredSplitMessages > 1) - SendSplitData(connection, ref segment, requiredSplitMessages, maxSplitMessageSize); - else - connection.SendToClient(channelId, segment); - } - - /// - /// Sends data to observers. - /// - /// - /// - /// - /// True to split large packets which exceed MTU and send them in order on the reliable channel. - internal void SendToClients(byte channelId, ArraySegment segment, HashSet observers, HashSet excludedConnections = null, bool splitLargeMessages = true) - { - segment = ProcessIntermediateOutgoing(segment, false); - SetSplitValues(channelId, segment, splitLargeMessages, out int requiredSplitMessages, out int maxSplitMessageSize); - SendToClients_Internal(channelId, segment, observers, excludedConnections, requiredSplitMessages, maxSplitMessageSize); - } - private void SendToClients_Internal(byte channelId, ArraySegment segment, HashSet observers, HashSet excludedConnections, int requiredSplitMessages, int maxSplitMessageSize) - { - if (excludedConnections == null || excludedConnections.Count == 0) - { - foreach (NetworkConnection conn in observers) - SendToClient_Internal(channelId, segment, conn, requiredSplitMessages, maxSplitMessageSize); - } - else - { - foreach (NetworkConnection conn in observers) - { - if (excludedConnections.Contains(conn)) - continue; - SendToClient_Internal(channelId, segment, conn, requiredSplitMessages, maxSplitMessageSize); - } - } - } - - - - /// - /// Sends data to all clients. - /// - /// Channel to send on. - /// Data to send. - /// True to split large packets which exceed MTU and send them in order on the reliable channel. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void SendToClients(byte channelId, ArraySegment segment, bool splitLargeMessages = true) - { - segment = ProcessIntermediateOutgoing(segment, false); - SetSplitValues(channelId, segment, splitLargeMessages, out int requiredSplitMessages, out int maxSplitMessageSize); - SendToClients_Internal(channelId, segment, requiredSplitMessages, maxSplitMessageSize); - } - private void SendToClients_Internal(byte channelId, ArraySegment segment, int requiredSplitMessages, int maxSplitMessageSize) - { - /* Rather than buffer the message once and send to every client - * it must be queued into every client. This ensures clients - * receive the message in order of other packets being - * delivered to them. */ - foreach (NetworkConnection conn in _networkManager.ServerManager.Clients.Values) - SendToClient_Internal(channelId, segment, conn, requiredSplitMessages, maxSplitMessageSize); - } - - /// - /// Sends data to the server. - /// - /// Channel to send on. - /// Data to send. - /// True to split large packets which exceed MTU and send them in order on the reliable channel. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void SendToServer(byte channelId, ArraySegment segment, bool splitLargeMessages = true) - { - segment = ProcessIntermediateOutgoing(segment, true); - SetSplitValues(channelId, segment, splitLargeMessages, out int requiredSplitMessages, out int maxSplitMessageSize); - SendToServer_Internal(channelId, segment, requiredSplitMessages, maxSplitMessageSize); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void SendToServer_Internal(byte channelId, ArraySegment segment, int requiredSplitMessages, int maxSplitMessageSize) - { - if (channelId >= _toServerBundles.Count) - channelId = (byte)Channel.Reliable; - - if (requiredSplitMessages > 1) - SendSplitData(null, ref segment, requiredSplitMessages, maxSplitMessageSize); - else - _toServerBundles[channelId].Write(segment); - } - - #region Splitting. - /// - /// Checks if a message can be split and outputs split information if so. - /// - private void SetSplitValues(byte channelId, ArraySegment segment, bool split, out int requiredSplitMessages, out int maxSplitMessageSize) - { - if (!split) - { - requiredSplitMessages = 0; - maxSplitMessageSize = 0; - } - else - { - SplitRequired(channelId, segment.Count, out requiredSplitMessages, out maxSplitMessageSize); - } - } - /// - /// True if data must be split. - /// - /// - /// - /// - private bool SplitRequired(byte channelId, int segmentSize, out int requiredMessages, out int maxMessageSize) - { - maxMessageSize = GetLowestMTU(channelId) - (TransportManager.TICK_BYTES + SPLIT_INDICATOR_SIZE); - requiredMessages = Mathf.CeilToInt((float)segmentSize / maxMessageSize); - - return (requiredMessages > 1); - } - - /// - /// Splits data going to which is too large to fit within the transport MTU. - /// - /// Connection to send to. If null data will be sent to the server. - /// True if data was sent split. - private void SendSplitData(NetworkConnection conn, ref ArraySegment segment, int requiredMessages, int maxMessageSize) - { - if (requiredMessages <= 1) - { - _networkManager.LogError($"SendSplitData was called with {requiredMessages} required messages. This method should only be called if messages must be split into 2 pieces or more."); - return; - } - - byte channelId = (byte)Channel.Reliable; - PooledWriter headerWriter = WriterPool.GetWriter(); - headerWriter.WritePacketId(PacketId.Split); - headerWriter.WriteInt32(requiredMessages); - ArraySegment headerSegment = headerWriter.GetArraySegment(); - - int writeIndex = 0; - bool firstWrite = true; - //Send to connection until everything is written. - while (writeIndex < segment.Count) - { - int headerReduction = 0; - if (firstWrite) - { - headerReduction = headerSegment.Count; - firstWrite = false; - } - int chunkSize = Mathf.Min(segment.Count - writeIndex - headerReduction, maxMessageSize); - //Make a new array segment for the chunk that is getting split. - ArraySegment splitSegment = new ArraySegment( - segment.Array, segment.Offset + writeIndex, chunkSize); - - //If connection is specified then it's going to a client. - if (conn != null) - { - conn.SendToClient(channelId, headerSegment, true); - conn.SendToClient(channelId, splitSegment); - } - //Otherwise it's going to the server. - else - { - _toServerBundles[channelId].Write(headerSegment, true); - _toServerBundles[channelId].Write(splitSegment, false); - } - - writeIndex += chunkSize; - } - - headerWriter.Dispose(); - } - #endregion - - - /// - /// Processes data received by the socket. - /// - /// True to process data received on the server. - internal void IterateIncoming(bool server) - { - OnIterateIncomingStart?.Invoke(server); - Transport.IterateIncoming(server); - OnIterateIncomingEnd?.Invoke(server); - } - - /// - /// Processes data to be sent by the socket. - /// - /// True to process data received on the server. - internal void IterateOutgoing(bool toServer) - { - OnIterateOutgoingStart?.Invoke(); - int channelCount = CHANNEL_COUNT; - ulong sentBytes = 0; -#if UNITY_EDITOR || DEVELOPMENT_BUILD - bool latencySimulatorEnabled = LatencySimulator.CanSimulate; -#endif - /* If sending to the client. */ - if (!toServer) - { - TimeManager tm = _networkManager.TimeManager; - uint localTick = tm.LocalTick; - //Write any dirty syncTypes. - _networkManager.ServerManager.Objects.WriteDirtySyncTypes(); - - int dirtyCount = _dirtyToClients.Count; - - //Run through all dirty connections to send data to. - for (int z = 0; z < dirtyCount; z++) - { - NetworkConnection conn = _dirtyToClients[z]; - if (conn == null || !conn.IsValid) - continue; - - //Get packets for every channel. - for (byte channel = 0; channel < channelCount; channel++) - { - if (conn.GetPacketBundle(channel, out PacketBundle pb)) - { - for (int i = 0; i < pb.WrittenBuffers; i++) - { - //Length should always be more than 0 but check to be safe. - if (pb.GetBuffer(i, out ByteBuffer bb)) - { - ArraySegment segment = new ArraySegment(bb.Data, 0, bb.Length); -#if UNITY_EDITOR || DEVELOPMENT_BUILD - if (latencySimulatorEnabled) - _latencySimulator.AddOutgoing(channel, segment, false, conn.ClientId); - else -#endif - Transport.SendToClient(channel, segment, conn.ClientId); - sentBytes += (ulong)segment.Count; - } - } - - pb.Reset(); - } - } - - /* When marked as disconnecting data will still be sent - * this iteration but the connection will be marked as invalid. - * This will prevent future data from going out/coming in. - * Also the connection will be added to a disconnecting collection - * so it will it disconnected briefly later to allow data from - * this tick to send. */ - if (conn.Disconnecting) - { - uint requiredTicks = tm.TimeToTicks(0.1d, TickRounding.RoundUp); - /* Require 100ms or 2 ticks to pass - * before disconnecting to allow for the - * higher chance of success that remaining - * data is sent. */ - requiredTicks = Math.Max(requiredTicks, 2); - _disconnectingClients.Add(new DisconnectingClient(requiredTicks + localTick, conn)); - } - - conn.ResetServerDirty(); - } - - //Iterate disconnects. - for (int i = 0; i < _disconnectingClients.Count; i++) - { - DisconnectingClient dc = _disconnectingClients[i]; - if (localTick >= dc.Tick) - { - _networkManager.TransportManager.Transport.StopConnection(dc.Connection.ClientId, true); - _disconnectingClients.RemoveAt(i); - i--; - } - } - - _networkManager.StatisticsManager.NetworkTraffic.LocalServerSentData(sentBytes); - - if (dirtyCount == _dirtyToClients.Count) - _dirtyToClients.Clear(); - else if (dirtyCount > 0) - _dirtyToClients.RemoveRange(0, dirtyCount); - } - /* If sending to the server. */ - else - { - for (byte channel = 0; channel < channelCount; channel++) - { - if (PacketBundle.GetPacketBundle(channel, _toServerBundles, out PacketBundle pb)) - { - for (int i = 0; i < pb.WrittenBuffers; i++) - { - if (pb.GetBuffer(i, out ByteBuffer bb)) - { - ArraySegment segment = new ArraySegment(bb.Data, 0, bb.Length); -#if UNITY_EDITOR || DEVELOPMENT_BUILD - if (latencySimulatorEnabled) - _latencySimulator.AddOutgoing(channel, segment); - else -#endif - Transport.SendToServer(channel, segment); - sentBytes += (ulong)segment.Count; - } - } - pb.Reset(); - } - } - - _networkManager.StatisticsManager.NetworkTraffic.LocalClientSentData(sentBytes); - } - -#if UNITY_EDITOR || DEVELOPMENT_BUILD - if (latencySimulatorEnabled) - _latencySimulator.IterateOutgoing(toServer); -#endif - - Transport.IterateOutgoing(toServer); - OnIterateOutgoingEnd?.Invoke(); - } - - #region Editor. -#if UNITY_EDITOR - private void OnValidate() - { - if (Transport == null) - Transport = GetComponent(); - - /* Update enabled state to force a reset if needed. - * This may be required if the user checked the enabled - * tick box at runtime. If enabled value didn't change - * then the Get will be the same as the Set and nothing - * will happen. */ - _latencySimulator.SetEnabled(_latencySimulator.GetEnabled()); - } -#endif - #endregion - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Transporting/TransportManager.cs.meta b/Assets/FishNet/Runtime/Managing/Transporting/TransportManager.cs.meta deleted file mode 100644 index b3b9a63..0000000 --- a/Assets/FishNet/Runtime/Managing/Transporting/TransportManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 34e4a322dca349547989b14021da4e23 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Utility.meta b/Assets/FishNet/Runtime/Managing/Utility.meta deleted file mode 100644 index bb492a2..0000000 --- a/Assets/FishNet/Runtime/Managing/Utility.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 3be43175b2896f44194e0f4ef13a9ac5 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Managing/Utility/Utility.cs b/Assets/FishNet/Runtime/Managing/Utility/Utility.cs deleted file mode 100644 index 71774dc..0000000 --- a/Assets/FishNet/Runtime/Managing/Utility/Utility.cs +++ /dev/null @@ -1,63 +0,0 @@ -using FishNet.Object; -using FishNet.Serializing; -using FishNet.Transporting; -using UnityEngine; - -namespace FishNet.Managing.Utility -{ - - public class Packets - { - /// - /// Returns written data length for packet. - /// - internal static int GetPacketLength(ushort packetId, PooledReader reader, Channel channel) - { - /* Broadcast is a special circumstance where data - * will not be purged even if unreliable. - * This is because a broadcast receiver may not - * be set, which could be intentional. Because of this - * length is always sent to skip - * past the broadcast data. - * - * Reliables also need length read in the instance a client - * sends data to an object which server is despawning. Without - * parsing length the remainer data from client will be corrupt. */ - PacketId pid = (PacketId)packetId; - if (channel == Channel.Reliable || - pid == PacketId.Broadcast || - pid == PacketId.SyncVar - ) - { - return reader.ReadInt32(); - } - //Unreliable purges remaining. - else if (channel == Channel.Unreliable) - { - return (int)MissingObjectPacketLength.PurgeRemaiming; - } - /* Unhandled. This shouldn't be possible - * since both reliable and unreliable is checked. - * There are no other options. This is merely here - * for a sanity check. */ - else - { - LogError($"Operation is unhandled for packetId {(PacketId)packetId} on channel {channel}."); - return (int)MissingObjectPacketLength.PurgeRemaiming; - } - - //Logs an error message. - void LogError(string message) - { - if (reader.NetworkManager != null) - reader.NetworkManager.LogError(message); - else - NetworkManager.StaticLogError(message); - } - - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Managing/Utility/Utility.cs.meta b/Assets/FishNet/Runtime/Managing/Utility/Utility.cs.meta deleted file mode 100644 index a2a301b..0000000 --- a/Assets/FishNet/Runtime/Managing/Utility/Utility.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: facab6859c82ccd49b2d1c6b80404726 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object.meta b/Assets/FishNet/Runtime/Object.meta deleted file mode 100644 index 194abf7..0000000 --- a/Assets/FishNet/Runtime/Object.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: bcd52ca5352336e44acf3536245b6205 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Attributes.cs b/Assets/FishNet/Runtime/Object/Attributes.cs deleted file mode 100644 index 7742d27..0000000 --- a/Assets/FishNet/Runtime/Object/Attributes.cs +++ /dev/null @@ -1,170 +0,0 @@ -using FishNet.Managing.Logging; -using FishNet.Transporting; -using System; -using UnityEngine; - -namespace FishNet.Object -{ - - /// - /// ServerRpc methods will send messages to the server. - /// - [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)] - public class ServerRpcAttribute : Attribute - { - /// - /// True to only allow the owning client to call this RPC. - /// - public bool RequireOwnership = true; - /// - /// True to also run the RPC logic locally. - /// - public bool RunLocally = false; - /// - /// Estimated length of data being sent. - /// When a value other than -1 the minimum length of the used serializer will be this value. - /// This is useful for writing large packets which otherwise resize the serializer. - /// - public int DataLength = -1; - } - - /// - /// ObserversRpc methods will send messages to all observers. - /// - [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)] - public class ObserversRpcAttribute : Attribute - { - /// - /// True to exclude the owner from receiving this RPC. - /// - public bool ExcludeOwner = false; - /// - /// True to prevent the connection from receiving this Rpc if they are also server. - /// - public bool ExcludeServer = false; - /// - /// True to buffer the last value and send it to new players when the object is spawned for them. - /// RPC will be sent on the same channel as the original RPC, and immediately before the OnSpawnServer override. - /// - public bool BufferLast = false; - /// - /// True to also run the RPC logic locally. - /// - public bool RunLocally = false; - /// - /// Estimated length of data being sent. - /// When a value other than -1 the minimum length of the used serializer will be this value. - /// This is useful for writing large packets which otherwise resize the serializer. - /// - public int DataLength = -1; - } - - /// - /// TargetRpc methods will send messages to a single client. - /// - [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)] - public class TargetRpcAttribute : Attribute - { - /// - /// True to prevent the connection from receiving this Rpc if they are also server. - /// - public bool ExcludeServer = false; - /// - /// True to also run the RPC logic locally. - /// - public bool RunLocally = false; - /// - /// True to validate the target is possible and output debug when not. - /// Use this field with caution as it may create undesired results when set to false. - /// - public bool ValidateTarget = true; - /// - /// Estimated length of data being sent. - /// When a value other than -1 the minimum length of the used serializer will be this value. - /// This is useful for writing large packets which otherwise resize the serializer. - /// - public int DataLength = -1; - } - - /// - /// Prevents a method from running if server is not active. - /// Can only be used inside a NetworkBehaviour - /// - [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)] - public class ServerAttribute : Attribute - { - /// - /// Type of logging to use when the IsServer check fails. - /// - public LoggingType Logging = LoggingType.Warning; - } - - /// - /// Prevents this method from running if client is not active. - /// - [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)] - public class ClientAttribute : Attribute - { - /// - /// Type of logging to use when the IsClient check fails. - /// - public LoggingType Logging = LoggingType.Warning; - /// - /// True to only allow a client to run the method if they are owner of the object. - /// - public bool RequireOwnership = false; - } -} - - -namespace FishNet.Object.Synchronizing -{ - - /// - /// Synchronizes collections or objects from the server to clients. Can be used with custom SyncObjects. - /// Value must be changed on server. - /// - [AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = false)] - public class SyncObjectAttribute : PropertyAttribute - { - /// - /// How often values may update over the network. - /// - public float SendRate = 0.1f; - /// - /// Clients which may receive value updates. - /// - public ReadPermission ReadPermissions = ReadPermission.Observers; - /// - /// True if to require the readonly attribute. - /// Setting to false will allow inspector serialization of this object, but you must never manually initialize this object. - /// - public bool RequireReadOnly = true; - } - - /// - /// Synchronizes a variable from server to clients automatically. - /// Value must be changed on server. - /// - [AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = false)] - public class SyncVarAttribute : PropertyAttribute - { - /// - /// How often values may update over the network. - /// - public float SendRate = 0.1f; - /// - /// Clients which may receive value updates. - /// - public ReadPermission ReadPermissions = ReadPermission.Observers; - /// - /// Channel to use. Unreliable SyncVars will use eventual consistency. - /// - public Channel Channel; - /// - /// Method which will be called on the server and clients when the value changes. - /// - public string OnChange; - } - -} diff --git a/Assets/FishNet/Runtime/Object/Attributes.cs.meta b/Assets/FishNet/Runtime/Object/Attributes.cs.meta deleted file mode 100644 index 9bf2107..0000000 --- a/Assets/FishNet/Runtime/Object/Attributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e2c79ec60813585469c43b4539e3d0c5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/ChangedTransformProperties.cs b/Assets/FishNet/Runtime/Object/ChangedTransformProperties.cs deleted file mode 100644 index 400c957..0000000 --- a/Assets/FishNet/Runtime/Object/ChangedTransformProperties.cs +++ /dev/null @@ -1,35 +0,0 @@ -using FishNet.Documenting; - -namespace FishNet.Object -{ - /// - /// Properties which have changed on a transform. - /// - [System.Flags] - [APIExclude] - internal enum ChangedTransformProperties : byte - { - Unset = 0, - LocalPosition = 1, - LocalRotation = 2, - LocalScale = 4, - } - - [APIExclude] - internal static partial class ChangedTransformPropertiesEnum - { - /// - /// Returns if whole contains part. - /// - /// - /// - /// - public static bool Contains(ChangedTransformProperties whole, ChangedTransformProperties part) - { - return (whole & part) == part; - } - } - - -} - diff --git a/Assets/FishNet/Runtime/Object/ChangedTransformProperties.cs.meta b/Assets/FishNet/Runtime/Object/ChangedTransformProperties.cs.meta deleted file mode 100644 index 3357abe..0000000 --- a/Assets/FishNet/Runtime/Object/ChangedTransformProperties.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1870202c019b99348aaedbe2029caf33 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Delegates.cs b/Assets/FishNet/Runtime/Object/Delegates.cs deleted file mode 100644 index dab149f..0000000 --- a/Assets/FishNet/Runtime/Object/Delegates.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FishNet.Connection; -using FishNet.Serializing; -using FishNet.Transporting; -using FishNet.Utility.Constant; -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo(UtilityConstants.CODEGEN_ASSEMBLY_NAME)] -namespace FishNet.Object.Delegating -{ - public delegate void ServerRpcDelegate(PooledReader reader, Channel channel, NetworkConnection sender); - public delegate void ClientRpcDelegate(PooledReader reader, Channel channel); - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/Delegates.cs.meta b/Assets/FishNet/Runtime/Object/Delegates.cs.meta deleted file mode 100644 index 67c5bde..0000000 --- a/Assets/FishNet/Runtime/Object/Delegates.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5dbd9cdda4843f34ab416273d80f83c8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/DespawnType.cs b/Assets/FishNet/Runtime/Object/DespawnType.cs deleted file mode 100644 index 5fa5426..0000000 --- a/Assets/FishNet/Runtime/Object/DespawnType.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FishNet.Object.Helping; - -namespace FishNet.Object -{ - - public enum DespawnType : byte - { - Destroy = 0, - Pool = 1, - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/DespawnType.cs.meta b/Assets/FishNet/Runtime/Object/DespawnType.cs.meta deleted file mode 100644 index 0a7a9f4..0000000 --- a/Assets/FishNet/Runtime/Object/DespawnType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 205c3ddfc86fbaa44aa0b92ecef58474 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/EmptyNetworkBehaviour.cs b/Assets/FishNet/Runtime/Object/EmptyNetworkBehaviour.cs deleted file mode 100644 index 19aed6a..0000000 --- a/Assets/FishNet/Runtime/Object/EmptyNetworkBehaviour.cs +++ /dev/null @@ -1,13 +0,0 @@ - -namespace FishNet.Object -{ - /// - /// This may be added at runtime to find objects without any network scripts, beneath a NetworkObject. - /// - public class EmptyNetworkBehaviour : NetworkBehaviour - { - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/EmptyNetworkBehaviour.cs.meta b/Assets/FishNet/Runtime/Object/EmptyNetworkBehaviour.cs.meta deleted file mode 100644 index 4c947e7..0000000 --- a/Assets/FishNet/Runtime/Object/EmptyNetworkBehaviour.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8a6a39c46bf52104ba8efe3100bce3f7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Helping.meta b/Assets/FishNet/Runtime/Object/Helping.meta deleted file mode 100644 index b4e5fab..0000000 --- a/Assets/FishNet/Runtime/Object/Helping.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 0684bc52d23dfb743a5d2fab1278d8f7 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Helping/Hashing.cs b/Assets/FishNet/Runtime/Object/Helping/Hashing.cs deleted file mode 100644 index 1f06b4e..0000000 --- a/Assets/FishNet/Runtime/Object/Helping/Hashing.cs +++ /dev/null @@ -1,153 +0,0 @@ -namespace FishNet.Object.Helping -{ - - public static class Hashing - { - - private const uint FNV_offset_basis32 = 2166136261; - private const uint FNV_prime32 = 16777619; - private const ulong FNV_offset_basis64 = 14695981039346656037; - private const ulong FNV_prime64 = 1099511628211; - - - /// - /// non cryptographic stable hash code, - /// it will always return the same hash for the same - /// string. - /// - /// This is simply an implementation of FNV-1 32 bit xor folded to 16 bit - /// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function - /// - /// The stable hash32. - /// Text. - internal static ushort GetStableHash16(this string txt) - { - uint hash32 = txt.GetStableHash32(); - - return (ushort)((hash32 >> 16) ^ hash32); - } - - - /// - /// non cryptographic stable hash code, - /// it will always return the same hash for the same - /// string. - /// - /// This is simply an implementation of FNV-1 32 bit - /// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function - /// - /// The stable hash32. - /// Text. - public static uint GetStableHash32(this string txt) - { - unchecked - { - uint hash = FNV_offset_basis32; - for (int i = 0; i < txt.Length; i++) - { - uint ch = txt[i]; - hash = hash * FNV_prime32; - hash = hash ^ ch; - } - return hash; - } - } - - /// - /// non cryptographic stable hash code, - /// it will always return the same hash for the same - /// string. - /// - /// This is simply an implementation of FNV-1 64 bit - /// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function - /// - /// The stable hash32. - /// Text. - internal static ulong GetStableHash64(this string txt) - { - unchecked - { - ulong hash = FNV_offset_basis64; - for (int i = 0; i < txt.Length; i++) - { - ulong ch = txt[i]; - hash = hash * FNV_prime64; - hash = hash ^ ch; - } - return hash; - } - } - - ///// - ///// non cryptographic stable hash code, - ///// it will always return the same hash for the same - ///// string. - ///// - ///// This is simply an implementation of FNV-1 32 bit xor folded to 16 bit - ///// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function - ///// - ///// The stable hash32. - ///// Text. - //internal static ushort GetStableHash16(this byte[] bytes) - //{ - // uint hash32 = bytes.GetStableHash32(); - - // return (ushort)((hash32 >> 16) ^ hash32); - //} - - ///// - ///// non cryptographic stable hash code, - ///// it will always return the same hash for the same - ///// string. - ///// - ///// This is simply an implementation of FNV-1 32 bit - ///// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function - ///// - ///// The stable hash32. - ///// Text. - //internal static uint GetStableHash32(this byte[] bytes) - //{ - // unchecked - // { - // uint hash = FNV_offset_basis32; - // for (int i = 0; i < bytes.Length; i++) - // { - // uint bt = bytes[i]; - // hash = hash * FNV_prime32; - // hash = hash ^ bt; - // } - // return hash; - // } - //} - - ///// - ///// non cryptographic stable hash code, - ///// it will always return the same hash for the same - ///// string. - ///// - ///// This is simply an implementation of FNV-1 64 bit - ///// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function - ///// - ///// The stable hash32. - ///// Text. - //internal static ulong GetStableHash64(this byte[] bytes) - //{ - // unchecked - // { - // ulong hash = FNV_offset_basis64; - // for (int i = 0; i < bytes.Length; i++) - // { - // ulong bt = bytes[i]; - // hash = hash * FNV_prime64; - // hash = hash ^ bt; - // } - // return hash; - // } - //} - - - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/Helping/Hashing.cs.meta b/Assets/FishNet/Runtime/Object/Helping/Hashing.cs.meta deleted file mode 100644 index 327d971..0000000 --- a/Assets/FishNet/Runtime/Object/Helping/Hashing.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7c55dc5a22646764aa5dbfab2062669e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Helping/RpcLink.cs b/Assets/FishNet/Runtime/Object/Helping/RpcLink.cs deleted file mode 100644 index 53c2aea..0000000 --- a/Assets/FishNet/Runtime/Object/Helping/RpcLink.cs +++ /dev/null @@ -1,39 +0,0 @@ -using FishNet.Object.Helping; - -namespace FishNet.Object -{ - - #region Types. - /// - /// Lookup data for a RPC Link. - /// - internal struct RpcLink - { - /// - /// ObjectId for link. - /// - public int ObjectId; - /// - /// NetworkBehaviour component index on ObjectId. - /// - public byte ComponentIndex; - /// - /// RpcHash for link. - /// - public uint RpcHash; - /// - /// Type of Rpc link is for. - /// - public RpcType RpcType; - - public RpcLink(int objectId, byte componentIndex, uint rpcHash, RpcType rpcType) - { - ObjectId = objectId; - ComponentIndex = componentIndex; - RpcHash = rpcHash; - RpcType = rpcType; - } - } - #endregion - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/Helping/RpcLink.cs.meta b/Assets/FishNet/Runtime/Object/Helping/RpcLink.cs.meta deleted file mode 100644 index b76b723..0000000 --- a/Assets/FishNet/Runtime/Object/Helping/RpcLink.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 05a91745dd829d043aadf391ac7b233e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Helping/RpcType.cs b/Assets/FishNet/Runtime/Object/Helping/RpcType.cs deleted file mode 100644 index 5bf072a..0000000 --- a/Assets/FishNet/Runtime/Object/Helping/RpcType.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace FishNet.Object.Helping -{ - public enum RpcType : int - { - None = 0, - Server = 1, - Observers = 2, - Target = 4, - Replicate = 8, - Reconcile = 16 - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/Helping/RpcType.cs.meta b/Assets/FishNet/Runtime/Object/Helping/RpcType.cs.meta deleted file mode 100644 index 7cb63bd..0000000 --- a/Assets/FishNet/Runtime/Object/Helping/RpcType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 09f9e7236f988c64fad54645f4cc7f8b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Helping/StaticShortcuts.cs b/Assets/FishNet/Runtime/Object/Helping/StaticShortcuts.cs deleted file mode 100644 index 32e781f..0000000 --- a/Assets/FishNet/Runtime/Object/Helping/StaticShortcuts.cs +++ /dev/null @@ -1,49 +0,0 @@ - -namespace FishNet.Object.Helping -{ - - public static class CodegenHelper - { - /// - /// Returns if a NetworkObject is deinitializing. - /// - /// - /// - public static bool NetworkObject_Deinitializing(NetworkBehaviour nb) - { - if (nb == null) - return true; - - return nb.IsDeinitializing; - } - - /// - /// Returns if running as server. - /// - /// - /// - public static bool IsServer(NetworkBehaviour nb) - { - if (nb == null) - return false; - - return nb.IsServer; - } - - /// - /// Returns if running as client. - /// - /// - /// - public static bool IsClient(NetworkBehaviour nb) - { - if (nb == null) - return false; - - return nb.IsClient; - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/Helping/StaticShortcuts.cs.meta b/Assets/FishNet/Runtime/Object/Helping/StaticShortcuts.cs.meta deleted file mode 100644 index 70bef6e..0000000 --- a/Assets/FishNet/Runtime/Object/Helping/StaticShortcuts.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 149cde0042627604d810c2c7fc0f9176 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.Callbacks.cs b/Assets/FishNet/Runtime/Object/NetworkBehaviour.Callbacks.cs deleted file mode 100644 index bf1d1fc..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.Callbacks.cs +++ /dev/null @@ -1,184 +0,0 @@ -#if UNITY_2020_3_OR_NEWER && UNITY_EDITOR_WIN -using FishNet.CodeAnalysis.Annotations; -#endif -using FishNet.Connection; -using FishNet.Documenting; -using FishNet.Object.Synchronizing.Internal; -using UnityEngine; - -namespace FishNet.Object -{ - - public abstract partial class NetworkBehaviour : MonoBehaviour - { - #region Public. - /// - /// True if OnStartServer has been called. - /// - [APIExclude] - public bool OnStartServerCalled { get; private set; } - /// - /// True if OnStartClient has been called. - /// - [APIExclude] - public bool OnStartClientCalled { get; private set; } - #endregion - - #region Private. - /// - /// True if OnStartNetwork has been called. - /// - private bool _onStartNetworkCalled; - /// - /// True if OnStopNetwork has been called. - /// - private bool _onStopNetworkCalled; - #endregion - - /// - /// Invokes cached callbacks on SyncTypes which were held until OnStartXXXXX was called. - /// - /// - internal void InvokeSyncTypeCallbacks(bool asServer) - { - foreach (SyncBase item in _syncVars.Values) - item.OnStartCallback(asServer); - foreach (SyncBase item in _syncObjects.Values) - item.OnStartCallback(asServer); - } - /// - /// Invokes the OnStart/StopNetwork. - /// - /// - internal void InvokeOnNetwork(bool start) - { - if (start) - { - if (_onStartNetworkCalled) - return; - OnStartNetwork(); - } - else - { - if (_onStopNetworkCalled) - return; - OnStopNetwork(); - } - } - - /// - /// Called when the network has initialized this object. May be called for server or client but will only be called once. - /// When as host or server this method will run before OnStartServer. - /// When as client only the method will run before OnStartClient. - /// -#if UNITY_2020_3_OR_NEWER && UNITY_EDITOR_WIN - [OverrideMustCallBase(BaseCallMustBeFirstStatement = true)] -#endif - public virtual void OnStartNetwork() - { - _onStartNetworkCalled = true; - _onStopNetworkCalled = false; - } - /// - /// Called when the network is deinitializing this object. May be called for server or client but will only be called once. - /// When as host or server this method will run after OnStopServer. - /// When as client only this method will run after OnStopClient. - /// -#if UNITY_2020_3_OR_NEWER && UNITY_EDITOR_WIN - [OverrideMustCallBase(BaseCallMustBeFirstStatement = true)] -#endif - public virtual void OnStopNetwork() - { - _onStopNetworkCalled = true; - _onStartNetworkCalled = false; - } - - /// - /// Called on the server after initializing this object. - /// SyncTypes modified before or during this method will be sent to clients in the spawn message. - /// -#if UNITY_2020_3_OR_NEWER && UNITY_EDITOR_WIN - [OverrideMustCallBase(BaseCallMustBeFirstStatement = true)] -#endif - public virtual void OnStartServer() - { - OnStartServerCalled = true; - } - /// - /// Called on the server before deinitializing this object. - /// -#if UNITY_2020_3_OR_NEWER && UNITY_EDITOR_WIN - [OverrideMustCallBase(BaseCallMustBeFirstStatement = true)] -#endif - public virtual void OnStopServer() - { - OnStartServerCalled = false; - ReturnRpcLinks(); - } - /// - /// Called on the server after ownership has changed. - /// - /// Previous owner of this object. -#if UNITY_2020_3_OR_NEWER && UNITY_EDITOR_WIN - [OverrideMustCallBase(BaseCallMustBeFirstStatement = true)] -#endif - public virtual void OnOwnershipServer(NetworkConnection prevOwner) - { - //When switching ownership always clear replicate cache on server. - ClearReplicateCache_Internal(true); - } - /// - /// Called on the server after a spawn message for this object has been sent to clients. - /// Useful for sending remote calls or data to clients. - /// - /// Connection the object is being spawned for. -#if UNITY_2020_3_OR_NEWER && UNITY_EDITOR_WIN - [OverrideMustCallBase(BaseCallMustBeFirstStatement = true)] -#endif - public virtual void OnSpawnServer(NetworkConnection connection) { } - /// - /// Called on the server before a despawn message for this object has been sent to connection. - /// Useful for sending remote calls or actions to clients. - /// -#if UNITY_2020_3_OR_NEWER && UNITY_EDITOR_WIN - [OverrideMustCallBase(BaseCallMustBeFirstStatement = true)] -#endif - public virtual void OnDespawnServer(NetworkConnection connection) { } - /// - /// Called on the client after initializing this object. - /// -#if UNITY_2020_3_OR_NEWER && UNITY_EDITOR_WIN - [OverrideMustCallBase(BaseCallMustBeFirstStatement = true)] -#endif - public virtual void OnStartClient() - { - OnStartClientCalled = true; - } - /// - /// Called on the client before deinitializing this object. - /// -#if UNITY_2020_3_OR_NEWER && UNITY_EDITOR_WIN - [OverrideMustCallBase(BaseCallMustBeFirstStatement = true)] -#endif - public virtual void OnStopClient() - { - OnStartClientCalled = false; - } - /// - /// Called on the client after gaining or losing ownership. - /// - /// Previous owner of this object. -#if UNITY_2020_3_OR_NEWER && UNITY_EDITOR_WIN - [OverrideMustCallBase(BaseCallMustBeFirstStatement = true)] -#endif - public virtual void OnOwnershipClient(NetworkConnection prevOwner) - { - //If losing or gaining ownership then clear replicate cache. - if (IsOwner || prevOwner == LocalConnection) - ClearReplicateCache_Internal(false); - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.Callbacks.cs.meta b/Assets/FishNet/Runtime/Object/NetworkBehaviour.Callbacks.cs.meta deleted file mode 100644 index f5aabb3..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.Callbacks.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a9ddaf08801752b49bcfe720217df74a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.Logging.cs b/Assets/FishNet/Runtime/Object/NetworkBehaviour.Logging.cs deleted file mode 100644 index 496e8ac..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.Logging.cs +++ /dev/null @@ -1,22 +0,0 @@ -using FishNet.Managing.Logging; -using UnityEngine; - -namespace FishNet.Object -{ - - public abstract partial class NetworkBehaviour : MonoBehaviour - { - - /// - /// True if can log for loggingType. - /// - /// Type of logging being filtered. - /// - public bool CanLog(LoggingType loggingType) - { - return (NetworkManager == null) ? false : NetworkManager.CanLog(loggingType); - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.Logging.cs.meta b/Assets/FishNet/Runtime/Object/NetworkBehaviour.Logging.cs.meta deleted file mode 100644 index e446436..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.Logging.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ad4dd2795a9a00e4d814892ac1a67157 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.Prediction.cs b/Assets/FishNet/Runtime/Object/NetworkBehaviour.Prediction.cs deleted file mode 100644 index cccee30..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.Prediction.cs +++ /dev/null @@ -1,746 +0,0 @@ -using FishNet.Connection; -using FishNet.Documenting; -using FishNet.Managing.Predicting; -using FishNet.Managing.Timing; -using FishNet.Object.Prediction; -using FishNet.Object.Prediction.Delegating; -using FishNet.Serializing; -using FishNet.Serializing.Helping; -using FishNet.Transporting; -using FishNet.Utility.Constant; -using FishNet.Utility.Extension; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; -using UnityScene = UnityEngine.SceneManagement.Scene; - -[assembly: InternalsVisibleTo(UtilityConstants.CODEGEN_ASSEMBLY_NAME)] -namespace FishNet.Object -{ - - public abstract partial class NetworkBehaviour : MonoBehaviour - { - #region Public. - /// - /// - /// - private uint _lastReconcileTick; - /// - /// Gets the last tick this NetworkBehaviour reconciled with. - /// - public uint GetLastReconcileTick() => _lastReconcileTick; - - internal void SetLastReconcileTick(uint value, bool updateGlobals = true) - { - _lastReconcileTick = value; - if (updateGlobals) - PredictionManager.LastReconcileTick = value; - } - /// - /// - /// - private uint _lastReplicateTick; - /// - /// Gets the last tick this NetworkBehaviour replicated with. - /// - public uint GetLastReplicateTick() => _lastReplicateTick; - /// - /// Sets the last tick this NetworkBehaviour replicated with. - /// For internal use only. - /// - private void SetLastReplicateTick(uint value, bool updateGlobals = true) - { - _lastReplicateTick = value; - if (updateGlobals) - { - Owner.LocalReplicateTick = TimeManager.LocalTick; - PredictionManager.LastReplicateTick = value; - } - } - /// - /// True if this object is reconciling. - /// - public bool IsReconciling { get; internal set; } - #endregion - - #region Private. - /// - /// Registered Replicate methods. - /// - private readonly Dictionary _replicateRpcDelegates = new Dictionary(); - /// - /// Registered Reconcile methods. - /// - private readonly Dictionary _reconcileRpcDelegates = new Dictionary(); - /// - /// True if initialized compnents for prediction. - /// - private bool _predictionInitialized; - /// - /// Rigidbody found on this object. This is used for prediction. - /// - private Rigidbody _predictionRigidbody; - /// - /// Rigidbody2D found on this object. This is used for prediction. - /// - private Rigidbody2D _predictionRigidbody2d; - /// - /// Last position for TransformMayChange. - /// - private Vector3 _lastMayChangePosition; - /// - /// Last rotation for TransformMayChange. - /// - private Quaternion _lastMayChangeRotation; - /// - /// Last scale for TransformMayChange. - /// - private Vector3 _lastMayChangeScale; - /// - /// Number of resends which may occur. This could be for client resending replicates to the server or the server resending reconciles to the client. - /// - private int _remainingResends; - /// - /// Last enqueued replicate tick on the server. - /// - private uint _lastReceivedReplicateTick; - /// - /// Last tick of a reconcile received from the server. - /// - private uint _lastReceivedReconcileTick; - /// - /// True if the client has cached reconcile - /// - private bool _clientHasReconcileData; - #endregion - - /// - /// Registers a RPC method. - /// Internal use. - /// - /// - /// - [APIExclude] - [CodegenMakePublic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected internal void RegisterReplicateRpc_Internal(uint hash, ReplicateRpcDelegate del) - { - _replicateRpcDelegates[hash] = del; - } - /// - /// Registers a RPC method. - /// Internal use. - /// - /// - /// - [APIExclude] - [CodegenMakePublic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected internal void RegisterReconcileRpc_Internal(uint hash, ReconcileRpcDelegate del) - { - _reconcileRpcDelegates[hash] = del; - } - - - /// - /// Called when a replicate is received. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void OnReplicateRpc(uint? methodHash, PooledReader reader, NetworkConnection sendingClient, Channel channel) - { - if (methodHash == null) - methodHash = ReadRpcHash(reader); - - if (sendingClient == null) - { - _networkObjectCache.NetworkManager.LogError($"NetworkConnection is null. Replicate {methodHash.Value} on {gameObject.name}, behaviour {GetType().Name} will not complete. Remainder of packet may become corrupt."); - return; - } - - if (_replicateRpcDelegates.TryGetValueIL2CPP(methodHash.Value, out ReplicateRpcDelegate del)) - del.Invoke(reader, sendingClient, channel); - else - _networkObjectCache.NetworkManager.LogWarning($"Replicate not found for hash {methodHash.Value} on {gameObject.name}, behaviour {GetType().Name}. Remainder of packet may become corrupt."); - } - - - /// - /// Called when a reconcile is received. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void OnReconcileRpc(uint? methodHash, PooledReader reader, Channel channel) - { - if (methodHash == null) - methodHash = ReadRpcHash(reader); - - if (_reconcileRpcDelegates.TryGetValueIL2CPP(methodHash.Value, out ReconcileRpcDelegate del)) - del.Invoke(reader, channel); - else - _networkObjectCache.NetworkManager.LogWarning($"Reconcile not found for hash {methodHash.Value}. Remainder of packet may become corrupt."); - } - - /// - /// Clears cached replicates. This can be useful to call on server and client after teleporting. - /// - /// True to reset values for server, false to reset values for client. - public void ClearReplicateCache(bool asServer) - { - ResetLastPredictionTicks(); - ClearReplicateCache_Internal(asServer); - } - /// - /// Clears cached replicates for server and client. This can be useful to call on server and client after teleporting. - /// - public void ClearReplicateCache() - { - ResetLastPredictionTicks(); - ClearReplicateCache_Internal(true); - ClearReplicateCache_Internal(false); - } - /// - /// Resets last predirection tick values. - /// - private void ResetLastPredictionTicks() - { - _lastSentReplicateTick = 0; - _lastReceivedReplicateTick = 0; - _lastReceivedReconcileTick = 0; - SetLastReconcileTick(0, false); - SetLastReplicateTick(0, false); - } - /// - /// Clears cached replicates. - /// For internal use only. - /// - /// - [CodegenMakePublic] - [APIExclude] - protected internal virtual void ClearReplicateCache_Internal(bool asServer) { } - - /// - /// Writes number of past inputs from buffer to writer and sends it to the server. - /// Internal use. - /// - [CodegenMakePublic] - [APIExclude] - private void SendReplicateRpc(uint hash, List replicates, Channel channel) where T : IReplicateData - { - if (!IsSpawnedWithWarning()) - return; - - int bufferCount = replicates.Count; - int lastBufferIndex = (bufferCount - 1); - //Nothing to send; should never be possible. - if (lastBufferIndex < 0) - return; - - //Number of past inputs to send. - int pastInputs = Mathf.Min(PredictionManager.GetRedundancyCount(), bufferCount); - /* Where to start writing from. When passed - * into the writer values from this offset - * and forward will be written. */ - int offset = bufferCount - pastInputs; - if (offset < 0) - offset = 0; - - uint lastReplicateTick = _lastSentReplicateTick; - if (lastReplicateTick > 0) - { - uint diff = TimeManager.LocalTick - GetLastReplicateTick(); - offset += (int)diff - 1; - if (offset >= replicates.Count) - return; - } - - _lastSentReplicateTick = TimeManager.LocalTick; - - //Write history to methodWriter. - PooledWriter methodWriter = WriterPool.GetWriter(WriterPool.LENGTH_BRACKET); - methodWriter.WriteReplicate(replicates, offset); - PooledWriter writer; - //if (_rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link)) - //writer = CreateLinkedRpc(link, methodWriter, Channel.Unreliable); - //else //todo add support for -> server rpc links. - - writer = CreateRpc(hash, methodWriter, PacketId.Replicate, channel); - NetworkManager.TransportManager.SendToServer((byte)channel, writer.GetArraySegment(), false); - - /* If being sent as reliable then clear buffer - * since we know it will get there. - * Also reset remaining resends. */ - if (channel == Channel.Reliable) - { - replicates.Clear(); - _remainingResends = 0; - } - - methodWriter.DisposeLength(); - writer.DisposeLength(); - } - - private uint _lastSentReplicateTick; - - /// - /// Sends a RPC to target. - /// Internal use. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [CodegenMakePublic] - [APIExclude] - internal void SendReconcileRpc(uint hash, T reconcileData, Channel channel) - { - if (!IsSpawned) - return; - if (!Owner.IsActive) - return; - - PooledWriter methodWriter = WriterPool.GetWriter(); - methodWriter.WriteUInt32(GetLastReplicateTick()); - methodWriter.Write(reconcileData); - - PooledWriter writer; -#if UNITY_EDITOR || DEVELOPMENT_BUILD - if (NetworkManager.DebugManager.ReconcileRpcLinks && _rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link)) -#else - if (_rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link)) -#endif - writer = CreateLinkedRpc(link, methodWriter, channel); - else - writer = CreateRpc(hash, methodWriter, PacketId.Reconcile, channel); - - _networkObjectCache.NetworkManager.TransportManager.SendToClient((byte)channel, writer.GetArraySegment(), Owner); - - methodWriter.Dispose(); - writer.Dispose(); - } - - /// - /// Returns if there is a chance the transform may change after the tick. - /// - /// - protected internal bool TransformMayChange() - { - if (!_predictionInitialized) - { - _predictionInitialized = true; - _predictionRigidbody = GetComponentInParent(); - _predictionRigidbody2d = GetComponentInParent(); - } - - /* Use distance when checking if changed because rigidbodies can twitch - * or move an extremely small amount. These small moves are not worth - * resending over because they often fix themselves each frame. */ - float changeDistance = 0.000004f; - - bool positionChanged = (transform.position - _lastMayChangePosition).sqrMagnitude > changeDistance; - bool rotationChanged = (transform.rotation.eulerAngles - _lastMayChangeRotation.eulerAngles).sqrMagnitude > changeDistance; - bool scaleChanged = (transform.localScale - _lastMayChangeScale).sqrMagnitude > changeDistance; - bool transformChanged = (positionChanged || rotationChanged || scaleChanged); - /* Returns true if transform.hasChanged, or if either - * of the rigidbodies have velocity. */ - bool changed = ( - transformChanged || - (_predictionRigidbody != null && (_predictionRigidbody.velocity != Vector3.zero || _predictionRigidbody.angularVelocity != Vector3.zero)) || - (_predictionRigidbody2d != null && (_predictionRigidbody2d.velocity != Vector2.zero || _predictionRigidbody2d.angularVelocity != 0f)) - ); - - //If transform changed update last values. - if (transformChanged) - { - _lastMayChangePosition = transform.position; - _lastMayChangeRotation = transform.rotation; - _lastMayChangeScale = transform.localScale; - } - - return changed; - } - - /// - /// Checks conditions for a replicate. - /// - /// True if checking as server. - /// Returns true if to exit the replicate early. - [CodegenMakePublic] //internal - [APIExclude] - public bool Replicate_ExitEarly_A_Internal(bool asServer, bool replaying) - { - bool isOwner = IsOwner; - //Server. - if (asServer) - { - //No owner, do not try to replicate 'owner' input. - if (!Owner.IsActive) - { - ClearReplicateCache(true); - return true; - } - //Is client host, no need to use CSP; trust client. - if (isOwner) - { - ClearReplicateCache(); - return true; - } - } - //Client. - else - { - //Server does not replay; this should never happen. - if (replaying && IsServer) - return true; - //Spectators cannot replicate. - if (!isOwner) - { - ClearReplicateCache(false); - return true; - } - } - - //Checks pass. - return false; - } - - /// - /// Clears a Queue. - /// This is used as a patch for Unity 2022 Burst compiler bugs. - /// Using Queue.Clear via codegen throws for an unknown reason. - /// - public void ClearQueue_Server_Internal(Queue q) - { - q.Clear(); - } - - /// - /// Gets the next replicate in queue. - /// - [CodegenMakePublic] //internal - [APIExclude] - public void Replicate_Server_Internal(ReplicateUserLogicDelegate del, Queue q, Channel channel) where T : IReplicateData - { - int count = q.Count; - if (count > 0) - { - ReplicateData(q.Dequeue()); - count--; - - PredictionManager pm = PredictionManager; - bool consumeExcess = !pm.DropExcessiveReplicates; - //Number of entries to leave in buffer when consuming. - const int leaveInBuffer = 2; - //Only consume if the queue count is over leaveInBuffer. - if (consumeExcess && count > leaveInBuffer) - { - byte maximumAllowedConsumes = pm.GetMaximumConsumeCount(); - int maximumPossibleConsumes = (count - leaveInBuffer); - int consumeAmount = Mathf.Min(maximumAllowedConsumes, maximumPossibleConsumes); - - for (int i = 0; i < consumeAmount; i++) - ReplicateData(q.Dequeue()); - } - - void ReplicateData(T data) - { - uint tick = data.GetTick(); - SetLastReplicateTick(tick); - del.Invoke(data, true, channel, false); - } - - _remainingResends = pm.GetRedundancyCount(); - } - else - { - del.Invoke(default, true, channel, false); - } - } - - /// - /// Returns the maximum amount of replicates when consuming multiple inputs per tick. - /// - /// - private int GetMaximumReplicatesWhenConsuming() => (TimeManager.TickRate * 3); - - /// - /// Returns if a replicates data changed and updates resends as well data tick. - /// - /// True to enqueue data for replaying. - /// True if data has changed.. - [CodegenMakePublic] //internal - [APIExclude] - public void Replicate_Client_Internal(ReplicateUserLogicDelegate del, uint methodHash, List replicates, T data, Channel channel) where T : IReplicateData - { - //Only check to enqueu/send if not clientHost. - if (!IsServer) - { - Func isDefaultDel = GeneratedComparer.IsDefault; - if (isDefaultDel == null) - { - NetworkManager.LogError($"ReplicateComparers not found for type {typeof(T).FullName}"); - return; - } - - //If there's no datas then reset last replicate send tick. - if (replicates.Count == 0) - _lastSentReplicateTick = 0; - - PredictionManager pm = NetworkManager.PredictionManager; - - bool isDefault = isDefaultDel.Invoke(data); - bool mayChange = TransformMayChange(); - bool resetResends = (pm.UsingRigidbodies || mayChange || !isDefault); - /* If there is going to be a resend then enqueue data no matter what. - * Then ensures there are no data gaps for ticks. EG, input may - * look like this... - * Move - tick 0. - * Idle - tick 1. - * Move - tick 2. - * - * If there were no 'using rigidbodies' then resetResends may be false. - * As result the queue would be filled like this... - * Move - tick 0. - * Move - tick 2. - * - * The ticks are not sent per data, just once and incremented once per data. - * Due to this the results would actually be... - * Move - tick 0. - * Move - tick 1 (should be tick 2!). - * - * But by including data if there will be resends the defaults will become added. */ - if (resetResends) - _remainingResends = pm.GetRedundancyCount(); - - bool enqueueData = (_remainingResends > 0); - if (enqueueData) - { - /* Replicates will be limited to 1 second - * worth on the client. That means the client - * will only lose replays if they do not receive - * a response back from the server for over a second. - * When a client drops a replay it does not necessarily mean - * they will be out of synchronization, but rather they - * will not be able to reconcile that tick. */ - /* Even though limit is 1 second only remove entries if over 2 seconds - * to prevent constant remove calls to the collection. */ - int maximumReplicates = (TimeManager.TickRate * 2); - //If over then remove half the replicates. - if (replicates.Count >= maximumReplicates) - { - int removeCount = (maximumReplicates / 2); - //Dispose first. - for (int i = 0; i < removeCount; i++) - replicates[i].Dispose(); - //Then remove. - replicates.RemoveRange(0, removeCount); - } - - uint localTick = TimeManager.LocalTick; - //Update tick on the data to current. - data.SetTick(localTick); - //Add to collection. - replicates.Add(data); - } - - //If theres resends left. - if (_remainingResends > 0) - { - _remainingResends--; - SendReplicateRpc(methodHash, replicates, channel); - //Update last replicate tick. - SetLastReplicateTick(TimeManager.LocalTick); - } - } - - del.Invoke(data, false, channel, false); - } - - - /// - /// Reads a replicate the client. - /// - public void Replicate_Reader_Internal(PooledReader reader, NetworkConnection sender, T[] arrBuffer, Queue replicates, Channel channel) where T : IReplicateData - { - int receivedReplicatesCount = reader.ReadReplicate(ref arrBuffer, TimeManager.LastPacketTick); - if (!OwnerMatches(sender)) - return; - - PredictionManager pm = PredictionManager; - bool consumeExcess = !pm.DropExcessiveReplicates; - //Maximum number of replicates allowed to be queued at once. - int replicatesCountLimit = (consumeExcess) ? - GetMaximumReplicatesWhenConsuming() : pm.GetMaximumServerReplicates(); - - for (int i = 0; i < receivedReplicatesCount; i++) - { - uint tick = arrBuffer[i].GetTick(); - if (tick > _lastReceivedReplicateTick) - { - //Cannot queue anymore, discard oldest. - if (replicates.Count >= replicatesCountLimit) - { - T data = replicates.Dequeue(); - data.Dispose(); - } - - replicates.Enqueue(arrBuffer[i]); - _lastReceivedReplicateTick = tick; - } - } - } - - /// - /// Checks conditions for a reconcile. - /// - /// True if checking as server. - /// Returns true if able to continue. - [CodegenMakePublic] //internal - [APIExclude] - public bool Reconcile_ExitEarly_A_Internal(bool asServer, out Channel channel) - { - channel = Channel.Unreliable; - //Server. - if (asServer) - { - if (_remainingResends <= 0) - return true; - - _remainingResends--; - if (_remainingResends == 0) - channel = Channel.Reliable; - } - //Client. - else - { - if (!_clientHasReconcileData) - return true; - - _clientHasReconcileData = false; - /* If clientHost then invoke reconciles but - * don't actually reconcile. This is done - * because certain user code may - * rely on those events running even as host. */ - if (IsServer) - { - PredictionManager.InvokeOnReconcile_Internal(this, true); - PredictionManager.InvokeOnReconcile_Internal(this, false); - return true; - } - } - - //Checks pass. - return false; - } - - /// - /// Updates lastReconcileTick as though running asServer. - /// - /// Data to set tick on. - public void Reconcile_Server_Internal(uint methodHash, T data, Channel channel) where T : IReconcileData - { - //Server always uses last replicate tick as reconcile tick. - uint tick = _lastReplicateTick; - data.SetTick(tick); - SetLastReconcileTick(tick); - - PredictionManager.InvokeServerReconcile(this, true); - SendReconcileRpc(methodHash, data, channel); - PredictionManager.InvokeServerReconcile(this, false); - - } - - /// - /// Processes a reconcile for client. - /// - public void Reconcile_Client_Internal(ReconcileUserLogicDelegate reconcileDel, ReplicateUserLogicDelegate replicateULDel, List replicates, T data, Channel channel) where T : IReconcileData where T2 : IReplicateData - { - uint tick = data.GetTick(); - - /* If the first entry in cllection has a tick higher than - * the received tick then something went wrong, do not reconcile. */ - if (replicates.Count > 0 && replicates[0].GetTick() > tick) - return; - - UnityScene scene = gameObject.scene; - PhysicsScene ps = scene.GetPhysicsScene(); - PhysicsScene2D ps2d = scene.GetPhysicsScene2D(); - - //This must be set before reconcile is invoked. - SetLastReconcileTick(tick); - //Invoke that reconcile is starting. - PredictionManager.InvokeOnReconcile_Internal(this, true); - //Call reconcile user logic. - reconcileDel?.Invoke(data, false, channel); - - //True if the timemanager is handling physics simulations. - bool tmPhysics = (TimeManager.PhysicsMode == PhysicsMode.TimeManager); - //Sync transforms if using tm physics. - if (tmPhysics) - { - Physics.SyncTransforms(); - Physics2D.SyncTransforms(); - } - - //Remove excess from buffered inputs. - int queueIndex = -1; - for (int i = 0; i < replicates.Count; i++) - { - if (replicates[i].GetTick() == tick) - { - queueIndex = i; - break; - } - } - //Now found, weird. - if (queueIndex == -1) - replicates.Clear(); - //Remove up to found, including it. - else - replicates.RemoveRange(0, queueIndex + 1); - - //Number of replays which will be performed. - int replays = replicates.Count; - float tickDelta = (float)TimeManager.TickDelta; - - for (int i = 0; i < replays; i++) - { - T2 rData = replicates[i]; - uint replayTick = rData.GetTick(); - - PredictionManager.InvokeOnReplicateReplay_Internal(scene, replayTick, ps, ps2d, true); - - //Replay the data using the replicate logic delegate. - replicateULDel.Invoke(rData, false, channel, true); - if (tmPhysics) - { - ps.Simulate(tickDelta); - ps2d.Simulate(tickDelta); - } - - PredictionManager.InvokeOnReplicateReplay_Internal(scene, replayTick, ps, ps2d, false); - } - - //Reconcile ended. - PredictionManager.InvokeOnReconcile_Internal(this, false); - } - - /// - /// Reads a reconcile the client. - /// - public void Reconcile_Reader_Internal(PooledReader reader, ref T data, Channel channel) where T : IReconcileData - { - uint tick = reader.ReadUInt32(); - T newData = reader.Read(); - - //Tick is old or already processed. - if (tick <= _lastReceivedReconcileTick) - return; - //Only owner reconciles. Maybe ownership changed then packet arrived out of order. - if (!IsOwner) - return; - - data = newData; - data.SetTick(tick); - _clientHasReconcileData = true; - _lastReceivedReconcileTick = tick; - } - - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.Prediction.cs.meta b/Assets/FishNet/Runtime/Object/NetworkBehaviour.Prediction.cs.meta deleted file mode 100644 index 1d59a32..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.Prediction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 074dac4dd3f9f6a4d8c1eb1191334472 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.QOL.cs b/Assets/FishNet/Runtime/Object/NetworkBehaviour.QOL.cs deleted file mode 100644 index e4da3a7..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.QOL.cs +++ /dev/null @@ -1,258 +0,0 @@ -#if UNITY_2020_3_OR_NEWER && UNITY_EDITOR_WIN -using FishNet.CodeAnalysis.Annotations; -#endif -using FishNet.Component.ColliderRollback; -using FishNet.Connection; -using FishNet.Managing; -using FishNet.Managing.Client; -using FishNet.Managing.Observing; -using FishNet.Managing.Predicting; -using FishNet.Managing.Scened; -using FishNet.Managing.Server; -using FishNet.Managing.Timing; -using FishNet.Managing.Transporting; -using FishNet.Observing; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.Object -{ - - public abstract partial class NetworkBehaviour : MonoBehaviour - { - /// - /// True if the NetworkObject for this NetworkBehaviour is deinitializing. - /// - public bool IsDeinitializing => _networkObjectCache.IsDeinitializing; - /// - /// NetworkManager for this object. - /// - public NetworkManager NetworkManager => _networkObjectCache.NetworkManager; - /// - /// ServerManager for this object. - /// - public ServerManager ServerManager => _networkObjectCache.ServerManager; - /// - /// ClientManager for this object. - /// - public ClientManager ClientManager => _networkObjectCache.ClientManager; - /// - /// ObserverManager for this object. - /// - public ObserverManager ObserverManager => _networkObjectCache.ObserverManager; - /// - /// TransportManager for this object. - /// - public TransportManager TransportManager => _networkObjectCache.TransportManager; - /// - /// TimeManager for this object. - /// - public TimeManager TimeManager => _networkObjectCache.TimeManager; - /// - /// SceneManager for this object. - /// - public SceneManager SceneManager => _networkObjectCache.SceneManager; - /// - /// PredictionManager for this object. - /// - public PredictionManager PredictionManager => _networkObjectCache.PredictionManager; - /// - /// RollbackManager for this object. - /// - public RollbackManager RollbackManager => _networkObjectCache.RollbackManager; - /// - /// NetworkObserver on this object. - /// - public NetworkObserver NetworkObserver => _networkObjectCache.NetworkObserver; - /// - /// True if the client is active and authenticated. - /// - public bool IsClient => _networkObjectCache.IsClient; - /// - /// True if only the client is active and authenticated. - /// - public bool IsClientOnly => _networkObjectCache.IsClientOnly; - /// - /// True if server is active. - /// - public bool IsServer => _networkObjectCache.IsServer; - /// - /// True if only the server is active. - /// - public bool IsServerOnly => _networkObjectCache.IsServerOnly; - /// - /// True if client and server are active. - /// - public bool IsHost => _networkObjectCache.IsHost; - /// - /// True if client nor server are active. - /// - public bool IsOffline => _networkObjectCache.IsOffline; - /// - /// Observers for this NetworkBehaviour. - /// - public HashSet Observers => _networkObjectCache.Observers; - /// - /// True if the local client is the owner of this object. - /// -#if UNITY_2020_3_OR_NEWER && UNITY_EDITOR_WIN - [PreventUsageInside("global::FishNet.Object.NetworkBehaviour", "OnStartServer", "")] - [PreventUsageInside("global::FishNet.Object.NetworkBehaviour", "OnStartNetwork", " Use base.Owner.IsLocalClient instead.")] - [PreventUsageInside("global::FishNet.Object.NetworkBehaviour", "Awake", "")] - [PreventUsageInside("global::FishNet.Object.NetworkBehaviour", "Start", "")] -#endif - public bool IsOwner => _networkObjectCache.IsOwner; - /// - /// Owner of this object. - /// - public NetworkConnection Owner - { - get - { - //Ensures a null Owner is never returned. - if (_networkObjectCache == null) - return FishNet.Managing.NetworkManager.EmptyConnection; - - return _networkObjectCache.Owner; - } - } - /// - /// ClientId for this NetworkObject owner. - /// - public int OwnerId => _networkObjectCache.OwnerId; - /// - /// Unique Id for this _networkObjectCache. This does not represent the object owner. - /// - public int ObjectId => _networkObjectCache.ObjectId; - /// - /// The local connection of the client calling this method. - /// - public NetworkConnection LocalConnection => _networkObjectCache.LocalConnection; - /// - /// Returns if a connection is the owner of this object. - /// - /// - /// - public bool OwnerMatches(NetworkConnection connection) - { - return (_networkObjectCache.Owner == connection); - } - - /// - /// Despawns a GameObject. Only call from the server. - /// - /// GameObject to despawn. - /// What happens to the object after being despawned. - public void Despawn(GameObject go, DespawnType? despawnType = null) - { - if (!IsNetworkObjectNull(true)) - _networkObjectCache.Despawn(go, despawnType); - } - /// - /// Despawns a NetworkObject. Only call from the server. - /// - /// NetworkObject to despawn. - /// What happens to the object after being despawned. - public void Despawn(NetworkObject nob, DespawnType? despawnType = null) - { - if (!IsNetworkObjectNull(true)) - _networkObjectCache.Despawn(nob, despawnType); - } - - /// - /// Despawns this _networkObjectCache. Can only be called on the server. - /// - /// What happens to the object after being despawned. - public void Despawn(DespawnType? despawnType = null) - { - if (!IsNetworkObjectNull(true)) - _networkObjectCache.Despawn(despawnType); - } - /// - /// Spawns an object over the network. Can only be called on the server. - /// - /// GameObject instance to spawn. - /// Connection to give ownership to. - public void Spawn(GameObject go, NetworkConnection ownerConnection = null) - { - if (IsNetworkObjectNull(true)) - return; - _networkObjectCache.Spawn(go, ownerConnection); - } - /// - /// Spawns an object over the network. Can only be called on the server. - /// - /// GameObject instance to spawn. - /// Connection to give ownership to. - public void Spawn(NetworkObject nob, NetworkConnection ownerConnection = null) - { - if (IsNetworkObjectNull(true)) - return; - _networkObjectCache.Spawn(nob, ownerConnection); - } - /// - /// Returns if NetworkObject is null. - /// - /// True to throw a warning if null. - /// - private bool IsNetworkObjectNull(bool warn) - { - bool isNull = (_networkObjectCache == null); - if (isNull && warn) - NetworkManager.LogWarning($"NetworkObject is null. This can occur if this object is not spawned, or initialized yet."); - - return isNull; - } - /// - /// Removes ownership from all clients. - /// - public void RemoveOwnership() - { - _networkObjectCache.GiveOwnership(null, true); - } - /// - /// Gives ownership to newOwner. - /// - /// - public void GiveOwnership(NetworkConnection newOwner) - { - _networkObjectCache.GiveOwnership(newOwner, true); - } - - #region Registered components - /// - /// Invokes an action when a specified component becomes registered. Action will invoke immediately if already registered. - /// - /// Component type. - /// Action to invoke. - public void RegisterInvokeOnInstance(Action handler) where T : UnityEngine.Component => _networkObjectCache.RegisterInvokeOnInstance(handler); - /// - /// Removes an action to be invoked when a specified component becomes registered. - /// - /// Component type. - /// Action to invoke. - public void UnregisterInvokeOnInstance(Action handler) where T : UnityEngine.Component => _networkObjectCache.UnregisterInvokeOnInstance(handler); - /// - /// Returns class of type if found within CodegenBase classes. - /// - /// - /// - public T GetInstance() where T : UnityEngine.Component => _networkObjectCache.GetInstance(); - /// - /// Registers a new component to this NetworkManager. - /// - /// Type to register. - /// Reference of the component being registered. - /// True to replace existing references. - public void RegisterInstance(T component, bool replace = true) where T : UnityEngine.Component => _networkObjectCache.RegisterInstance(component, replace); - /// - /// Unregisters a component from this NetworkManager. - /// - /// Type to unregister. - public void UnregisterInstance() where T : UnityEngine.Component => _networkObjectCache.UnregisterInstance(); - #endregion - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.QOL.cs.meta b/Assets/FishNet/Runtime/Object/NetworkBehaviour.QOL.cs.meta deleted file mode 100644 index 79aaf06..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.QOL.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d7aef532208d06c4880973c51b1906f5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCLinks.cs b/Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCLinks.cs deleted file mode 100644 index 11990b3..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCLinks.cs +++ /dev/null @@ -1,140 +0,0 @@ -using FishNet.Managing.Server; -using FishNet.Object.Helping; -using FishNet.Serializing; -using FishNet.Transporting; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Object -{ - - public abstract partial class NetworkBehaviour : MonoBehaviour - { - #region Private. - /// - /// Link indexes for RPCs. - /// - private Dictionary _rpcLinks = new Dictionary(); - #endregion - - /// - /// Initializes RpcLinks. This will only call once even as host. - /// - private void InitializeOnceRpcLinks() - { - if (NetworkManager.IsServer) - { - /* Link only data from server to clients. While it is - * just as easy to link client to server it's usually - * not needed because server out data is more valuable - * than server in data. */ - /* Links will be stored in the NetworkBehaviour so that - * when the object is destroyed they can be added back - * into availableRpcLinks, within the ServerManager. */ - - ServerManager serverManager = NetworkManager.ServerManager; - //ObserverRpcs. - foreach (uint rpcHash in _observersRpcDelegates.Keys) - { - if (!MakeLink(rpcHash, RpcType.Observers)) - return; - } - //TargetRpcs. - foreach (uint rpcHash in _targetRpcDelegates.Keys) - { - if (!MakeLink(rpcHash, RpcType.Target)) - return; - } - //ReconcileRpcs. - foreach (uint rpcHash in _reconcileRpcDelegates.Keys) - { - if (!MakeLink(rpcHash, RpcType.Reconcile)) - return; - } - - /* Tries to make a link and returns if - * successful. When a link cannot be made the method - * should exit as no other links will be possible. */ - bool MakeLink(uint rpcHash, RpcType rpcType) - { - if (serverManager.GetRpcLink(out ushort linkIndex)) - { - _rpcLinks[rpcHash] = new RpcLinkType(linkIndex, rpcType); - return true; - } - else - { - return false; - } - } - } - } - - /// - /// Returns an estimated length for any Rpc header. - /// - /// - private int GetEstimatedRpcHeaderLength() - { - /* Imaginary number for how long RPC headers are. - * They are well under this value but this exist to - * ensure a writer of appropriate length is pulled - * from the pool. */ - return 20; - } - - /// - /// Creates a PooledWriter and writes the header for a rpc. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private PooledWriter CreateLinkedRpc(RpcLinkType link, PooledWriter methodWriter, Channel channel) - { - int rpcHeaderBufferLength = GetEstimatedRpcHeaderLength(); - int methodWriterLength = methodWriter.Length; - //Writer containing full packet. - PooledWriter writer = WriterPool.GetWriter(rpcHeaderBufferLength + methodWriterLength); - writer.WriteUInt16(link.LinkIndex); - //Write length only if reliable. - if (channel == Channel.Reliable) - writer.WriteLength(methodWriter.Length); - //Data. - writer.WriteArraySegment(methodWriter.GetArraySegment()); - - return writer; - } - - /// - /// Returns RpcLinks the ServerManager. - /// - private void ReturnRpcLinks() - { - if (_rpcLinks.Count == 0) - return; - - ServerManager?.StoreRpcLinks(_rpcLinks); - _rpcLinks.Clear(); - } - - /// - /// Writes rpcLinks to writer. - /// - internal void WriteRpcLinks(Writer writer) - { - PooledWriter rpcLinkWriter = WriterPool.GetWriter(); - foreach (KeyValuePair item in _rpcLinks) - { - //RpcLink index. - rpcLinkWriter.WriteUInt16(item.Value.LinkIndex); - //Hash. - rpcLinkWriter.WriteUInt16((ushort)item.Key); - //True/false if observersRpc. - rpcLinkWriter.WriteByte((byte)item.Value.RpcType); - } - - writer.WriteBytesAndSize(rpcLinkWriter.GetBuffer(), 0, rpcLinkWriter.Length); - rpcLinkWriter.Dispose(); - } - } -} - diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCLinks.cs.meta b/Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCLinks.cs.meta deleted file mode 100644 index 3f93ed0..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCLinks.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7136e9ee3f7eee44abab09285ab7b939 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCs.cs b/Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCs.cs deleted file mode 100644 index 1e770f9..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCs.cs +++ /dev/null @@ -1,364 +0,0 @@ -using FishNet.Connection; -using FishNet.Documenting; -using FishNet.Managing.Logging; -using FishNet.Managing.Transporting; -using FishNet.Object.Delegating; -using FishNet.Serializing; -using FishNet.Serializing.Helping; -using FishNet.Transporting; -using FishNet.Utility.Extension; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Object -{ - - - public abstract partial class NetworkBehaviour : MonoBehaviour - { - #region Private. - /// - /// Registered ServerRpc methods. - /// - private readonly Dictionary _serverRpcDelegates = new Dictionary(); - /// - /// Registered ObserversRpc methods. - /// - private readonly Dictionary _observersRpcDelegates = new Dictionary(); - /// - /// Registered TargetRpc methods. - /// - private readonly Dictionary _targetRpcDelegates = new Dictionary(); - /// - /// Number of total RPC methods for scripts in the same inheritance tree for this instance. - /// - private uint _rpcMethodCount; - /// - /// Size of every rpcHash for this networkBehaviour. - /// - private byte _rpcHashSize = 1; - /// - /// RPCs buffered for new clients. - /// - private Dictionary _bufferedRpcs = new Dictionary(); - /// - /// Connections to exclude from RPCs, such as ExcludeOwner or ExcludeServer. - /// - private HashSet _networkConnectionCache = new HashSet(); - #endregion - - /// - /// Called when buffered RPCs should be sent. - /// - internal void SendBufferedRpcs(NetworkConnection conn) - { - TransportManager tm = _networkObjectCache.NetworkManager.TransportManager; - foreach ((PooledWriter writer, Channel ch) in _bufferedRpcs.Values) - tm.SendToClient((byte)ch, writer.GetArraySegment(), conn); - } - - /// - /// Registers a RPC method. - /// - /// - /// - [APIExclude] - [CodegenMakePublic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected internal void RegisterServerRpc_Internal(uint hash, ServerRpcDelegate del) - { - bool contains = _serverRpcDelegates.ContainsKey(hash); - _serverRpcDelegates[hash] = del; - if (!contains) - IncreaseRpcMethodCount(); - } - /// - /// Registers a RPC method. - /// - /// - /// - [APIExclude] - [CodegenMakePublic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected internal void RegisterObserversRpc_Internal(uint hash, ClientRpcDelegate del) - { - bool contains = _observersRpcDelegates.ContainsKey(hash); - _observersRpcDelegates[hash] = del; - if (!contains) - IncreaseRpcMethodCount(); - } - /// - /// Registers a RPC method. - /// - /// - /// - [APIExclude] - [CodegenMakePublic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected internal void RegisterTargetRpc_Internal(uint hash, ClientRpcDelegate del) - { - bool contains = _targetRpcDelegates.ContainsKey(hash); - _targetRpcDelegates[hash] = del; - if (!contains) - IncreaseRpcMethodCount(); - } - - /// - /// Increases rpcMethodCount and rpcHashSize. - /// - private void IncreaseRpcMethodCount() - { - _rpcMethodCount++; - if (_rpcMethodCount <= byte.MaxValue) - _rpcHashSize = 1; - else - _rpcHashSize = 2; - } - - /// - /// Clears all buffered RPCs for this NetworkBehaviour. - /// - public void ClearBuffedRpcs() - { - foreach ((PooledWriter writer, Channel _) in _bufferedRpcs.Values) - writer.Dispose(); - _bufferedRpcs.Clear(); - } - - /// - /// Reads a RPC hash. - /// - /// - /// - private uint ReadRpcHash(PooledReader reader) - { - if (_rpcHashSize == 1) - return reader.ReadByte(); - else - return reader.ReadUInt16(); - } - /// - /// Called when a ServerRpc is received. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void OnServerRpc(PooledReader reader, NetworkConnection sendingClient, Channel channel) - { - uint methodHash = ReadRpcHash(reader); - - if (sendingClient == null) - { - _networkObjectCache.NetworkManager.LogError($"NetworkConnection is null. ServerRpc {methodHash} on object {gameObject.name} [id {ObjectId}] will not complete. Remainder of packet may become corrupt."); - return; - } - - if (_serverRpcDelegates.TryGetValueIL2CPP(methodHash, out ServerRpcDelegate data)) - data.Invoke(reader, channel, sendingClient); - else - _networkObjectCache.NetworkManager.LogWarning($"ServerRpc not found for hash {methodHash} on object {gameObject.name} [id {ObjectId}]. Remainder of packet may become corrupt."); - } - - /// - /// Called when an ObserversRpc is received. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void OnObserversRpc(uint? methodHash, PooledReader reader, Channel channel) - { - if (methodHash == null) - methodHash = ReadRpcHash(reader); - - if (_observersRpcDelegates.TryGetValueIL2CPP(methodHash.Value, out ClientRpcDelegate del)) - del.Invoke(reader, channel); - else - _networkObjectCache.NetworkManager.LogWarning($"ObserversRpc not found for hash {methodHash.Value} on object {gameObject.name} [id {ObjectId}] . Remainder of packet may become corrupt."); - } - - /// - /// Called when an TargetRpc is received. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void OnTargetRpc(uint? methodHash, PooledReader reader, Channel channel) - { - if (methodHash == null) - methodHash = ReadRpcHash(reader); - - if (_targetRpcDelegates.TryGetValueIL2CPP(methodHash.Value, out ClientRpcDelegate del)) - del.Invoke(reader, channel); - else - _networkObjectCache.NetworkManager.LogWarning($"TargetRpc not found for hash {methodHash.Value} on object {gameObject.name} [id {ObjectId}] . Remainder of packet may become corrupt."); - } - - /// - /// Sends a RPC to server. - /// - /// - /// - /// - [CodegenMakePublic] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SendServerRpc_Internal(uint hash, PooledWriter methodWriter, Channel channel) - { - if (!IsSpawnedWithWarning()) - return; - - PooledWriter writer = CreateRpc(hash, methodWriter, PacketId.ServerRpc, channel); - _networkObjectCache.NetworkManager.TransportManager.SendToServer((byte)channel, writer.GetArraySegment()); - writer.DisposeLength(); - } - - /// - /// Sends a RPC to observers. - /// - /// - /// - /// - [APIExclude] - [CodegenMakePublic] //Make internal. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SendObserversRpc_Internal(uint hash, PooledWriter methodWriter, Channel channel, bool buffered, bool excludeServer, bool excludeOwner) - { - if (!IsSpawnedWithWarning()) - return; - - PooledWriter writer; -#if UNITY_EDITOR || DEVELOPMENT_BUILD - if (NetworkManager.DebugManager.ObserverRpcLinks && _rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link)) -#else - if (_rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link)) -#endif - writer = CreateLinkedRpc(link, methodWriter, channel); - else - writer = CreateRpc(hash, methodWriter, PacketId.ObserversRpc, channel); - - SetNetworkConnectionCache(excludeServer, excludeOwner); - _networkObjectCache.NetworkManager.TransportManager.SendToClients((byte)channel, writer.GetArraySegment(), _networkObjectCache.Observers, _networkConnectionCache, true); - - /* If buffered then dispose of any already buffered - * writers and replace with new one. Writers should - * automatically dispose when references are lost - * anyway but better safe than sorry. */ - if (buffered) - { - if (_bufferedRpcs.TryGetValueIL2CPP(hash, out (PooledWriter pw, Channel ch) result)) - result.pw.DisposeLength(); - _bufferedRpcs[hash] = (writer, channel); - } - //If not buffered then dispose immediately. - else - { - writer.DisposeLength(); - } - } - - /// - /// Sends a RPC to target. - /// - [CodegenMakePublic] //Make internal. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SendTargetRpc_Internal(uint hash, PooledWriter methodWriter, Channel channel, NetworkConnection target, bool excludeServer, bool validateTarget = true) - { - if (!IsSpawnedWithWarning()) - return; - - if (validateTarget) - { - if (target == null) - { - _networkObjectCache.NetworkManager.LogWarning($"Action cannot be completed as no Target is specified."); - return; - } - else - { - //If target is not an observer. - if (!_networkObjectCache.Observers.Contains(target)) - { - _networkObjectCache.NetworkManager.LogWarning($"Action cannot be completed as Target is not an observer for object {gameObject.name} [id {ObjectId}]."); - return; - } - } - } - - //Excluding server. - if (excludeServer && target.IsLocalClient) - return; - - PooledWriter writer; - -#if UNITY_EDITOR || DEVELOPMENT_BUILD - if (NetworkManager.DebugManager.TargetRpcLinks && _rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link)) -#else - if (_rpcLinks.TryGetValueIL2CPP(hash, out RpcLinkType link)) -#endif - writer = CreateLinkedRpc(link, methodWriter, channel); - else - writer = CreateRpc(hash, methodWriter, PacketId.TargetRpc, channel); - - _networkObjectCache.NetworkManager.TransportManager.SendToClient((byte)channel, writer.GetArraySegment(), target); - writer.DisposeLength(); - } - - /// - /// Adds excluded connections to ExcludedRpcConnections. - /// - private void SetNetworkConnectionCache(bool addClientHost, bool addOwner) - { - _networkConnectionCache.Clear(); - if (addClientHost && IsClient) - _networkConnectionCache.Add(LocalConnection); - if (addOwner && Owner.IsValid) - _networkConnectionCache.Add(Owner); - } - - - /// - /// Returns if spawned and throws a warning if not. - /// - /// - private bool IsSpawnedWithWarning() - { - bool result = this.IsSpawned; - if (!result) - _networkObjectCache.NetworkManager.LogWarning($"Action cannot be completed as object {gameObject.name} [Id {ObjectId}] is not spawned."); - - return result; - } - - /// - /// Writes a full RPC and returns the writer. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private PooledWriter CreateRpc(uint hash, PooledWriter methodWriter, PacketId packetId, Channel channel) - { - int rpcHeaderBufferLength = GetEstimatedRpcHeaderLength(); - int methodWriterLength = methodWriter.Length; - //Writer containing full packet. - PooledWriter writer = WriterPool.GetWriter(rpcHeaderBufferLength + methodWriterLength); - writer.WritePacketId(packetId); - writer.WriteNetworkBehaviour(this); - //Only write length if reliable. - if (channel == Channel.Reliable) - writer.WriteLength(methodWriterLength + _rpcHashSize); - //Hash and data. - WriteRpcHash(hash, writer); - writer.WriteArraySegment(methodWriter.GetArraySegment()); - - return writer; - } - - /// - /// Writes rpcHash to writer. - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void WriteRpcHash(uint hash, PooledWriter writer) - { - if (_rpcHashSize == 1) - writer.WriteByte((byte)hash); - else - writer.WriteUInt16((byte)hash); - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCs.cs.meta b/Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCs.cs.meta deleted file mode 100644 index b468914..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.RPCs.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 938eacb83fa7d0046bd769b31dac7e80 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.SyncTypes.cs b/Assets/FishNet/Runtime/Object/NetworkBehaviour.SyncTypes.cs deleted file mode 100644 index 4a92bc0..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.SyncTypes.cs +++ /dev/null @@ -1,429 +0,0 @@ -using FishNet.Connection; -using FishNet.Documenting; -using FishNet.Managing.Logging; -using FishNet.Managing.Transporting; -using FishNet.Object.Synchronizing; -using FishNet.Object.Synchronizing.Internal; -using FishNet.Serializing; -using FishNet.Transporting; -using FishNet.Utility.Extension; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.Object -{ - - public abstract partial class NetworkBehaviour : MonoBehaviour - { - #region Types. - /// - /// Used to generate data sent from synctypes. - /// - private class SyncTypeWriter - { - /// - /// Clients which can be synchronized. - /// - public ReadPermission ReadPermission; - /// - /// Writers for each channel. - /// - public PooledWriter[] Writers { get; private set; } - - public SyncTypeWriter(ReadPermission readPermission) - { - ReadPermission = readPermission; - Writers = new PooledWriter[TransportManager.CHANNEL_COUNT]; - for (int i = 0; i < Writers.Length; i++) - Writers[i] = WriterPool.GetWriter(); - } - - /// - /// Resets Writers. - /// - public void Reset() - { - if (Writers == null) - return; - - for (int i = 0; i < Writers.Length; i++) - Writers[i].Reset(); - } - } - #endregion - - #region Private. - /// - /// Writers for syncTypes. A writer will exist for every ReadPermission type. - /// - private SyncTypeWriter[] _syncTypeWriters; - /// - /// SyncVars within this NetworkBehaviour. - /// - private Dictionary _syncVars = new Dictionary(); - /// - /// True if at least one syncVar is dirty. - /// - private bool _syncVarDirty; - /// - /// SyncVars within this NetworkBehaviour. - /// - private Dictionary _syncObjects = new Dictionary(); - /// - /// True if at least one syncObject is dirty. - /// - private bool _syncObjectDirty; - /// - /// All ReadPermission values. - /// - private static ReadPermission[] _readPermissions; - #endregion - - /// - /// Registers a SyncType. - /// - /// - /// - internal void RegisterSyncType(SyncBase sb, uint index) - { - if (sb.IsSyncObject) - _syncObjects.Add(index, sb); - else - _syncVars.Add(index, sb); - } - /// - /// Sets a SyncVar as dirty. - /// - /// True if dirtying a syncObject. - /// True if able to dirty SyncType. - internal bool DirtySyncType(bool isSyncObject) - { - if (!IsServer) - return false; - /* No reason to dirty if there are no observers. - * This can happen even if a client is going to see - * this object because the server side initializes - * before observers are built. */ - if (_networkObjectCache.Observers.Count == 0) - return false; - - bool alreadyDirtied = (isSyncObject) ? _syncObjectDirty : _syncVarDirty; - if (isSyncObject) - _syncObjectDirty = true; - else - _syncVarDirty = true; - - if (!alreadyDirtied) - _networkObjectCache.NetworkManager.ServerManager.Objects.SetDirtySyncType(this, isSyncObject); - - return true; - } - - /// - /// Initializes SyncTypes. This will only call once even as host. - /// - private void InitializeOnceSyncTypes() - { - if (_readPermissions == null) - { - System.Array arr = System.Enum.GetValues(typeof(ReadPermission)); - _readPermissions = new ReadPermission[arr.Length]; - - int count = 0; - foreach (ReadPermission rp in arr) - { - _readPermissions[count] = rp; - count++; - } - } - - //Build writers for observers and owner. - _syncTypeWriters = new SyncTypeWriter[_readPermissions.Length]; - for (int i = 0; i < _syncTypeWriters.Length; i++) - _syncTypeWriters[i] = new SyncTypeWriter(_readPermissions[i]); - - foreach (SyncBase sb in _syncVars.Values) - sb.PreInitialize(_networkObjectCache.NetworkManager); - foreach (SyncBase sb in _syncObjects.Values) - sb.PreInitialize(_networkObjectCache.NetworkManager); - } - - - /// - /// Reads a SyncVar. - /// - /// - internal void OnSyncType(PooledReader reader, int length, bool isSyncObject, bool asServer = false) - { - int readerStart = reader.Position; - while (reader.Position - readerStart < length) - { - byte index = reader.ReadByte(); - if (isSyncObject) - { - if (_syncObjects.TryGetValueIL2CPP(index, out SyncBase sb)) - sb.Read(reader, asServer); - else - NetworkManager.LogWarning($"SyncObject not found for index {index} on {transform.name}. Remainder of packet may become corrupt."); - } - else - { - if (_syncVars.ContainsKey(index)) - ReadSyncVar(reader, index, asServer); - else - NetworkManager.LogWarning($"SyncVar not found for index {index} on {transform.name}. Remainder of packet may become corrupt."); - } - } - } - - /// - /// Codegen overrides this method to read syncVars for each script which inherits NetworkBehaviour. - /// - /// - /// - /// True if reading into SyncVars for the server, false for client. This would be true for predicted spawning if the predicted spawner sent syncvars. - [APIExclude] - internal virtual bool ReadSyncVar(PooledReader reader, uint index, bool asServer) { return false; } - - /// - /// Writers dirty SyncTypes if their write tick has been met. - /// - /// True if there are no pending dirty sync types. - internal bool WriteDirtySyncTypes(bool isSyncObject, bool ignoreInterval = false) - { - /* Can occur when a synctype is queued after - * the object is marked for destruction. This should not - * happen under most conditions since synctypes will be - * pushed through when despawn is called. */ - if (!IsSpawned) - { - ResetSyncTypes(); - return true; - } - - /* If there is nothing dirty then return true, indicating no more - * pending dirty checks. */ - if (isSyncObject && (!_syncObjectDirty || _syncObjects.Count == 0)) - return true; - else if (!isSyncObject && (!_syncVarDirty || _syncVars.Count == 0)) - return true; - - /* True if writers have been reset for this check. - * For perf writers are only reset when data is to be written. */ - bool writersReset = false; - uint tick = _networkObjectCache.NetworkManager.TimeManager.Tick; - - //True if a syncvar is found to still be dirty. - bool dirtyFound = false; - //True if data has been written and is ready to send. - bool dataWritten = false; - Dictionary collection = (isSyncObject) ? _syncObjects : _syncVars; - - foreach (SyncBase sb in collection.Values) - { - if (!sb.IsDirty) - continue; - - dirtyFound = true; - if (ignoreInterval || sb.WriteTimeMet(tick)) - { - //If writers still need to be reset. - if (!writersReset) - { - writersReset = true; - //Reset writers. - for (int i = 0; i < _syncTypeWriters.Length; i++) - _syncTypeWriters[i].Reset(); - } - - //Find channel. - byte channel = (byte)sb.Channel; - sb.ResetDirty(); - //If ReadPermission is owner but no owner skip this syncvar write. - if (sb.Settings.ReadPermission == ReadPermission.OwnerOnly && !_networkObjectCache.Owner.IsValid) - continue; - - dataWritten = true; - //Find PooledWriter to use. - PooledWriter writer = null; - for (int i = 0; i < _syncTypeWriters.Length; i++) - { - if (_syncTypeWriters[i].ReadPermission == sb.Settings.ReadPermission) - { - /* Channel for syncVar is beyond available channels in transport. - * Use default reliable. */ - if (channel >= _syncTypeWriters[i].Writers.Length) - channel = (byte)Channel.Reliable; - - writer = _syncTypeWriters[i].Writers[channel]; - break; - } - } - - if (writer == null) - NetworkManager.LogError($"Writer couldn't be found for permissions {sb.Settings.ReadPermission} on channel {channel}."); - else - sb.WriteDelta(writer); - } - } - - //If no dirty were found. - if (!dirtyFound) - { - if (isSyncObject) - _syncObjectDirty = false; - else - _syncVarDirty = false; - return true; - } - //At least one sync type was dirty. - else if (dataWritten) - { - for (int i = 0; i < _syncTypeWriters.Length; i++) - { - for (byte channel = 0; channel < _syncTypeWriters[i].Writers.Length; channel++) - { - PooledWriter channelWriter = _syncTypeWriters[i].Writers[channel]; - //If there is data to send. - if (channelWriter.Length > 0) - { - using (PooledWriter headerWriter = WriterPool.GetWriter()) - { - //Write the packetId and NB information. - PacketId packetId = (isSyncObject) ? PacketId.SyncObject : PacketId.SyncVar; - headerWriter.WritePacketId(packetId); - PooledWriter dataWriter = WriterPool.GetWriter(); - dataWriter.WriteNetworkBehaviour(this); - - /* SyncVars need length written regardless because amount - * of data being sent per syncvar is unknown, and the packet may have - * additional data after the syncvars. Because of this we should only - * read up to syncvar length then assume the remainder is another packet. - * - * Reliable always has data written as well even if syncObject. This is so - * if an object does not exist for whatever reason the packet can be - * recovered by skipping the data. - * - * Realistically everything will be a syncvar or on the reliable channel unless - * the user makes a custom syncobject that utilizes unreliable. */ - if (!isSyncObject || (Channel)channel == Channel.Reliable) - dataWriter.WriteBytesAndSize(channelWriter.GetBuffer(), 0, channelWriter.Length); - else - dataWriter.WriteBytes(channelWriter.GetBuffer(), 0, channelWriter.Length); - - //Attach data onto packetWriter. - headerWriter.WriteArraySegment(dataWriter.GetArraySegment()); - dataWriter.Dispose(); - - - //If only sending to owner. - if (_syncTypeWriters[i].ReadPermission == ReadPermission.OwnerOnly) - { - _networkObjectCache.NetworkManager.TransportManager.SendToClient(channel, headerWriter.GetArraySegment(), _networkObjectCache.Owner); - } - //Sending to observers. - else - { - bool excludeOwner = (_syncTypeWriters[i].ReadPermission == ReadPermission.ExcludeOwner); - SetNetworkConnectionCache(false, excludeOwner); - NetworkConnection excludedConnection = (excludeOwner) ? _networkObjectCache.Owner : null; - _networkObjectCache.NetworkManager.TransportManager.SendToClients((byte)channel, headerWriter.GetArraySegment(), _networkObjectCache.Observers, _networkConnectionCache); - - } - - - - } - } - } - } - } - - /* Fall through. If here then sync types are still pending - * being written or were just written this frame. */ - return false; - } - - - /// - /// Resets all SyncTypes for this NetworkBehaviour for server and client side. - /// - internal void ResetSyncTypes() - { - foreach (SyncBase item in _syncVars.Values) - item.Reset(); - foreach (SyncBase item in _syncObjects.Values) - item.Reset(); - - _syncObjectDirty = false; - _syncVarDirty = false; - } - - - /// - /// Resets all SyncTypes for this NetworkBehaviour. - /// - internal void ResetSyncTypes(bool asServer) - { - if (asServer || (!asServer && !IsServer)) - { - foreach (SyncBase item in _syncVars.Values) - item.Reset(); - foreach (SyncBase item in _syncObjects.Values) - item.Reset(); - } - } - - /// - /// Writers syncVars for a spawn message. - /// - internal void WriteSyncTypesForSpawn(PooledWriter writer, SyncTypeWriteType writeType) - { - //Write for owner if writing all or owner, but not observers. - bool ownerWrite = (writeType != SyncTypeWriteType.Observers); - WriteSyncType(_syncVars); - WriteSyncType(_syncObjects); - - void WriteSyncType(Dictionary collection) - { - using (PooledWriter syncTypeWriter = WriterPool.GetWriter()) - { - /* Since all values are being written everything is - * written in order so there's no reason to pass - * indexes. */ - foreach (SyncBase sb in collection.Values) - { - //If not for owner and syncvar is owner only. - if (!ownerWrite && sb.Settings.ReadPermission == ReadPermission.OwnerOnly) - { - //If there is an owner then skip. - if (_networkObjectCache.Owner.IsValid) - continue; - } - - sb.WriteFull(syncTypeWriter); - } - - writer.WriteBytesAndSize(syncTypeWriter.GetBuffer(), 0, syncTypeWriter.Length); - } - } - } - - - /// - /// Manually marks a SyncType as dirty, be it SyncVar or SyncObject. - /// - /// SyncType variable to dirty. - protected void DirtySyncType(object syncType) - { - /* This doesn't actually do anything. - * The codegen replaces calls to this method - * with a Dirty call for syncType. */ - } - - - } - - -} - diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.SyncTypes.cs.meta b/Assets/FishNet/Runtime/Object/NetworkBehaviour.SyncTypes.cs.meta deleted file mode 100644 index 2d0f47e..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.SyncTypes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e56d5389eb07aa040b8a9ec8b0d7c597 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.cs b/Assets/FishNet/Runtime/Object/NetworkBehaviour.cs deleted file mode 100644 index 750bb12..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.cs +++ /dev/null @@ -1,190 +0,0 @@ -using FishNet.Documenting; -using FishNet.Serializing.Helping; -using FishNet.Utility.Constant; -using System.Runtime.CompilerServices; -using UnityEngine; - -[assembly: InternalsVisibleTo(UtilityConstants.CODEGEN_ASSEMBLY_NAME)] -namespace FishNet.Object -{ - /// - /// Scripts which inherit from NetworkBehaviour can be used to gain insight of, and perform actions on the network. - /// - public abstract partial class NetworkBehaviour : MonoBehaviour - { - /// - /// True if this NetworkBehaviour is initialized for the network. - /// - public bool IsSpawned => _networkObjectCache.IsSpawned; - /// - /// - /// - [SerializeField, HideInInspector] - private byte _componentIndexCache = byte.MaxValue; - /// - /// ComponentIndex for this NetworkBehaviour. - /// - public byte ComponentIndex - { - get => _componentIndexCache; - private set => _componentIndexCache = value; - } -#if UNITY_EDITOR - /// - /// NetworkObject automatically added or discovered during edit time. - /// - [SerializeField, HideInInspector] - private NetworkObject _addedNetworkObject; -#endif - /// - /// - /// - [SerializeField, HideInInspector] - private NetworkObject _networkObjectCache; - /// - /// NetworkObject this behaviour is for. - /// - public NetworkObject NetworkObject => _networkObjectCache; - - /// - /// Initializes this script. This will only run once even as host. - /// - /// - /// - internal void InitializeOnce_Internal() - { - InitializeOnceSyncTypes(); - InitializeOnceRpcLinks(); - } - - - /// - /// Serializes information for network components. - /// - internal void SerializeComponents(NetworkObject nob, byte componentIndex) - { - _networkObjectCache = nob; - ComponentIndex = componentIndex; - } - - /// - /// Manually initializes network content for the NetworkBehaviour if the object it's on is disabled. - /// - internal void InitializeIfDisabled() - { - if (gameObject.activeInHierarchy) - return; - - NetworkInitializeIfDisabled(); - } - /// - /// Long name is to prevent users from potentially creating their own method named the same. - /// - [CodegenMakePublic] - [APIExclude] - internal virtual void NetworkInitializeIfDisabled() { } - - #region Editor. - protected virtual void Reset() - { -#if UNITY_EDITOR - if (Application.isPlaying) - return; - - TryAddNetworkObject(); -#endif - } - - protected virtual void OnValidate() - { -#if UNITY_EDITOR - if (Application.isPlaying) - return; - - TryAddNetworkObject(); -#endif - } - - /// - /// Resets this NetworkBehaviour so that it may be added to an object pool. - /// - internal void ResetForObjectPool() - { - ResetSyncTypes(); - ClearReplicateCache(); - ClearBuffedRpcs(); - } - - - /// - /// Tries to add the NetworkObject component. - /// - private NetworkObject TryAddNetworkObject() - { -#if UNITY_EDITOR - if (Application.isPlaying) - return _addedNetworkObject; - - if (_addedNetworkObject != null) - { - AlertToDuplicateNetworkObjects(_addedNetworkObject.transform); - return _addedNetworkObject; - } - - /* Manually iterate up the chain because GetComponentInParent doesn't - * work when modifying prefabs in the inspector. Unity, you're starting - * to suck a lot right now. */ - NetworkObject result = null; - Transform climb = transform; - - while (climb != null) - { - if (climb.TryGetComponent(out result)) - break; - else - climb = climb.parent; - } - - if (result != null) - { - _addedNetworkObject = result; - } - //Not found, add a new nob. - else - { - _addedNetworkObject = transform.root.gameObject.AddComponent(); - Debug.Log($"Script {GetType().Name} on object {gameObject.name} added a NetworkObject component to {transform.root.name}."); - } - - AlertToDuplicateNetworkObjects(_addedNetworkObject.transform); - return _addedNetworkObject; - - //Removes duplicate network objects from t. - void AlertToDuplicateNetworkObjects(Transform t) - { - NetworkObject[] nobs = t.GetComponents(); - //This shouldn't be possible but does occur sometimes; maybe a unity bug? - if (nobs.Length > 1) - { - //Update added to first entryt. - _addedNetworkObject = nobs[0]; - - string useMenu = " You may also use the Fish-Networking menu to automatically remove duplicate NetworkObjects."; - string sceneName = t.gameObject.scene.name; - if (string.IsNullOrEmpty(sceneName)) - Debug.LogError($"Prefab {t.name} has multiple NetworkObject components. Please remove the extra component(s) to prevent errors.{useMenu}"); - else - Debug.LogError($"Object {t.name} in scene {sceneName} has multiple NetworkObject components. Please remove the extra component(s) to prevent errors.{useMenu}"); - } - - } -#else - return null; -#endif - } - - #endregion - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/NetworkBehaviour.cs.meta b/Assets/FishNet/Runtime/Object/NetworkBehaviour.cs.meta deleted file mode 100644 index 6188375..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkBehaviour.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d2230f9cdb1ffc9489b53875c963342d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.Broadcast.cs b/Assets/FishNet/Runtime/Object/NetworkObject.Broadcast.cs deleted file mode 100644 index 14459b7..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.Broadcast.cs +++ /dev/null @@ -1,31 +0,0 @@ -using FishNet.Broadcast; -using FishNet.Managing; -using FishNet.Transporting; -using UnityEngine; - -namespace FishNet.Object -{ - public sealed partial class NetworkObject : MonoBehaviour - { - - /// - /// Sends a broadcast to Observers on this NetworkObject. - /// - /// Type of broadcast to send. - /// Broadcast data being sent; for example: an instance of your broadcast type. - /// True if the client must be authenticated for this broadcast to send. - /// Channel to send on. - public void Broadcast(T message, bool requireAuthenticated = true, Channel channel = Channel.Reliable) where T : struct, IBroadcast - { - if (NetworkManager == null) - { - NetworkManager.StaticLogWarning($"Cannot send broadcast from {gameObject.name}, NetworkManager reference is null. This may occur if the object is not spawned or initialized."); - return; - } - - NetworkManager.ServerManager.Broadcast(Observers, message, requireAuthenticated, channel); - } - } - -} - diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.Broadcast.cs.meta b/Assets/FishNet/Runtime/Object/NetworkObject.Broadcast.cs.meta deleted file mode 100644 index 4068fcb..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.Broadcast.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 55d793117b52da549affcc9ec30b05c0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.Callbacks.cs b/Assets/FishNet/Runtime/Object/NetworkObject.Callbacks.cs deleted file mode 100644 index edc700c..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.Callbacks.cs +++ /dev/null @@ -1,150 +0,0 @@ -using FishNet.Connection; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Object -{ - public sealed partial class NetworkObject : MonoBehaviour - { - /// - /// Called after all data is synchronized with this NetworkObject. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void InitializeCallbacks(bool asServer, bool invokeSyncTypeCallbacks) - { - /* Note: When invoking OnOwnership here previous owner will - * always be an empty connection, since the object is just - * now initializing. */ - - if (!asServer) - ClientInitialized = true; - - //Set that client or server is active before callbacks. - SetActiveStatus(true, asServer); - - //Invoke OnStartNetwork. - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].InvokeOnNetwork(true); - - //As server. - if (asServer) - { - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].OnStartServer(); - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].OnOwnershipServer(FishNet.Managing.NetworkManager.EmptyConnection); - if (invokeSyncTypeCallbacks) - InvokeSyncTypeCallbacks(true); - } - //As client. - else - { - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].OnStartClient(); - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].OnOwnershipClient(FishNet.Managing.NetworkManager.EmptyConnection); - if (invokeSyncTypeCallbacks) - InvokeSyncTypeCallbacks(false); - } - } - - - /// - /// Invokes pending SyncType callbacks. - /// - /// - internal void InvokeSyncTypeCallbacks(bool asServer) - { - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].InvokeSyncTypeCallbacks(asServer); - } - - /// - /// Invokes events to be called after OnServerStart. - /// This is made one method to save instruction calls. - /// - /// - internal void InvokePostOnServerStart(NetworkConnection conn) - { - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].SendBufferedRpcs(conn); - - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].OnSpawnServer(conn); - } - - /// - /// Called on the server before it sends a despawn message to a client. - /// - /// Connection spawn was sent to. - internal void InvokeOnServerDespawn(NetworkConnection conn) - { - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].OnDespawnServer(conn); - } - - /// - /// Invokes OnStop callbacks. - /// - /// - internal void InvokeStopCallbacks(bool asServer) - { - if (asServer) - { - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].OnStopServer(); - } - else - { - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].OnStopClient(); - } - - /* Invoke OnStopNetwork if server is calling - * or if client and not as server. */ - if (asServer || (!asServer && !IsServer)) - { - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].InvokeOnNetwork(false); - } - - if (asServer) - IsServer = false; - else - IsClient = false; - } - - /// - /// Invokes OnOwnership callbacks. - /// - /// - private void InvokeOwnership(NetworkConnection prevOwner, bool asServer) - { - if (asServer) - { - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].OnOwnershipServer(prevOwner); - } - else - { - /* If local client is owner and not server then only - * invoke if the prevOwner is different. This prevents - * the owner change callback from happening twice when - * using TakeOwnership. - * - * Further explained, the TakeOwnership sets local client - * as owner client-side, which invokes the OnOwnership method. - * Then when the server approves the owner change it would invoke - * again, which is not needed. */ - bool blockInvoke = ((IsOwner && !IsServer) && (prevOwner == Owner)); - if (!blockInvoke) - { - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].OnOwnershipClient(prevOwner); - } - } - } - } - -} - diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.Callbacks.cs.meta b/Assets/FishNet/Runtime/Object/NetworkObject.Callbacks.cs.meta deleted file mode 100644 index 21b4bb7..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.Callbacks.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8e9fbf0d6eb10e94d892dd4e817030bc -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.Observers.cs b/Assets/FishNet/Runtime/Object/NetworkObject.Observers.cs deleted file mode 100644 index e39a968..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.Observers.cs +++ /dev/null @@ -1,213 +0,0 @@ -using FishNet.Connection; -using FishNet.Observing; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Object -{ - public sealed partial class NetworkObject : MonoBehaviour - { - #region Public. - /// - /// Called when this NetworkObject losses all observers or gains observers while previously having none. - /// - public event Action OnObserversActive; - /// - /// NetworkObserver on this object. - /// - [HideInInspector] - public NetworkObserver NetworkObserver = null; - /// - /// Clients which can see and get messages from this NetworkObject. - /// - public HashSet Observers = new HashSet(); - #endregion - - #region Private. - /// - /// True if NetworkObserver has been initialized. - /// - private bool _networkObserverInitiliazed = false; - /// - /// Found renderers on the NetworkObject and it's children. This is only used as clientHost to hide non-observers objects. - /// - [System.NonSerialized] - private Renderer[] _renderers; - /// - /// True if renderers have been looked up. - /// - private bool _renderersPopulated; - /// - /// Last visibility value for clientHost on this object. - /// - private bool _lastClientHostVisibility; - #endregion - - /// - /// Updates cached renderers used to managing clientHost visibility. - /// - /// True to also update visibility if clientHost. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void UpdateRenderers(bool updateVisibility = true) - { - UpdateRenderers_Internal(updateVisibility); - } - - /// - /// Sets the renderer visibility for clientHost. - /// - /// True if renderers are to be visibile. - /// True to skip blocking checks. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SetRenderersVisible(bool visible, bool force = false) - { - if (!force) - { - if (!NetworkObserver.UpdateHostVisibility) - return; - } - - if (!_renderersPopulated) - { - UpdateRenderers_Internal(false); - _renderersPopulated = true; - } - - UpdateRenderVisibility(visible); - } - - /// - /// Clears and updates renderers. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void UpdateRenderers_Internal(bool updateVisibility) - { - _renderers = GetComponentsInChildren(true); - List enabledRenderers = new List(); - foreach (Renderer r in _renderers) - { - if (r.enabled) - enabledRenderers.Add(r); - } - //If there are any disabled renderers then change _renderers to cached values. - if (enabledRenderers.Count != _renderers.Length) - _renderers = enabledRenderers.ToArray(); - - if (updateVisibility) - UpdateRenderVisibility(_lastClientHostVisibility); - } - - /// - /// Updates visibilites on renders without checks. - /// - /// - private void UpdateRenderVisibility(bool visible) - { - bool rebuildRenderers = false; - - Renderer[] rs = _renderers; - int count = rs.Length; - for (int i = 0; i < count; i++) - { - Renderer r = rs[i]; - if (r == null) - { - rebuildRenderers = true; - break; - } - - r.enabled = visible; - } - - _lastClientHostVisibility = visible; - //If to rebuild then do so, while updating visibility. - if (rebuildRenderers) - UpdateRenderers(true); - } - - /// - /// Adds the default NetworkObserver conditions using the ObserverManager. - /// - private void AddDefaultNetworkObserverConditions() - { - if (_networkObserverInitiliazed) - return; - - NetworkObserver = NetworkManager.ObserverManager.AddDefaultConditions(this); - } - - - /// - /// Removes a connection from observers for this object returning if the connection was removed. - /// - /// - internal bool RemoveObserver(NetworkConnection connection) - { - int startCount = Observers.Count; - bool removed = Observers.Remove(connection); - if (removed) - TryInvokeOnObserversActive(startCount); - - return removed; - } - - /// - /// Adds the connection to observers if conditions are met. - /// - /// - /// True if added to Observers. - internal ObserverStateChange RebuildObservers(NetworkConnection connection, bool timedOnly) - { - //If not a valid connection. - if (!connection.IsValid) - { - NetworkManager.LogWarning($"An invalid connection was used when rebuilding observers."); - return ObserverStateChange.Unchanged; - } - //Valid not not active. - else if (!connection.IsActive) - { - /* Just remove from observers since connection isn't active - * and return unchanged because nothing should process - * given the connection isnt active. */ - Observers.Remove(connection); - return ObserverStateChange.Unchanged; - } - else if (IsDeinitializing) - { - /* If object is deinitializing it's either being despawned - * this frame or it's not spawned. If we've made it this far, - * it's most likely being despawned. */ - return ObserverStateChange.Unchanged; - } - - int startCount = Observers.Count; - ObserverStateChange osc = NetworkObserver.RebuildObservers(connection, timedOnly); - if (osc == ObserverStateChange.Added) - Observers.Add(connection); - else if (osc == ObserverStateChange.Removed) - Observers.Remove(connection); - - if (osc != ObserverStateChange.Unchanged) - TryInvokeOnObserversActive(startCount); - - return osc; - } - - /// - /// Invokes OnObserversActive if observers are now 0 but previously were not, or if was previously 0 but now has observers. - /// - /// - private void TryInvokeOnObserversActive(int startCount) - { - if ((Observers.Count > 0 && startCount == 0) || - Observers.Count == 0 && startCount > 0) - OnObserversActive?.Invoke(this); - } - - } - -} - diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.Observers.cs.meta b/Assets/FishNet/Runtime/Object/NetworkObject.Observers.cs.meta deleted file mode 100644 index 2024e29..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.Observers.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 816dbea70a70ab949a44f485155f0087 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.QOL.cs b/Assets/FishNet/Runtime/Object/NetworkObject.QOL.cs deleted file mode 100644 index 076a756..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.QOL.cs +++ /dev/null @@ -1,313 +0,0 @@ -using FishNet.Component.ColliderRollback; -using FishNet.Connection; -using FishNet.Managing; -using FishNet.Managing.Client; -using FishNet.Managing.Observing; -using FishNet.Managing.Predicting; -using FishNet.Managing.Scened; -using FishNet.Managing.Server; -using FishNet.Managing.Timing; -using FishNet.Managing.Transporting; -using System; -using UnityEngine; - -namespace FishNet.Object -{ - public sealed partial class NetworkObject : MonoBehaviour - { - #region Public. - /// - /// True if predicted spawning is allowed for this object. - /// - internal bool AllowPredictedSpawning => (PredictedSpawn == null) ? false : PredictedSpawn.GetAllowSpawning(); - /// - /// True if predicted spawning is allowed for this object. - /// - internal bool AllowPredictedDespawning => (PredictedSpawn == null) ? false : PredictedSpawn.GetAllowDespawning(); - /// - /// True to allow clients to predicted set syncTypes prior to spawning the item. Set values will be applied on the server and sent to other clients. - /// - internal bool AllowPredictedSyncTypes => (PredictedSpawn == null) ? false : PredictedSpawn.GetAllowSyncTypes(); - /// - /// True if this object has been initialized on the client side. - /// This is set true right before client callbacks. - /// - public bool ClientInitialized { get; private set; } - /// - /// - /// - private bool _isClient; - /// - /// True if the client is active and authenticated. - /// - public bool IsClient - { - /* This needs to use a special check when - * player is acting as host. Clients won't - * set IsClient until they receive the spawn message - * but the user may expect this true after client - * gains observation but before client gets spawn. */ - get - { - if (IsServer) - return (NetworkManager == null) ? false : NetworkManager.IsClient; - else - return _isClient; - } - - private set => _isClient = value; - } - - /// - /// True if only the client is active and authenticated. - /// - public bool IsClientOnly => (IsClient && !IsServer); - /// - /// True if server is active. - /// - public bool IsServer { get; private set; } - /// - /// True if only the server is active. - /// - public bool IsServerOnly => (IsServer && !IsClient); - /// - /// True if client and server are active. - /// - public bool IsHost => (IsClient && IsServer); - /// - /// True if client nor server are active. - /// - public bool IsOffline => (!IsClient && !IsServer); - /// - /// True if the local client is the owner of this object. - /// - public bool IsOwner - { - get - { - /* ClientInitialized becomes true when this - * NetworkObject has been initialized on the client side. - * - * This value is used to prevent IsOwner from returning true - * when running as host; primarily in Update or Tick callbacks - * where IsOwner would be true as host but OnStartClient has - * not called yet. - * - * EG: server will set owner when it spawns the object. - * If IsOwner is checked before the object spawns on the - * client-host then it would also return true, since the - * Owner reference would be the same as what was set by server. - * - * This is however bad when the client hasn't initialized the object - * yet because it gives a false sense of execution order. - * As a result, Update or Ticks may return IsOwner as true well before OnStartClient - * is called. Many users rightfully create code with the assumption the client has been - * initialized by the time IsOwner is true. - * - * This is a double edged sword though because now IsOwner would return true - * within OnStartNetwork for clients only, but not for host given the client - * side won't be initialized yet as host. As a work around CodeAnalysis will - * inform users to instead use base.Owner.IsLocalClient within OnStartNetwork. */ - if (!ClientInitialized) - return false; - - return Owner.IsLocalClient; - } - } - - /// - /// - /// - private NetworkConnection _owner; - /// - /// Owner of this object. - /// - public NetworkConnection Owner - { - get - { - //Ensures a null Owner is never returned. - if (_owner == null) - return FishNet.Managing.NetworkManager.EmptyConnection; - - return _owner; - } - private set { _owner = value; } - } - /// - /// ClientId for this NetworkObject owner. - /// - public int OwnerId => (!Owner.IsValid) ? -1 : Owner.ClientId; - /// - /// True if the object is initialized for the network. - /// - public bool IsSpawned => (!IsDeinitializing && ObjectId != NetworkObject.UNSET_OBJECTID_VALUE); - /// - /// The local connection of the client calling this method. - /// - public NetworkConnection LocalConnection => (NetworkManager == null) ? new NetworkConnection() : NetworkManager.ClientManager.Connection; - /// - /// NetworkManager for this object. - /// - public NetworkManager NetworkManager { get; private set; } - /// - /// ServerManager for this object. - /// - public ServerManager ServerManager { get; private set; } - /// - /// ClientManager for this object. - /// - public ClientManager ClientManager { get; private set; } - /// - /// ObserverManager for this object. - /// - public ObserverManager ObserverManager { get; private set; } - /// - /// TransportManager for this object. - /// - public TransportManager TransportManager { get; private set; } - /// - /// TimeManager for this object. - /// - public TimeManager TimeManager { get; private set; } - /// - /// SceneManager for this object. - /// - public SceneManager SceneManager { get; private set; } - /// - /// PredictionManager for this object. - /// - public PredictionManager PredictionManager {get;private set;} - /// - /// RollbackManager for this object. - /// - public RollbackManager RollbackManager { get; private set; } - #endregion - - /// - /// Returns a NetworkBehaviour on this NetworkObject. - /// - /// ComponentIndex of the NetworkBehaviour. - /// True to error if not found. - /// - public NetworkBehaviour GetNetworkBehaviour(byte componentIndex, bool error) - { - if (componentIndex >= NetworkBehaviours.Length) - { - if (error) - { - string message = $"ComponentIndex of {componentIndex} is out of bounds on {gameObject.name} [id {ObjectId}]. This may occur if you have modified your gameObject/prefab without saving it, or the scene."; - if (NetworkManager == null) - NetworkManager.StaticLogError(message); - else - NetworkManager.LogError(message); - - } - } - - return NetworkBehaviours[componentIndex]; - } - - /// - /// Despawns a GameObject. Only call from the server. - /// - /// GameObject to despawn. - /// What happens to the object after being despawned. - public void Despawn(GameObject go, DespawnType? despawnType = null) - { - NetworkManager?.ServerManager.Despawn(go, despawnType); - } - /// - /// Despawns a NetworkObject. Only call from the server. - /// - /// NetworkObject to despawn. - /// What happens to the object after being despawned. - public void Despawn(NetworkObject nob, DespawnType? despawnType = null) - { - NetworkManager?.ServerManager.Despawn(nob, despawnType); - } - /// - /// Despawns this NetworkObject. Only call from the server. - /// - /// What happens to the object after being despawned. - public void Despawn(DespawnType? despawnType = null) - { - NetworkObject nob = this; - NetworkManager?.ServerManager.Despawn(nob, despawnType); - } - /// - /// Spawns an object over the network. Only call from the server. - /// - public void Spawn(GameObject go, NetworkConnection ownerConnection = null) - { - NetworkManager?.ServerManager.Spawn(go, ownerConnection); - } - /// - /// Spawns an object over the network. Only call from the server. - /// - public void Spawn(NetworkObject nob, NetworkConnection ownerConnection = null) - { - NetworkManager?.ServerManager.Spawn(nob, ownerConnection); - } - - /// - /// Takes ownership of this object and child network objects, allowing immediate control. - /// - /// Connection to give ownership to. - public void SetLocalOwnership(NetworkConnection caller) - { - NetworkConnection prevOwner = Owner; - SetOwner(caller); - - int count; - count = NetworkBehaviours.Length; - for (int i = 0; i < count; i++) - NetworkBehaviours[i].OnOwnershipClient(prevOwner); - count = ChildNetworkObjects.Count; - for (int i = 0; i < count; i++) - ChildNetworkObjects[i].SetLocalOwnership(caller); - } - - #region Registered components - /// - /// Invokes an action when a specified component becomes registered. Action will invoke immediately if already registered. - /// - /// Component type. - /// Action to invoke. - public void RegisterInvokeOnInstance(Action handler) where T : UnityEngine.Component => NetworkManager.RegisterInvokeOnInstance(handler); - /// - /// Removes an action to be invoked when a specified component becomes registered. - /// - /// Component type. - /// Action to invoke. - public void UnregisterInvokeOnInstance(Action handler) where T : UnityEngine.Component => NetworkManager.UnregisterInvokeOnInstance(handler); - /// - /// Returns if an instance exists for type. - /// - /// - /// - public bool HasInstance() where T : UnityEngine.Component => NetworkManager.HasInstance(); - /// - /// Returns class of type if found within CodegenBase classes. - /// - /// - /// - public T GetInstance() where T : UnityEngine.Component => NetworkManager.GetInstance(); - /// - /// Registers a new component to this NetworkManager. - /// - /// Type to register. - /// Reference of the component being registered. - /// True to replace existing references. - public void RegisterInstance(T component, bool replace = true) where T : UnityEngine.Component => NetworkManager.RegisterInstance(component, replace); - /// - /// Unregisters a component from this NetworkManager. - /// - /// Type to unregister. - public void UnregisterInstance() where T : UnityEngine.Component => NetworkManager.UnregisterInstance(); - #endregion - - } - -} - diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.QOL.cs.meta b/Assets/FishNet/Runtime/Object/NetworkObject.QOL.cs.meta deleted file mode 100644 index 422ef3f..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.QOL.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fd30b4b61d50d01499c94a63a6eeb863 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.ReferenceIds.cs b/Assets/FishNet/Runtime/Object/NetworkObject.ReferenceIds.cs deleted file mode 100644 index f5eeb08..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.ReferenceIds.cs +++ /dev/null @@ -1,213 +0,0 @@ -using UnityEngine; -using System.Collections.Generic; -using System; -using FishNet.Object.Helping; -using System.Linq; -#if UNITY_EDITOR -using UnityEditor.Experimental.SceneManagement; -using UnityEditor.SceneManagement; -using UnityEditor; -#endif - -namespace FishNet.Object -{ - public sealed partial class NetworkObject : MonoBehaviour - { - #region Serialized. - - /// - /// Networked PrefabId assigned to this Prefab. - /// - [field: SerializeField, HideInInspector] - public ushort PrefabId { get; internal set; } = 0; - /// - /// Spawn collection to use assigned to this Prefab. - /// - [field: SerializeField, HideInInspector] - public ushort SpawnableCollectionId { get; internal set; } = 0; -#pragma warning disable 414 //Disabled because Unity thinks tihs is unused when building. - /// - /// Hash to the scene which this object resides. - /// - [SerializeField, HideInInspector] - private uint _scenePathHash; -#pragma warning restore 414 - /// - /// Network Id for this scene object. - /// - [field: SerializeField, HideInInspector] - internal ulong SceneId { get; private set; } - /// - /// Hash for the path which this asset resides. This value is set during edit time. - /// - [field: SerializeField, HideInInspector] - public ulong AssetPathHash { get; private set; } - /// - /// Sets AssetPathhash value. - /// - /// Value to use. - public void SetAssetPathHash(ulong value) => AssetPathHash = value; - #endregion - -#if UNITY_EDITOR - /// - /// This is used to store NetworkObjects in the scene during edit time. - /// SceneIds are compared against this collection to ensure there are no duplicated. - /// - [SerializeField, HideInInspector] - private List _sceneNetworkObjects = new List(); -#endif - - /// - /// Removes SceneObject state. - /// This may only be called at runtime. - /// - internal void ClearRuntimeSceneObject() - { - if (!Application.isPlaying) - { - Debug.LogError($"ClearRuntimeSceneObject may only be called at runtime."); - return; - } - - SceneId = 0; - } - -#if UNITY_EDITOR - /// - /// Tries to generate a SceneId. - /// - internal void TryCreateSceneID() - { - if (Application.isPlaying) - return; - //Unity bug, sometimes this can be null depending on editor callback orders. - if (gameObject == null) - return; - //Not a scene object. - if (string.IsNullOrEmpty(gameObject.scene.name)) - { - SceneId = 0; - return; - } - - ulong startId = SceneId; - uint startPath = _scenePathHash; - - ulong sceneId = 0; - uint scenePathHash = 0; - //If prefab or part of a prefab, not a scene object. - if (PrefabUtility.IsPartOfPrefabAsset(this) || IsEditingInPrefabMode() || - //Not in a scene, another prefab check. - !gameObject.scene.IsValid() || - //Stored on disk, so is a prefab. Somehow prefabutility missed it. - EditorUtility.IsPersistent(this)) - { - //These are all failing conditions, don't do additional checks. - } - else - { - System.Random rnd = new System.Random(); - scenePathHash = gameObject.scene.path.ToLower().GetStableHash32(); - sceneId = SceneId; - //Not a valid sceneId or is a duplicate. - if (scenePathHash != _scenePathHash || SceneId == 0 || IsDuplicateSceneId(SceneId)) - { - /* If a scene has not been opened since an id has been - * generated then it will not be serialized in editor. The id - * would be correct in build but not if running in editor. - * Should conditions be true where scene is building without - * being opened then cancel build and request user to open and save - * scene. */ - if (BuildPipeline.isBuildingPlayer) - throw new InvalidOperationException($"Networked GameObject {gameObject.name} in scene {gameObject.scene.path} is missing a SceneId. Open the scene, select the Fish-Networking menu, and choose Rebuild SceneIds. If the problem persist ensures {gameObject.name} does not have any missing script references on it's prefab or in the scene. Also ensure that you have any prefab changes for the object applied."); - - ulong shiftedHash = (ulong)scenePathHash << 32; - ulong randomId = 0; - while (randomId == 0 || IsDuplicateSceneId(randomId)) - { - uint next = (uint)(rnd.Next(int.MinValue, int.MaxValue) + int.MaxValue); - /* Since the collection is lost when a scene loads the it's possible to - * have a sceneid from another scene. Because of this the scene path is - * inserted into the sceneid. */ - randomId = (next & 0xFFFFFFFF) | shiftedHash; - } - - sceneId = randomId; - } - - } - - bool idChanged = (sceneId != startId); - bool pathChanged = (startPath != scenePathHash); - //If either changed then dirty and set. - if (idChanged || pathChanged) - { - //Set dirty so changes will be saved. - EditorUtility.SetDirty(this); - /* Add to sceneIds collection. This must be done - * even if a new sceneId was not generated because - * the collection information is lost when the - * scene is existed. Essentially, it gets repopulated - * when the scene is re-opened. */ - SceneId = sceneId; - _scenePathHash = scenePathHash; - } - } - - private bool IsEditingInPrefabMode() - { - if (EditorUtility.IsPersistent(this)) - { - // if the game object is stored on disk, it is a prefab of some kind, despite not returning true for IsPartOfPrefabAsset =/ - return true; - } - else - { - // If the GameObject is not persistent let's determine which stage we are in first because getting Prefab info depends on it - StageHandle mainStage = StageUtility.GetMainStageHandle(); - StageHandle currentStage = StageUtility.GetStageHandle(gameObject); - if (currentStage != mainStage) - { - var prefabStage = PrefabStageUtility.GetPrefabStage(gameObject); - if (prefabStage != null) - { - return true; - } - } - } - return false; - - } - - /// - /// Returns if the Id used is a sceneId already belonging to another object. - /// - /// - /// - private bool IsDuplicateSceneId(ulong id) - { - //Find all nobs in scene. - _sceneNetworkObjects = GameObject.FindObjectsOfType().ToList(); - foreach (NetworkObject nob in _sceneNetworkObjects) - { - if (nob != null && nob != this && nob.SceneId == id) - return true; - } - //If here all checks pass. - return false; - } - - private void ReferenceIds_OnValidate() - { - TryCreateSceneID(); - } - private void ReferenceIds_Reset() - { - TryCreateSceneID(); - } -#endif - } - -} - diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.ReferenceIds.cs.meta b/Assets/FishNet/Runtime/Object/NetworkObject.ReferenceIds.cs.meta deleted file mode 100644 index 8858eee..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.ReferenceIds.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: be0a4b0a32b02f64495ba3b1d22f89c4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.RpcLinks.cs b/Assets/FishNet/Runtime/Object/NetworkObject.RpcLinks.cs deleted file mode 100644 index 2d2269a..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.RpcLinks.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.Object -{ - public sealed partial class NetworkObject : MonoBehaviour - { - - #region Private. - /// - /// RpcLinks being used within this NetworkObject. - /// - private List _rpcLinkIndexes; - #endregion - - /// - /// Sets rpcLinkIndexes to values. - /// - internal void SetRpcLinkIndexes(List values) - { - _rpcLinkIndexes = values; - } - - /// - /// Removes used link indexes from ClientObjects. - /// - internal void RemoveClientRpcLinkIndexes() - { - NetworkManager.ClientManager.Objects.RemoveLinkIndexes(_rpcLinkIndexes); - } - } - -} - diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.RpcLinks.cs.meta b/Assets/FishNet/Runtime/Object/NetworkObject.RpcLinks.cs.meta deleted file mode 100644 index d7142a8..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.RpcLinks.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8b2f6927cf3ef254d91b89e5f99a92b9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.SyncTypes.cs b/Assets/FishNet/Runtime/Object/NetworkObject.SyncTypes.cs deleted file mode 100644 index 3a3e028..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.SyncTypes.cs +++ /dev/null @@ -1,25 +0,0 @@ -using UnityEngine; - -namespace FishNet.Object -{ - public sealed partial class NetworkObject : MonoBehaviour - { - /// - /// Writers dirty SyncTypes for all Networkbehaviours if their write tick has been met. - /// - internal void WriteDirtySyncTypes() - { - NetworkBehaviour[] nbs = NetworkBehaviours; - int count = nbs.Length; - for (int i = 0; i < count; i++) - { - //There was a null check here before, shouldn't be needed so it was removed. - NetworkBehaviour nb = nbs[i]; - nb.WriteDirtySyncTypes(true, true); - nb.WriteDirtySyncTypes(false, true); - } - } - } - -} - diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.SyncTypes.cs.meta b/Assets/FishNet/Runtime/Object/NetworkObject.SyncTypes.cs.meta deleted file mode 100644 index a50da6e..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.SyncTypes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8ffb07b7ea3c5b4419dc5f9941b2d204 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.cs b/Assets/FishNet/Runtime/Object/NetworkObject.cs deleted file mode 100644 index 22447ff..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.cs +++ /dev/null @@ -1,862 +0,0 @@ -using FishNet.Managing; -using FishNet.Connection; -using UnityEngine; -using FishNet.Serializing; -using FishNet.Transporting; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using FishNet.Utility.Performance; -using System; -using FishNet.Managing.Object; -using FishNet.Component.Ownership; -#if UNITY_EDITOR -using UnityEditor; -#endif - -namespace FishNet.Object -{ - [DisallowMultipleComponent] - public sealed partial class NetworkObject : MonoBehaviour - { - #region Public. - /// - /// True if was nested during scene setup or within a prefab. - /// - [field: SerializeField, HideInInspector] - public bool IsNested { get; private set; } - /// - /// NetworkConnection which predicted spawned this object. - /// - public NetworkConnection PredictedSpawner { get; private set; } = NetworkManager.EmptyConnection; - /// - /// True if this NetworkObject was active during edit. Will be true if placed in scene during edit, and was in active state on run. - /// - [System.NonSerialized] - internal bool ActiveDuringEdit; - /// - /// Returns if this object was placed in the scene during edit-time. - /// - /// - public bool IsSceneObject => (SceneId > 0); - /// - /// ComponentIndex for this NetworkBehaviour. - /// - [field: SerializeField, HideInInspector] - public byte ComponentIndex { get; private set; } - /// - /// Unique Id for this NetworkObject. This does not represent the object owner. - /// - public int ObjectId { get; private set; } - /// - /// True if this NetworkObject is deinitializing. Will also be true until Initialize is called. May be false until the object is cleaned up if object is destroyed without using Despawn. - /// - internal bool IsDeinitializing { get; private set; } = true; - /// - /// PredictedSpawn component on this object. Will be null if not added manually. - /// - [field: SerializeField, HideInInspector] - public PredictedSpawn PredictedSpawn { get; private set; } - /// - /// - /// - [field: SerializeField, HideInInspector] - private NetworkBehaviour[] _networkBehaviours; - /// - /// NetworkBehaviours within the root and children of this object. - /// - public NetworkBehaviour[] NetworkBehaviours - { - get => _networkBehaviours; - private set => _networkBehaviours = value; - } - /// - /// NetworkObject parenting this instance. The parent NetworkObject will be null if there was no parent during serialization. - /// - [field: SerializeField, HideInInspector] - public NetworkObject ParentNetworkObject { get; private set; } - /// - /// NetworkObjects nested beneath this one. Recursive NetworkObjects may exist within each entry of this field. - /// - [field: SerializeField, HideInInspector] - public List ChildNetworkObjects { get; private set; } = new List(); - /// - /// - /// - [SerializeField, HideInInspector] - internal TransformProperties SerializedTransformProperties = new TransformProperties(); - /// - /// Current state of the NetworkObject. - /// - [System.NonSerialized] - internal NetworkObjectState State = NetworkObjectState.Unset; - #endregion - - #region Serialized. - /// - /// True if the object will always initialize as a networked object. When false the object will not automatically initialize over the network. Using Spawn() on an object will always set that instance as networked. - /// - public bool IsNetworked - { - get => _isNetworked; - private set => _isNetworked = value; - } - /// - /// Sets IsNetworked value. This method must be called before Start. - /// - /// New IsNetworked value. - public void SetIsNetworked(bool value) - { - IsNetworked = value; - } - [Tooltip("True if the object will always initialize as a networked object. When false the object will not automatically initialize over the network. Using Spawn() on an object will always set that instance as networked.")] - [SerializeField] - private bool _isNetworked = true; - /// - /// True to make this object global, and added to the DontDestroyOnLoad scene. This value may only be set for instantiated objects, and can be changed if done immediately after instantiating. - /// - public bool IsGlobal - { - get => _isGlobal; - private set => _isGlobal = value; - } - /// - /// Sets IsGlobal value. - /// - /// New global value. - public void SetIsGlobal(bool value) - { - if (IsNested) - { - NetworkManager.StaticLogWarning($"Object {gameObject.name} cannot change IsGlobal because it is nested. Only root objects may be set global."); - return; - } - if (!IsDeinitializing) - { - NetworkManager.StaticLogWarning($"Object {gameObject.name} cannot change IsGlobal as it's already initialized. IsGlobal may only be changed immediately after instantiating."); - return; - } - if (IsSceneObject) - { - NetworkManager.StaticLogWarning($"Object {gameObject.name} cannot have be global because it is a scene object. Only instantiated objects may be global."); - return; - } - - _networkObserverInitiliazed = false; - IsGlobal = value; - } - [Tooltip("True to make this object global, and added to the DontDestroyOnLoad scene. This value may only be set for instantiated objects, and can be changed if done immediately after instantiating.")] - [SerializeField] - private bool _isGlobal; - /// - /// Order to initialize this object's callbacks when spawned with other NetworkObjects in the same tick. Default value is 0, negative values will execute callbacks first. - /// - public sbyte GetInitializeOrder() => _initializeOrder; - [Tooltip("Order to initialize this object's callbacks when spawned with other NetworkObjects in the same tick. Default value is 0, negative values will execute callbacks first.")] - [SerializeField] - private sbyte _initializeOrder = 0; - /// - /// How to handle this object when it despawns. Scene objects are never destroyed when despawning. - /// - [SerializeField] - [Tooltip("How to handle this object when it despawns. Scene objects are never destroyed when despawning.")] - private DespawnType _defaultDespawnType = DespawnType.Destroy; - /// - /// True to use configured ObjectPool rather than destroy this NetworkObject when being despawned. Scene objects are never destroyed. - /// - public DespawnType GetDefaultDespawnType() => _defaultDespawnType; - /// - /// Sets DespawnType value. - /// - /// Default despawn type for this NetworkObject. - public void SetDefaultDespawnType(DespawnType despawnType) - { - _defaultDespawnType = despawnType; - } - #endregion - - #region Private. - /// - /// True if disabled NetworkBehaviours have been initialized. - /// - private bool _disabledNetworkBehavioursInitialized; - #endregion - - #region Const. - /// - /// Value used when the ObjectId has not been set. - /// - public const int UNSET_OBJECTID_VALUE = ushort.MaxValue; - /// - /// Value used when the PrefabId has not been set. - /// - public const int UNSET_PREFABID_VALUE = ushort.MaxValue; - #endregion - - #region Editor Debug. -#if UNITY_EDITOR - private int _editorOwnerId; -#endif - #endregion - - private void Awake() - { - SetChildDespawnedState(); - } - - private void Start() - { - TryStartDeactivation(); - } - - /// - /// Initializes NetworkBehaviours if they are disabled. - /// - private void InitializeNetworkBehavioursIfDisabled() - { - if (_disabledNetworkBehavioursInitialized) - return; - _disabledNetworkBehavioursInitialized = true; - - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].InitializeIfDisabled(); - } - - /// - /// Sets Despawned on child NetworkObjects if they are not enabled. - /// - private void SetChildDespawnedState() - { - NetworkObject nob; - for (int i = 0; i < ChildNetworkObjects.Count; i++) - { - nob = ChildNetworkObjects[i]; - if (!nob.gameObject.activeSelf) - nob.State = NetworkObjectState.Despawned; - } - } - - /// - /// Deactivates this NetworkObject during it's start cycle if conditions are met. - /// - internal void TryStartDeactivation() - { - if (!IsNetworked) - return; - - //Global. - if (IsGlobal && !IsSceneObject) - DontDestroyOnLoad(gameObject); - - if (NetworkManager == null || (!NetworkManager.IsClient && !NetworkManager.IsServer)) - { - //ActiveDuringEdit is only used for scene objects. - if (IsSceneObject) - ActiveDuringEdit = true; - gameObject.SetActive(false); - } - } - - private void OnDisable() - { - /* If deinitializing and an owner exist - * then remove object from owner. */ - if (IsDeinitializing && Owner.IsValid) - Owner.RemoveObject(this); - /* If not nested then check to despawn this OnDisable. - * A nob may become disabled without being despawned if it's - * beneath another deinitializing nob. This can be true even while - * not nested because users may move a nob under another at runtime. - * - * This object must also be activeSelf, meaning that it became disabled - * because a parent was. If not activeSelf then it's possible the - * user simply deactivated the object themselves. */ - else if (IsServer && !IsNested && gameObject.activeSelf) - { - bool canDespawn = false; - Transform nextParent = transform.parent; - while (nextParent != null) - { - if (nextParent.TryGetComponent(out NetworkObject pNob)) - { - /* If pNob is not the same as ParentNetworkObject - * then that means this object was moved around. It could be - * that this was previously a child of something else - * or that was given a parent later on in it's life cycle. - ^ - * When this occurs do not send a despawn for this object. - * Rather, let it destroy from unity callbacks which will force - * the proper destroy/stop cycle. */ - if (pNob != ParentNetworkObject) - break; - //If nob is deinitialized then this one cannot exist. - if (pNob.IsDeinitializing) - { - canDespawn = true; - break; - } - } - nextParent = nextParent.parent; - } - - if (canDespawn) - Despawn(); - } - } - - private void OnDestroy() - { - //Does this need to be here? I'm thinking no, remove it and examine later. //todo - if (Owner.IsValid) - Owner.RemoveObject(this); - //Already being deinitialized by FishNet. - if (IsDeinitializing) - return; - - if (NetworkManager != null) - { - //Was destroyed without going through the proper methods. - if (NetworkManager.IsServer) - NetworkManager.ServerManager.Objects.NetworkObjectUnexpectedlyDestroyed(this, true); - if (NetworkManager.IsClient) - NetworkManager.ClientManager.Objects.NetworkObjectUnexpectedlyDestroyed(this, false); - } - - /* When destroyed unexpectedly it's - * impossible to know if this occurred on - * the server or client side, so send callbacks - * for both. */ - if (IsServer) - InvokeStopCallbacks(true); - if (IsClient) - InvokeStopCallbacks(false); - - /* If owner exist then remove object from owner. - * This has to be called here as well OnDisable because - * the OnDisable will only remove the object if - * deinitializing. This is because the object shouldn't - * be removed from owner if the object is simply being - * disabled, but not deinitialized. But in the scenario - * the object is unexpectedly destroyed, which is how we - * arrive here, the object needs to be removed from owner. */ - if (Owner.IsValid) - Owner.RemoveObject(this); - - Observers.Clear(); - IsDeinitializing = true; - - SetActiveStatus(false); - //Do not need to set state if being destroyed. - //Don't need to reset sync types if object is being destroyed. - } - - /// - /// Sets IsClient or IsServer to isActive. - /// - private void SetActiveStatus(bool isActive, bool server) - { - if (server) - IsServer = isActive; - else - IsClient = isActive; - } - /// - /// Sets IsClient and IsServer to isActive. - /// - private void SetActiveStatus(bool isActive) - { - IsServer = isActive; - IsClient = isActive; - } - /// - /// Initializes this script. This is only called once even when as host. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void Preinitialize_Internal(NetworkManager networkManager, int objectId, NetworkConnection owner, bool asServer) - { - State = NetworkObjectState.Spawned; - InitializeNetworkBehavioursIfDisabled(); - IsDeinitializing = false; - //QOL references. - NetworkManager = networkManager; - ServerManager = networkManager.ServerManager; - ClientManager = networkManager.ClientManager; - ObserverManager = networkManager.ObserverManager; - TransportManager = networkManager.TransportManager; - TimeManager = networkManager.TimeManager; - SceneManager = networkManager.SceneManager; - PredictionManager = networkManager.PredictionManager; - RollbackManager = networkManager.RollbackManager; - - SetOwner(owner); - ObjectId = objectId; - - /* This must be called at the beginning - * so that all conditions are handled by the observer - * manager prior to the preinitialize call on networkobserver. - * The method called is dependent on NetworkManager being set. */ - AddDefaultNetworkObserverConditions(); - - for (int i = 0; i < NetworkBehaviours.Length; i++) - NetworkBehaviours[i].InitializeOnce_Internal(); - - /* NetworkObserver uses some information from - * NetworkBehaviour so it must be preinitialized - * after NetworkBehaviours are. */ - if (asServer) - NetworkObserver.PreInitialize(this); - _networkObserverInitiliazed = true; - - //Add to connection objects if owner exist. - if (owner != null) - owner.AddObject(this); - } - - /// - /// Adds a NetworkBehaviour and serializes it's components. - /// - internal T AddAndSerialize() where T : NetworkBehaviour //runtimeNB make public. - { - int startingLength = NetworkBehaviours.Length; - T result = gameObject.AddComponent(); - //Add to network behaviours. - Array.Resize(ref _networkBehaviours, startingLength + 1); - _networkBehaviours[startingLength] = result; - //Serialize values and return. - result.SerializeComponents(this, (byte)startingLength); - return result; - } - - /// - /// Updates NetworkBehaviours and initializes them with serialized values. - /// - /// True if this call originated from a prefab collection, such as during it's initialization. - internal void UpdateNetworkBehaviours(NetworkObject parentNob, ref byte componentIndex) //runtimeNB make public. - { - /* This method can be called by the developer initializing prefabs, the prefab collection doing it automatically, - * or when the networkobject is modified or added to an object. - * - * Prefab collections generally contain all prefabs, meaning they will not only call this on the topmost - * networkobject but also each child, as the child would be it's own prefab in the collection. This assumes - * that is, the child is a nested prefab. - * - * Because of this potential a check must be done where if the componentIndex is 0 we must look - * for a networkobject above this one. If there is a networkObject above this one then we know the prefab - * is being initialized individually, not part of a recursive check. In this case exit early - * as the parent would have already resolved the needed information. */ - - //If first componentIndex make sure there's no more than maximum allowed nested nobs. - if (componentIndex == 0) - { - //Not possible for index to be 0 and nested. - if (IsNested) - return; - byte maxNobs = 255; - if (GetComponentsInChildren(true).Length > maxNobs) - { - Debug.LogError($"The number of child NetworkObjects on {gameObject.name} exceeds the maximum of {maxNobs}."); - return; - } - } - - PredictedSpawn = GetComponent(); - ComponentIndex = componentIndex; - ParentNetworkObject = parentNob; - - //Transforms which can be searched for networkbehaviours. - ListCache transformCache = ListCaches.GetTransformCache(); - transformCache.Reset(); - ChildNetworkObjects.Clear(); - - transformCache.AddValue(transform); - for (int z = 0; z < transformCache.Written; z++) - { - Transform currentT = transformCache.Collection[z]; - for (int i = 0; i < currentT.childCount; i++) - { - Transform t = currentT.GetChild(i); - /* If contains a nob then do not add to transformsCache. - * Do add to ChildNetworkObjects so it can be initialized when - * parent is. */ - if (t.TryGetComponent(out NetworkObject childNob)) - { - /* Make sure both objects have the same value for - * IsSceneObject. It's possible the user instantiated - * an object and placed it beneath a scene object - * before the scene initialized. They may also - * add a scene object under an instantiated, even though - * this almost certainly will break things. */ - if (IsSceneObject == childNob.IsSceneObject) - ChildNetworkObjects.Add(childNob); - } - else - { - transformCache.AddValue(t); - } - } - } - - int written; - //Iterate all cached transforms and get networkbehaviours. - ListCache nbCache = ListCaches.GetNetworkBehaviourCache(); - nbCache.Reset(); - written = transformCache.Written; - List ts = transformCache.Collection; - // - for (int i = 0; i < written; i++) - nbCache.AddValues(ts[i].GetNetworkBehaviours()); - - //Copy to array. - written = nbCache.Written; - List nbs = nbCache.Collection; - NetworkBehaviours = new NetworkBehaviour[written]; - // - for (int i = 0; i < written; i++) - { - NetworkBehaviours[i] = nbs[i]; - NetworkBehaviours[i].SerializeComponents(this, (byte)i); - } - - ListCaches.StoreCache(transformCache); - ListCaches.StoreCache(nbCache); - - //Tell children nobs to update their NetworkBehaviours. - foreach (NetworkObject item in ChildNetworkObjects) - { - componentIndex++; - item.UpdateNetworkBehaviours(this, ref componentIndex); - } - } - - /// - /// Called after all data is synchronized with this NetworkObject. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void Initialize(bool asServer, bool invokeSyncTypeCallbacks) - { - InitializeCallbacks(asServer, invokeSyncTypeCallbacks); - } - - /// - /// Called to prepare this object to be destroyed or disabled. - /// - internal void Deinitialize(bool asServer) - { - InvokeStopCallbacks(asServer); - if (asServer) - { - IsDeinitializing = true; - } - else - { - ClientManager.Connection.LevelOfDetails.Remove(this); - //Client only. - if (!NetworkManager.IsServer) - IsDeinitializing = true; - - RemoveClientRpcLinkIndexes(); - } - - SetActiveStatus(false, asServer); - if (asServer) - Observers.Clear(); - } - - /// - /// Resets states for object to be pooled. - /// - /// True if performing as server. - public void ResetForObjectPool() - { - int count = NetworkBehaviours.Length; - for (int i = 0; i < count; i++) - NetworkBehaviours[i].ResetForObjectPool(); - - State = NetworkObjectState.Unset; - SetOwner(NetworkManager.EmptyConnection); - NetworkObserver.Deinitialize(); - //QOL references. - NetworkManager = null; - ServerManager = null; - ClientManager = null; - ObserverManager = null; - TransportManager = null; - TimeManager = null; - SceneManager = null; - RollbackManager = null; - //Misc sets. - ObjectId = 0; - ClientInitialized = false; - } - - /// - /// Removes ownership from all clients. - /// - public void RemoveOwnership() - { - GiveOwnership(null, true); - } - /// - /// Gives ownership to newOwner. - /// - /// - public void GiveOwnership(NetworkConnection newOwner) - { - GiveOwnership(newOwner, true); - } - /// - /// Gives ownership to newOwner. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void GiveOwnership(NetworkConnection newOwner, bool asServer) - { - /* Additional asServer checks. */ - if (asServer) - { - if (!NetworkManager.IsServer) - { - NetworkManager.LogWarning($"Ownership cannot be given for object {gameObject.name}. Only server may give ownership."); - return; - } - - //If the same owner don't bother sending a message, just ignore request. - if (newOwner == Owner && asServer) - return; - - if (newOwner != null && newOwner.IsActive && !newOwner.LoadedStartScenes(true)) - { - NetworkManager.LogWarning($"Ownership has been transfered to ConnectionId {newOwner.ClientId} but this is not recommended until after they have loaded start scenes. You can be notified when a connection loads start scenes by using connection.OnLoadedStartScenes on the connection, or SceneManager.OnClientLoadStartScenes."); - } - } - - bool activeNewOwner = (newOwner != null && newOwner.IsActive); - - //Set prevOwner, disallowing null. - NetworkConnection prevOwner = Owner; - if (prevOwner == null) - prevOwner = NetworkManager.EmptyConnection; - - SetOwner(newOwner); - /* Only modify objects if asServer or not - * host. When host, server would - * have already modified objects - * collection so there is no need - * for client to as well. */ - if (asServer || !NetworkManager.IsHost) - { - if (activeNewOwner) - newOwner.AddObject(this); - if (prevOwner.IsValid && prevOwner != newOwner) - prevOwner.RemoveObject(this); - } - - //After changing owners invoke callbacks. - InvokeOwnership(prevOwner, asServer); - - //If asServer send updates to clients as needed. - if (asServer) - { - if (activeNewOwner) - ServerManager.Objects.RebuildObservers(this, newOwner); - - using (PooledWriter writer = WriterPool.GetWriter()) - { - writer.WritePacketId(PacketId.OwnershipChange); - writer.WriteNetworkObject(this); - writer.WriteNetworkConnection(Owner); - //If sharing then send to all observers. - if (NetworkManager.ServerManager.ShareIds) - { - NetworkManager.TransportManager.SendToClients((byte)Channel.Reliable, writer.GetArraySegment(), this); - } - //Only sending to old / new. - else - { - if (prevOwner.IsActive) - NetworkManager.TransportManager.SendToClient((byte)Channel.Reliable, writer.GetArraySegment(), prevOwner); - if (activeNewOwner) - NetworkManager.TransportManager.SendToClient((byte)Channel.Reliable, writer.GetArraySegment(), newOwner); - } - } - - if (prevOwner.IsActive) - ServerManager.Objects.RebuildObservers(prevOwner); - } - } - - - /// - /// Initializes a predicted object for client. - /// - internal void InitializePredictedObject_Server(NetworkManager manager, NetworkConnection predictedSpawner) - { - NetworkManager = manager; - PredictedSpawner = predictedSpawner; - } - - - /// - /// Initializes a predicted object for client. - /// - internal void PreinitializePredictedObject_Client(NetworkManager manager, int objectId, NetworkConnection owner, NetworkConnection predictedSpawner) - { - PredictedSpawner = predictedSpawner; - Preinitialize_Internal(manager, objectId, owner, false); - } - - /// - /// Deinitializes this predicted spawned object. - /// - internal void DeinitializePredictedObject_Client() - { - /* For the time being we're just going to disable the object because - * deinitializing instead could present a lot of problems. - * For example: if client deinitializes rpc links are unregistered, - * and if server had a rpc on the way already the link would - * not be found. This would cause the reader length to be wrong - * resulting in packet corruption. */ - gameObject.SetActive(false); - } - - /// - /// Sets the owner of this object. - /// - /// - /// - private void SetOwner(NetworkConnection owner) - { - Owner = owner; - } - - /// - /// Returns if this NetworkObject is a scene object, and has changed. - /// - /// - internal ChangedTransformProperties GetTransformChanges(TransformProperties stp) - { - ChangedTransformProperties ctp = ChangedTransformProperties.Unset; - if (transform.localPosition != stp.Position) - ctp |= ChangedTransformProperties.LocalPosition; - if (transform.localRotation != stp.Rotation) - ctp |= ChangedTransformProperties.LocalRotation; - if (transform.localScale != stp.LocalScale) - ctp |= ChangedTransformProperties.LocalScale; - - return ctp; - } - - /// - /// Returns if this NetworkObject is a scene object, and has changed. - /// - /// - internal ChangedTransformProperties GetTransformChanges(GameObject prefab) - { - Transform t = prefab.transform; - ChangedTransformProperties ctp = ChangedTransformProperties.Unset; - if (transform.position != t.position) - ctp |= ChangedTransformProperties.LocalPosition; - if (transform.rotation != t.rotation) - ctp |= ChangedTransformProperties.LocalRotation; - if (transform.localScale != t.localScale) - ctp |= ChangedTransformProperties.LocalScale; - - return ctp; - } - - #region Editor. -#if UNITY_EDITOR - /// - /// Removes duplicate NetworkObject components on this object returning the removed count. - /// - /// - internal int RemoveDuplicateNetworkObjects() - { - NetworkObject[] nobs = GetComponents(); - for (int i = 1; i < nobs.Length; i++) - DestroyImmediate(nobs[i]); - - return (nobs.Length - 1); - } - - /// - /// Sets IsNested and returns the result. - /// - /// - private bool SetIsNestedThroughTraversal() - { - Transform parent = transform.parent; - //Iterate long as parent isn't null, and isnt self. - while (parent != null && parent != transform) - { - if (parent.TryGetComponent(out _)) - { - IsNested = true; - return IsNested; - } - - parent = parent.parent; - } - - //No NetworkObject found in parents, meaning this is not nested. - IsNested = false; - return IsNested; - } - - private void OnValidate() - { - SetIsNestedThroughTraversal(); - SceneUpdateNetworkBehaviours(); - ReferenceIds_OnValidate(); - - if (IsGlobal && IsSceneObject) - Debug.LogWarning($"Object {gameObject.name} will have it's IsGlobal state ignored because it is a scene object. Instantiated copies will still be global. This warning is informative only."); - } - - private void Reset() - { - SetIsNestedThroughTraversal(); - SerializeTransformProperties(); - SceneUpdateNetworkBehaviours(); - ReferenceIds_Reset(); - } - - private void SceneUpdateNetworkBehaviours() - { - //In a scene. - if (!string.IsNullOrEmpty(gameObject.scene.name)) - { - if (IsNested) - return; - - byte componentIndex = 0; - UpdateNetworkBehaviours(null, ref componentIndex); - } - - } - private void OnDrawGizmosSelected() - { - _editorOwnerId = (Owner == null) ? -1 : Owner.ClientId; - SerializeTransformProperties(); - } - - /// - /// Serializes TransformProperties to current transform properties. - /// - private void SerializeTransformProperties() - { - /* Use this method to set scene data since it doesn't need to exist outside - * the editor and because its updated regularly while selected. */ - //If a scene object. - if (!EditorApplication.isPlaying && !string.IsNullOrEmpty(gameObject.scene.name)) - { - SerializedTransformProperties = new TransformProperties( - transform.localPosition, transform.localRotation, transform.localScale); - } - } -#endif - #endregion - } - -} - diff --git a/Assets/FishNet/Runtime/Object/NetworkObject.cs.meta b/Assets/FishNet/Runtime/Object/NetworkObject.cs.meta deleted file mode 100644 index 228ed52..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObject.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 26b716c41e9b56b4baafaf13a523ba2e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/NetworkObjectState.cs b/Assets/FishNet/Runtime/Object/NetworkObjectState.cs deleted file mode 100644 index 0b0b6d1..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObjectState.cs +++ /dev/null @@ -1,24 +0,0 @@ - -namespace FishNet.Object -{ - /// - /// Current state of the NetworkObject. - /// - internal enum NetworkObjectState : byte - { - /// - /// State has not been set. This occurs when the object has never been spawned or despawned. - /// - Unset = 0, - /// - /// Object is currently spawned. - /// - Spawned = 1, - /// - /// Object is currently despawned. - /// - Despawned = 2, - } - -} - diff --git a/Assets/FishNet/Runtime/Object/NetworkObjectState.cs.meta b/Assets/FishNet/Runtime/Object/NetworkObjectState.cs.meta deleted file mode 100644 index 1873ca3..0000000 --- a/Assets/FishNet/Runtime/Object/NetworkObjectState.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 536f137f11dc6654eab9fbe94ca14cd8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/PredictedSpawningType.cs b/Assets/FishNet/Runtime/Object/PredictedSpawningType.cs deleted file mode 100644 index 43ad004..0000000 --- a/Assets/FishNet/Runtime/Object/PredictedSpawningType.cs +++ /dev/null @@ -1,14 +0,0 @@ -using FishNet.Object.Helping; - -namespace FishNet.Object -{ - [System.Flags] - public enum PredictedSpawningType : byte - { - Disabled = 0, - Spawn = 1, - Despawn = 2, - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/PredictedSpawningType.cs.meta b/Assets/FishNet/Runtime/Object/PredictedSpawningType.cs.meta deleted file mode 100644 index 59f8d22..0000000 --- a/Assets/FishNet/Runtime/Object/PredictedSpawningType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a4b112cfcb8cd57429eb0a4a32c5a774 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Prediction.meta b/Assets/FishNet/Runtime/Object/Prediction.meta deleted file mode 100644 index a673566..0000000 --- a/Assets/FishNet/Runtime/Object/Prediction.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 8bce6e27e176a2d4d91783beffe40ac2 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Prediction/Attributes.cs b/Assets/FishNet/Runtime/Object/Prediction/Attributes.cs deleted file mode 100644 index f3d355c..0000000 --- a/Assets/FishNet/Runtime/Object/Prediction/Attributes.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; - -namespace FishNet.Object.Prediction -{ - /// - /// Replicated methods are to be called from clients and will run the same data and logic on the server. - /// Only data used as method arguments will be serialized. - /// - [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)] - public class ReplicateAttribute : Attribute - { - /// - /// How many past datas to resend. - /// - public byte Resends = 5; - } - /// - /// Reconcile methods indicate how to reset your script or object after the server has replicated user data. - /// - [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)] - public class ReconcileAttribute : Attribute - { - /// - /// How many times to resend reconcile. - /// - public byte Resends = 3; - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/Prediction/Attributes.cs.meta b/Assets/FishNet/Runtime/Object/Prediction/Attributes.cs.meta deleted file mode 100644 index fdd81b7..0000000 --- a/Assets/FishNet/Runtime/Object/Prediction/Attributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b082d36535ce0404d8438bc1b0499e53 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Prediction/Delegates.cs b/Assets/FishNet/Runtime/Object/Prediction/Delegates.cs deleted file mode 100644 index 4b884c5..0000000 --- a/Assets/FishNet/Runtime/Object/Prediction/Delegates.cs +++ /dev/null @@ -1,20 +0,0 @@ -using FishNet.Connection; -using FishNet.Documenting; -using FishNet.Serializing; -using FishNet.Transporting; -using FishNet.Utility.Constant; -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo(UtilityConstants.CODEGEN_ASSEMBLY_NAME)] -namespace FishNet.Object.Prediction.Delegating -{ - [APIExclude] - public delegate void ReplicateRpcDelegate(PooledReader reader, NetworkConnection sender, Channel channel); - [APIExclude] - public delegate void ReconcileRpcDelegate(PooledReader reader, Channel channel); - - [APIExclude] - public delegate void ReplicateUserLogicDelegate(T data, bool asServer, Channel channel, bool replaying); - [APIExclude] - public delegate void ReconcileUserLogicDelegate(T data, bool asServer, Channel channel); -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/Prediction/Delegates.cs.meta b/Assets/FishNet/Runtime/Object/Prediction/Delegates.cs.meta deleted file mode 100644 index d3c53db..0000000 --- a/Assets/FishNet/Runtime/Object/Prediction/Delegates.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c9904192dacd41a4ba7b29bc3199ec3a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Prediction/Interfaces.cs b/Assets/FishNet/Runtime/Object/Prediction/Interfaces.cs deleted file mode 100644 index 6c9cb31..0000000 --- a/Assets/FishNet/Runtime/Object/Prediction/Interfaces.cs +++ /dev/null @@ -1,18 +0,0 @@ - -namespace FishNet.Object.Prediction -{ - public interface IReplicateData - { - uint GetTick(); - void SetTick(uint value); - void Dispose(); - } - - public interface IReconcileData - { - uint GetTick(); - void SetTick(uint value); - void Dispose(); - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/Prediction/Interfaces.cs.meta b/Assets/FishNet/Runtime/Object/Prediction/Interfaces.cs.meta deleted file mode 100644 index 24909d5..0000000 --- a/Assets/FishNet/Runtime/Object/Prediction/Interfaces.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 515754257f85574438408c7f5b268590 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/RpcLinkType.cs b/Assets/FishNet/Runtime/Object/RpcLinkType.cs deleted file mode 100644 index 84f89f4..0000000 --- a/Assets/FishNet/Runtime/Object/RpcLinkType.cs +++ /dev/null @@ -1,25 +0,0 @@ -using FishNet.Object.Helping; - -namespace FishNet.Object -{ - - - internal struct RpcLinkType - { - /// - /// Index of link. - /// - public ushort LinkIndex; - /// - /// Type of Rpc link is for. - /// - public RpcType RpcType; - - public RpcLinkType(ushort linkIndex, RpcType rpcType) - { - LinkIndex = linkIndex; - RpcType = rpcType; - } - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/RpcLinkType.cs.meta b/Assets/FishNet/Runtime/Object/RpcLinkType.cs.meta deleted file mode 100644 index 3781ab0..0000000 --- a/Assets/FishNet/Runtime/Object/RpcLinkType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4fa68ca6a21d08f42980dcf68f984d53 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/SyncTypeWriteType.cs b/Assets/FishNet/Runtime/Object/SyncTypeWriteType.cs deleted file mode 100644 index c5c68b9..0000000 --- a/Assets/FishNet/Runtime/Object/SyncTypeWriteType.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace FishNet.Object -{ - - internal enum SyncTypeWriteType - { - Observers = 0, - Owner = 1, - All = 2, - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/SyncTypeWriteType.cs.meta b/Assets/FishNet/Runtime/Object/SyncTypeWriteType.cs.meta deleted file mode 100644 index 2d119c2..0000000 --- a/Assets/FishNet/Runtime/Object/SyncTypeWriteType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e6406cc7d5fe47c44a26298145f54b00 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing.meta b/Assets/FishNet/Runtime/Object/Synchronizing.meta deleted file mode 100644 index fd7d57a..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 340de3ebc97a18642be780cbfeda01dc -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/ICustomSync.cs b/Assets/FishNet/Runtime/Object/Synchronizing/ICustomSync.cs deleted file mode 100644 index 71ed36b..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/ICustomSync.cs +++ /dev/null @@ -1,19 +0,0 @@ - -namespace FishNet.Object.Synchronizing -{ - /// - /// Custom SyncObjects must inherit from SyncBase and implement this interface. - /// - public interface ICustomSync - { - /// - /// Get the serialized type. - /// This must return the value type you are synchronizing, for example a struct or class. - /// If you are not synchronizing a particular value but instead of supported values such as int, bool, ect, then you may return null on this method. - /// - /// - object GetSerializedType(); - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/ICustomSync.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/ICustomSync.cs.meta deleted file mode 100644 index 7789232..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/ICustomSync.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2024b0be0cd1cc744a442f3e2e6ba483 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/ISyncObject.cs b/Assets/FishNet/Runtime/Object/Synchronizing/ISyncObject.cs deleted file mode 100644 index 9356bbd..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/ISyncObject.cs +++ /dev/null @@ -1,48 +0,0 @@ -using FishNet.Managing; -using FishNet.Serializing; -using System; - -namespace FishNet.Object.Synchronizing.Internal -{ - /// - /// A sync object is an object that can synchronize it's state - /// between server and client, such as a SyncList - /// - public interface ISyncType - { - /// - /// true if there are changes since the last flush - /// - bool IsDirty { get; } - /// - /// Sets index for the SyncType. - /// - void SetRegistered(); - /// - /// PreInitializes this for use with the network. - /// - void PreInitialize(NetworkManager networkManager); - /// - /// Writes all changed values. - /// - /// - ///True to set the next time data may sync. - void WriteDelta(PooledWriter writer, bool resetSyncTick = true); - /// - /// Writers all values if not initial values. - /// - /// - void WriteFull(PooledWriter writer); - /// - /// Sets current values. - /// - /// - void Read(PooledReader reader); - /// - /// Resets the SyncObject so that it can be re-used - /// - void Reset(); - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/ISyncObject.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/ISyncObject.cs.meta deleted file mode 100644 index e353a5a..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/ISyncObject.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9d0e81c03149ecd4eba926bba2d0edbe -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/MissingObjectPacketLength.cs b/Assets/FishNet/Runtime/Object/Synchronizing/MissingObjectPacketLength.cs deleted file mode 100644 index 56e0d3d..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/MissingObjectPacketLength.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace FishNet.Object -{ - - internal enum MissingObjectPacketLength : int - { - Reliable = -1, - PurgeRemaiming = -2, - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/MissingObjectPacketLength.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/MissingObjectPacketLength.cs.meta deleted file mode 100644 index 68a542f..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/MissingObjectPacketLength.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3d177496f9519e246b8e3ef199d83437 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/ReadPermissions.cs b/Assets/FishNet/Runtime/Object/Synchronizing/ReadPermissions.cs deleted file mode 100644 index 73c2afd..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/ReadPermissions.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace FishNet.Object.Synchronizing -{ - /// - /// Which clients may receive synchronization updates. - /// - public enum ReadPermission : byte - { - /// - /// All observers will receive updates. - /// - Observers, - /// - /// Only owner will receive updates. - /// - OwnerOnly, - /// - /// Send to all observers except owner. - /// - ExcludeOwner - } -} diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/ReadPermissions.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/ReadPermissions.cs.meta deleted file mode 100644 index e123b96..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/ReadPermissions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8050ef114e01f74409d8e29b821b6fc0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SecretMenu.meta b/Assets/FishNet/Runtime/Object/Synchronizing/SecretMenu.meta deleted file mode 100644 index 28aeb41..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SecretMenu.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 8c38d8297956cf34c9826ebe5fbadff6 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SecretMenu/SyncVarExtensions.cs b/Assets/FishNet/Runtime/Object/Synchronizing/SecretMenu/SyncVarExtensions.cs deleted file mode 100644 index b318742..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SecretMenu/SyncVarExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -//using FishNet.Documenting; - -//Remove on 2023/06/01 -//namespace FishNet.Object.Synchronizing.SecretMenu -//{ -// /// -// /// Internal SyncVar extensions. -// /// -// [APIExclude] -// public static class SyncVarExtensions -// { -// /// -// /// Dirties SyncVars. -// /// -// /// -// [APIExclude] -// public static void Dirty(this object obj) { } -// } - - -//} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SecretMenu/SyncVarExtensions.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/SecretMenu/SyncVarExtensions.cs.meta deleted file mode 100644 index aa9b282..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SecretMenu/SyncVarExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d1f982cd721eb344c88bab105d779127 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/Settings.cs b/Assets/FishNet/Runtime/Object/Synchronizing/Settings.cs deleted file mode 100644 index 5f610bd..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/Settings.cs +++ /dev/null @@ -1,53 +0,0 @@ -using FishNet.Transporting; - -namespace FishNet.Object.Synchronizing.Internal -{ - public class Settings - { - /// - /// Defines the write permissions for this var - /// - public WritePermission WritePermission = WritePermission.ServerOnly; - /// - /// Clients which may receive updated values. - /// - public ReadPermission ReadPermission = ReadPermission.Observers; - /// - /// How often this variable may synchronize. - /// - public float SendRate = 0f; - /// - /// Channel to send values on. - /// - public Channel Channel = Channel.Reliable; - - /// - /// Constructs a new NetworkedVarSettings instance - /// - public Settings() - { - - } - - public Settings(WritePermission writePermission, ReadPermission readPermission, float sendRate, Channel channel) - { - WritePermission = writePermission; - ReadPermission = readPermission; - SendRate = sendRate; - Channel = channel; - } - - public Settings(float sendTickrate) - { - SendRate = sendTickrate; - } - - public Settings(ReadPermission readPermission, float sendRate, Channel channel) - { - ReadPermission = readPermission; - SendRate = sendRate; - Channel = channel; - } - - } -} diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/Settings.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/Settings.cs.meta deleted file mode 100644 index 2492a21..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/Settings.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 24688925098da4d42be8dbfa66b88b82 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncBase.cs b/Assets/FishNet/Runtime/Object/Synchronizing/SyncBase.cs deleted file mode 100644 index 7dc53f5..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncBase.cs +++ /dev/null @@ -1,265 +0,0 @@ -using FishNet.Managing; -using FishNet.Managing.Timing; -using FishNet.Serializing; -using FishNet.Transporting; -using System; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Object.Synchronizing.Internal -{ - public class SyncBase : ISyncType - { - - #region Public. - /// - /// True if this SyncBase has been registered within it's containing class. - /// - public bool IsRegistered { get; private set; } - /// - /// True if the object for which this SyncType is for has been initialized for the network. - /// - public bool IsNetworkInitialized => (IsRegistered && (NetworkBehaviour.IsServer || NetworkBehaviour.IsClient)); - /// - /// True if a SyncObject, false if a SyncVar. - /// - public bool IsSyncObject { get; private set; } - /// - /// The settings for this SyncVar. - /// - public Settings Settings = new Settings(); - /// - /// How often updates may send. - /// - public float SendRate => Settings.SendRate; - /// - /// True if this SyncVar needs to send data. - /// - public bool IsDirty { get; private set; } - /// - /// NetworkManager this uses. - /// - public NetworkManager NetworkManager = null; - /// - /// NetworkBehaviour this SyncVar belongs to. - /// - public NetworkBehaviour NetworkBehaviour = null; - /// - /// Next time a SyncVar may send data/ - /// - public uint NextSyncTick = 0; - /// - /// Index within the sync collection. - /// - public uint SyncIndex { get; protected set; } = 0; - /// - /// Channel to send on. - /// - internal Channel Channel => _currentChannel; - #endregion - - #region Private. - /// - /// Sync interval converted to ticks. - /// - private uint _timeToTicks; - /// - /// Channel to use for next write. To ensure eventual consistency this eventually changes to reliable when Settings are unreliable. - /// - private Channel _currentChannel; - #endregion - - /// - /// Initializes this SyncBase. - /// - public void InitializeInstance(NetworkBehaviour nb, uint syncIndex, WritePermission writePermissions, ReadPermission readPermissions, float tickRate, Channel channel, bool isSyncObject) - { - NetworkBehaviour = nb; - SyncIndex = syncIndex; - _currentChannel = channel; - IsSyncObject = isSyncObject; - Settings = new Settings() - { - WritePermission = writePermissions, - ReadPermission = readPermissions, - SendRate = tickRate, - Channel = channel - }; - - NetworkBehaviour.RegisterSyncType(this, SyncIndex); - } - - /// - /// Sets the SyncIndex. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SetRegistered() - { - Registered(); - } - - /// - /// Called when the SyncType has been registered, but not yet initialized over the network. - /// - protected virtual void Registered() - { - IsRegistered = true; - } - - /// - /// PreInitializes this for use with the network. - /// - public void PreInitialize(NetworkManager networkManager) - { - NetworkManager = networkManager; - if (Settings.SendRate < 0f) - Settings.SendRate = networkManager.ServerManager.GetSynctypeRate(); - - _timeToTicks = NetworkManager.TimeManager.TimeToTicks(Settings.SendRate, TickRounding.RoundUp); - } - - /// - /// Called after OnStartXXXX has occurred. - /// - /// True if OnStartServer was called, false if OnStartClient. - public virtual void OnStartCallback(bool asServer) { } - - protected bool CanNetworkSetValues(bool warn = true) - { - /* If not registered then values can be set - * since at this point the object is still being initialized - * in awake so we want those values to be applied. */ - if (!IsRegistered) - return true; - /* If the network is not initialized yet then let - * values be set. Values set here will not synchronize - * to the network. We are assuming the user is setting - * these values on client and server appropriately - * since they are being applied prior to this object - * being networked. */ - if (!IsNetworkInitialized) - return true; - //If server is active then values can be set no matter what. - if (NetworkBehaviour.IsServer) - return true; - //Predicted spawning is enabled. - if (NetworkManager != null && NetworkManager.PredictionManager.GetAllowPredictedSpawning() && NetworkBehaviour.NetworkObject.AllowPredictedSpawning) - return true; - /* If here then server is not active and additional - * checks must be performed. */ - bool result = (Settings.ReadPermission == ReadPermission.ExcludeOwner && NetworkBehaviour.IsOwner); - if (!result && warn) - LogServerNotActiveWarning(); - - return result; - } - - /// - /// Logs that the operation could not be completed because the server is not active. - /// - protected void LogServerNotActiveWarning() - { - if (NetworkManager != null) - NetworkManager.LogWarning($"Cannot complete operation as server when server is not active."); - } - - /// - /// Dirties this Sync and the NetworkBehaviour. - /// - public bool Dirty() - { - /* Reset channel even if already dirty. - * This is because the value might have changed - * which will reset the eventual consistency state. */ - _currentChannel = Settings.Channel; - - /* Once dirty don't undirty until it's - * processed. This ensures that data - * is flushed. */ - bool canDirty = NetworkBehaviour.DirtySyncType(IsSyncObject); - IsDirty |= canDirty; - - return canDirty; - } - - /// - /// Sets IsDirty to false. - /// - internal void ResetDirty() - { - //If not a sync object and using unreliable channel. - if (!IsSyncObject && Settings.Channel == Channel.Unreliable) - { - //Check if dirty can be unset or if another tick must be run using reliable. - if (_currentChannel == Channel.Unreliable) - _currentChannel = Channel.Reliable; - //Already sent reliable, can undirty. Channel will reset next time this dirties. - else - IsDirty = false; - } - //If syncObject or using reliable unset dirty. - else - { - IsDirty = false; - } - } - /// - /// True if dirty and enough time has passed to write changes. - /// - /// - /// - internal bool WriteTimeMet(uint tick) - { - return (IsDirty && tick >= NextSyncTick); - } - /// - /// Writes current value. - /// - /// - /// True to set the next time data may sync. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public virtual void WriteDelta(PooledWriter writer, bool resetSyncTick = true) - { - WriteHeader(writer, resetSyncTick); - } - /// - /// Writers the header for this SyncType. - /// - /// - /// - protected virtual void WriteHeader(PooledWriter writer, bool resetSyncTick = true) - { - if (resetSyncTick) - NextSyncTick = NetworkManager.TimeManager.Tick + _timeToTicks; - - writer.WriteByte((byte)SyncIndex); - } - /// - /// Writes current value if not initialized value. - /// - /// - public virtual void WriteFull(PooledWriter writer) { } - /// - /// Sets current value as client. - /// - /// - [Obsolete("Use Read(PooledReader, bool).")] - public virtual void Read(PooledReader reader) { } - /// - /// Sets current value as server or client. - /// - /// - /// - public virtual void Read(PooledReader reader, bool asServer) { } - /// - /// Resets to initialized values. - /// - public virtual void Reset() - { - NextSyncTick = 0; - ResetDirty(); - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncBase.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/SyncBase.cs.meta deleted file mode 100644 index 9fb0dec..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1a6f26e3f8016cc499b3fa99e7368fbc -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionary.cs b/Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionary.cs deleted file mode 100644 index db2c8db..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionary.cs +++ /dev/null @@ -1,628 +0,0 @@ -using FishNet.Documenting; -using FishNet.Managing.Logging; -using FishNet.Object.Synchronizing.Internal; -using FishNet.Serializing; -using FishNet.Utility.Extension; -using JetBrains.Annotations; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Object.Synchronizing -{ - - public class SyncIDictionary : SyncBase, IDictionary, IReadOnlyDictionary - { - - #region Types. - /// - /// Information needed to invoke a callback. - /// - private struct CachedOnChange - { - internal readonly SyncDictionaryOperation Operation; - internal readonly TKey Key; - internal readonly TValue Value; - - public CachedOnChange(SyncDictionaryOperation operation, TKey key, TValue value) - { - Operation = operation; - Key = key; - Value = value; - } - } - - /// - /// Information about how the collection has changed. - /// - private struct ChangeData - { - internal readonly SyncDictionaryOperation Operation; - internal readonly TKey Key; - internal readonly TValue Value; - - public ChangeData(SyncDictionaryOperation operation, TKey key, TValue value) - { - this.Operation = operation; - this.Key = key; - this.Value = value; - } - } - #endregion - - #region Public. - /// - /// Implementation from Dictionary. Not used. - /// - [APIExclude] - public bool IsReadOnly => false; - /// - /// Delegate signature for when SyncDictionary changes. - /// - /// Operation being completed, such as Add, Set, Remove. - /// Key being modified. - /// Value of operation. - /// True if callback is on the server side. False is on the client side. - [APIExclude] - public delegate void SyncDictionaryChanged(SyncDictionaryOperation op, TKey key, TValue value, bool asServer); - /// - /// Called when the SyncDictionary changes. - /// - public event SyncDictionaryChanged OnChange; - /// - /// Collection of objects. - /// - public readonly IDictionary Collection; - /// - /// Copy of objects on client portion when acting as a host. - /// - public readonly IDictionary ClientHostCollection = new Dictionary(); - /// - /// Number of objects in the collection. - /// - public int Count => Collection.Count; - /// - /// Keys within the collection. - /// - public ICollection Keys => Collection.Keys; - [APIExclude] - IEnumerable IReadOnlyDictionary.Keys => Collection.Keys; - /// - /// Values within the collection. - /// - public ICollection Values => Collection.Values; - [APIExclude] - IEnumerable IReadOnlyDictionary.Values => Collection.Values; - #endregion - - #region Private. - /// - /// Initial values for the dictionary. - /// - private IDictionary _initialValues = new Dictionary(); - /// - /// Changed data which will be sent next tick. - /// - private readonly List _changed = new List(); - /// - /// Server OnChange events waiting for start callbacks. - /// - private readonly List _serverOnChanges = new List(); - /// - /// Client OnChange events waiting for start callbacks. - /// - private readonly List _clientOnChanges = new List(); - /// - /// True if values have changed since initialization. - /// The only reasonable way to reset this during a Reset call is by duplicating the original list and setting all values to it on reset. - /// - private bool _valuesChanged; - /// - /// True to send all values in the next WriteDelta. - /// - private bool _sendAll; - #endregion - - [APIExclude] - public SyncIDictionary(IDictionary objects) - { - this.Collection = objects; - //Add to clienthostcollection. - foreach (KeyValuePair item in objects) - this.ClientHostCollection[item.Key] = item.Value; - } - - /// - /// Gets the collection being used within this SyncList. - /// - /// True if returning the server value, false if client value. The values will only differ when running as host. While asServer is true the most current values on server will be returned, and while false the latest values received by client will be returned. - /// The used collection. - public Dictionary GetCollection(bool asServer) - { - bool asClientAndHost = (!asServer && base.NetworkManager.IsServer); - IDictionary collection = (asClientAndHost) ? ClientHostCollection : Collection; - return (collection as Dictionary); - } - - /// - /// Called when the SyncType has been registered, but not yet initialized over the network. - /// - protected override void Registered() - { - base.Registered(); - foreach (KeyValuePair item in Collection) - _initialValues[item.Key] = item.Value; - } - - /// - /// Adds an operation and invokes callback locally. - /// Internal use. - /// May be used for custom SyncObjects. - /// - /// - /// - /// - [APIExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void AddOperation(SyncDictionaryOperation operation, TKey key, TValue value) - { - if (!base.IsRegistered) - return; - - /* asServer might be true if the client is setting the value - * through user code. Typically synctypes can only be set - * by the server, that's why it is assumed asServer via user code. - * However, when excluding owner for the synctype the client should - * have permission to update the value locally for use with - * prediction. */ - bool asServerInvoke = (!base.IsNetworkInitialized || base.NetworkBehaviour.IsServer); - - if (asServerInvoke) - { - _valuesChanged = true; - if (base.Dirty()) - { - ChangeData change = new ChangeData(operation, key, value); - _changed.Add(change); - } - } - - InvokeOnChange(operation, key, value, asServerInvoke); - } - - - /// - /// Called after OnStartXXXX has occurred. - /// - /// True if OnStartServer was called, false if OnStartClient. - public override void OnStartCallback(bool asServer) - { - base.OnStartCallback(asServer); - List collection = (asServer) ? _serverOnChanges : _clientOnChanges; - - if (OnChange != null) - { - foreach (CachedOnChange item in collection) - OnChange.Invoke(item.Operation, item.Key, item.Value, asServer); - } - - collection.Clear(); - } - - - /// - /// Writes all changed values. - /// Internal use. - /// May be used for custom SyncObjects. - /// - /// - ///True to set the next time data may sync. - [APIExclude] - public override void WriteDelta(PooledWriter writer, bool resetSyncTick = true) - { - base.WriteDelta(writer, resetSyncTick); - - //If sending all then clear changed and write full. - if (_sendAll) - { - _sendAll = false; - _changed.Clear(); - WriteFull(writer); - } - else - { - //False for not full write. - writer.WriteBoolean(false); - writer.WriteInt32(_changed.Count); - - for (int i = 0; i < _changed.Count; i++) - { - ChangeData change = _changed[i]; - writer.WriteByte((byte)change.Operation); - - //Clear does not need to write anymore data so it is not included in checks. - if (change.Operation == SyncDictionaryOperation.Add || - change.Operation == SyncDictionaryOperation.Set) - { - writer.Write(change.Key); - writer.Write(change.Value); - } - else if (change.Operation == SyncDictionaryOperation.Remove) - { - writer.Write(change.Key); - } - } - - _changed.Clear(); - } - } - - - /// - /// Writers all values if not initial values. - /// Internal use. - /// May be used for custom SyncObjects. - /// - /// - [APIExclude] - public override void WriteFull(PooledWriter writer) - { - if (!_valuesChanged) - return; - - base.WriteHeader(writer, false); - //True for full write. - writer.WriteBoolean(true); - writer.WriteInt32(Collection.Count); - foreach (KeyValuePair item in Collection) - { - writer.WriteByte((byte)SyncDictionaryOperation.Add); - writer.Write(item.Key); - writer.Write(item.Value); - } - } - - - /// - /// Reads and sets the current values for server or client. - /// - [APIExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void Read(PooledReader reader, bool asServer) - { - /* When !asServer don't make changes if server is running. - * This is because changes would have already been made on - * the server side and doing so again would result in duplicates - * and potentially overwrite data not yet sent. */ - bool asClientAndHost = (!asServer && base.NetworkBehaviour.IsServer); - IDictionary collection = (asClientAndHost) ? ClientHostCollection : Collection; - - //Clear collection since it's a full write. - bool fullWrite = reader.ReadBoolean(); - if (fullWrite) - collection.Clear(); - - int changes = reader.ReadInt32(); - for (int i = 0; i < changes; i++) - { - SyncDictionaryOperation operation = (SyncDictionaryOperation)reader.ReadByte(); - TKey key = default; - TValue value = default; - - /* Add, Set. - * Use the Set code for add and set, - * especially so collection doesn't throw - * if entry has already been added. */ - if (operation == SyncDictionaryOperation.Add || operation == SyncDictionaryOperation.Set) - { - key = reader.Read(); - value = reader.Read(); - collection[key] = value; - } - //Clear. - else if (operation == SyncDictionaryOperation.Clear) - { - collection.Clear(); - } - //Remove. - else if (operation == SyncDictionaryOperation.Remove) - { - key = reader.Read(); - collection.Remove(key); - } - - InvokeOnChange(operation, key, value, false); - } - - //If changes were made invoke complete after all have been read. - if (changes > 0) - InvokeOnChange(SyncDictionaryOperation.Complete, default, default, false); - } - - - /// - /// Invokes OnChanged callback. - /// - private void InvokeOnChange(SyncDictionaryOperation operation, TKey key, TValue value, bool asServer) - { - if (asServer) - { - if (base.NetworkBehaviour.OnStartServerCalled) - OnChange?.Invoke(operation, key, value, asServer); - else - _serverOnChanges.Add(new CachedOnChange(operation, key, value)); - } - else - { - if (base.NetworkBehaviour.OnStartClientCalled) - OnChange?.Invoke(operation, key, value, asServer); - else - _clientOnChanges.Add(new CachedOnChange(operation, key, value)); - } - } - - - /// - /// Resets to initialized values. - /// - [APIExclude] - public override void Reset() - { - base.Reset(); - _sendAll = false; - _changed.Clear(); - Collection.Clear(); - ClientHostCollection.Clear(); - _valuesChanged = false; - - foreach (KeyValuePair item in _initialValues) - { - Collection[item.Key] = item.Value; - ClientHostCollection[item.Key] = item.Value; - } - } - - - /// - /// Adds item. - /// - /// Item to add. - public void Add(KeyValuePair item) - { - Add(item.Key, item.Value); - } - /// - /// Adds key and value. - /// - /// Key to add. - /// Value for key. - public void Add(TKey key, TValue value) - { - Add(key, value, true); - } - private void Add(TKey key, TValue value, bool asServer) - { - if (!base.CanNetworkSetValues(true)) - return; - - Collection.Add(key, value); - if (asServer) - AddOperation(SyncDictionaryOperation.Add, key, value); - } - - /// - /// Clears all values. - /// - public void Clear() - { - Clear(true); - } - private void Clear(bool asServer) - { - if (!base.CanNetworkSetValues(true)) - return; - - Collection.Clear(); - if (asServer) - AddOperation(SyncDictionaryOperation.Clear, default, default); - } - - - /// - /// Returns if key exist. - /// - /// Key to use. - /// True if found. - public bool ContainsKey(TKey key) - { - return Collection.ContainsKey(key); - } - /// - /// Returns if item exist. - /// - /// Item to use. - /// True if found. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(KeyValuePair item) - { - return TryGetValue(item.Key, out TValue value) && EqualityComparer.Default.Equals(value, item.Value); - } - - /// - /// Copies collection to an array. - /// - /// Array to copy to. - /// Offset of array data is copied to. - public void CopyTo([NotNull] KeyValuePair[] array, int offset) - { - if (offset <= -1 || offset >= array.Length) - { - base.NetworkManager.LogError($"Index is out of range."); - return; - } - - int remaining = array.Length - offset; - if (remaining < Count) - { - base.NetworkManager.LogError($"Array is not large enough to copy data. Array is of length {array.Length}, index is {offset}, and number of values to be copied is {Count.ToString()}."); - return; - } - - int i = offset; - foreach (KeyValuePair item in Collection) - { - array[i] = item; - i++; - } - } - - - /// - /// Removes a key. - /// - /// Key to remove. - /// True if removed. - public bool Remove(TKey key) - { - if (!base.CanNetworkSetValues(true)) - return false; - - if (Collection.Remove(key)) - { - AddOperation(SyncDictionaryOperation.Remove, key, default); - return true; - } - - return false; - } - - - /// - /// Removes an item. - /// - /// Item to remove. - /// True if removed. - public bool Remove(KeyValuePair item) - { - return Remove(item.Key); - } - - /// - /// Tries to get value from key. - /// - /// Key to use. - /// Variable to output to. - /// True if able to output value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryGetValue(TKey key, out TValue value) - { - return Collection.TryGetValueIL2CPP(key, out value); - } - - /// - /// Gets or sets value for a key. - /// - /// Key to use. - /// Value when using as Get. - public TValue this[TKey key] - { - get => Collection[key]; - set - { - if (!base.CanNetworkSetValues(true)) - return; - - Collection[key] = value; - AddOperation(SyncDictionaryOperation.Set, key, value); - } - } - - /// - /// Dirties the entire collection forcing a full send. - /// - public void DirtyAll() - { - if (!base.IsRegistered) - return; - if (!base.CanNetworkSetValues(true)) - return; - - if (base.Dirty()) - _sendAll = true; - } - - /// - /// Dirties an entry by key. - /// - /// Key to dirty. - public void Dirty(TKey key) - { - if (!base.IsRegistered) - return; - if (!base.CanNetworkSetValues(true)) - return; - - if (Collection.TryGetValueIL2CPP(key, out TValue value)) - AddOperation(SyncDictionaryOperation.Set, key, value); - } - - /// - /// Dirties an entry by value. - /// This operation can be very expensive, will cause allocations, and may fail if your value cannot be compared. - /// - /// Value to dirty. - /// True if value was found and marked dirty. - public bool Dirty(TValue value, EqualityComparer comparer = null) - { - if (!base.IsRegistered) - return false; - if (!base.CanNetworkSetValues(true)) - return false; - - if (comparer == null) - comparer = EqualityComparer.Default; - - foreach (KeyValuePair item in Collection) - { - if (comparer.Equals(item.Value, value)) - { - AddOperation(SyncDictionaryOperation.Set, item.Key, value); - return true; - } - } - - //Not found. - return false; - } - - /// - /// Gets the IEnumerator for the collection. - /// - /// - public IEnumerator> GetEnumerator() => Collection.GetEnumerator(); - /// - /// Gets the IEnumerator for the collection. - /// - /// - IEnumerator IEnumerable.GetEnumerator() => Collection.GetEnumerator(); - - } - - [APIExclude] - public class SyncDictionary : SyncIDictionary - { - [APIExclude] - public SyncDictionary() : base(new Dictionary()) { } - [APIExclude] - public SyncDictionary(IEqualityComparer eq) : base(new Dictionary(eq)) { } - [APIExclude] - public new Dictionary.ValueCollection Values => ((Dictionary)Collection).Values; - [APIExclude] - public new Dictionary.KeyCollection Keys => ((Dictionary)Collection).Keys; - [APIExclude] - public new Dictionary.Enumerator GetEnumerator() => ((Dictionary)Collection).GetEnumerator(); - - } -} diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionary.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionary.cs.meta deleted file mode 100644 index 10242a2..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionary.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 54751f912587a854cb61ff80a82087bf -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionaryOperation.cs b/Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionaryOperation.cs deleted file mode 100644 index 7f9913f..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionaryOperation.cs +++ /dev/null @@ -1,31 +0,0 @@ - -using FishNet.Documenting; - -namespace FishNet.Object.Synchronizing -{ - [APIExclude] - public enum SyncDictionaryOperation : byte - { - /// - /// A key and value have been added to the collection. - /// - Add, - /// - /// Collection has been cleared. - /// - Clear, - /// - /// A key was removed from the collection. - /// - Remove, - /// - /// A value has been set for a key in the collection. - /// - Set, - /// - /// All operations for the tick have been processed. - /// - Complete - } - -} diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionaryOperation.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionaryOperation.cs.meta deleted file mode 100644 index 2b2b24c..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncDictionaryOperation.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d5d6ed9db47a8224fa9ed4d2ff54586f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncHashSetOperation.cs b/Assets/FishNet/Runtime/Object/Synchronizing/SyncHashSetOperation.cs deleted file mode 100644 index 01017b4..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncHashSetOperation.cs +++ /dev/null @@ -1,31 +0,0 @@ - -using FishNet.Documenting; - -namespace FishNet.Object.Synchronizing -{ - [APIExclude] - public enum SyncHashSetOperation : byte - { - /// - /// An item is added to the collection. - /// - Add, - /// - /// An item is removed from the collection. - /// - Remove, - /// - /// Collection is cleared. - /// - Clear, - /// - /// All operations for the tick have been processed. This only occurs on clients as the server is unable to be aware of when the user is done modifying the list. - /// - Complete, - /// - /// An item has been updated within the collection. This is generally used when modifying data within a container. - /// - Update, - } - -} diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncHashSetOperation.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/SyncHashSetOperation.cs.meta deleted file mode 100644 index 2d909a8..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncHashSetOperation.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 914089f5707003340a68fd6cd718e4c4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncHashset.cs b/Assets/FishNet/Runtime/Object/Synchronizing/SyncHashset.cs deleted file mode 100644 index e7e83ec..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncHashset.cs +++ /dev/null @@ -1,616 +0,0 @@ -using FishNet.Documenting; -using FishNet.Managing.Logging; -using FishNet.Object.Synchronizing.Internal; -using FishNet.Serializing; -using FishNet.Serializing.Helping; -using FishNet.Utility.Performance; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Object.Synchronizing -{ - - public class SyncHashSet : SyncBase, ISet - { - #region Types. - /// - /// Information needed to invoke a callback. - /// - private struct CachedOnChange - { - internal readonly SyncHashSetOperation Operation; - internal readonly T Item; - - public CachedOnChange(SyncHashSetOperation operation, T item) - { - Operation = operation; - Item = item; - } - } - - /// - /// Information about how the collection has changed. - /// - private struct ChangeData - { - internal readonly SyncHashSetOperation Operation; - internal readonly T Item; - - public ChangeData(SyncHashSetOperation operation, T item) - { - Operation = operation; - - Item = item; - } - } - #endregion - - #region Public. - /// - /// Implementation from List. Not used. - /// - [APIExclude] - public bool IsReadOnly => false; - /// - /// Delegate signature for when SyncList changes. - /// - /// Type of change. - /// Item which was modified. - /// True if callback is occuring on the server. - [APIExclude] - public delegate void SyncHashSetChanged(SyncHashSetOperation op, T item, bool asServer); - /// - /// Called when the SyncList changes. - /// - public event SyncHashSetChanged OnChange; - /// - /// Collection of objects. - /// - public readonly ISet Collection; - /// - /// Copy of objects on client portion when acting as a host. - /// - public readonly ISet ClientHostCollection = new HashSet(); - /// - /// Number of objects in the collection. - /// - public int Count => Collection.Count; - #endregion - - #region Private. - /// - /// ListCache for comparing. - /// - private ListCache _listCache; - /// - /// Values upon initialization. - /// - private ISet _initialValues = new HashSet(); - /// - /// Comparer to see if entries change when calling public methods. - /// - private readonly IEqualityComparer _comparer; - /// - /// Changed data which will be sent next tick. - /// - private readonly List _changed = new List(); - /// - /// Server OnChange events waiting for start callbacks. - /// - private readonly List _serverOnChanges = new List(); - /// - /// Client OnChange events waiting for start callbacks. - /// - private readonly List _clientOnChanges = new List(); - /// - /// True if values have changed since initialization. - /// The only reasonable way to reset this during a Reset call is by duplicating the original list and setting all values to it on reset. - /// - private bool _valuesChanged; - /// - /// True to send all values in the next WriteDelta. - /// - private bool _sendAll; - #endregion - - [APIExclude] - public SyncHashSet() : this(new HashSet(), EqualityComparer.Default) { } - [APIExclude] - public SyncHashSet(IEqualityComparer comparer) : this(new HashSet(), (comparer == null) ? EqualityComparer.Default : comparer) { } - [APIExclude] - public SyncHashSet(ISet collection, IEqualityComparer comparer = null) - { - this._comparer = (comparer == null) ? EqualityComparer.Default : comparer; - this.Collection = collection; - //Add each in collection to clienthostcollection. - foreach (T item in collection) - ClientHostCollection.Add(item); - } - - /// - /// Called when the SyncType has been registered, but not yet initialized over the network. - /// - protected override void Registered() - { - base.Registered(); - foreach (T item in Collection) - _initialValues.Add(item); - } - - /// - /// Gets the collection being used within this SyncList. - /// - /// - public HashSet GetCollection(bool asServer) - { - bool asClientAndHost = (!asServer && base.NetworkManager.IsServer); - ISet collection = (asClientAndHost) ? ClientHostCollection : Collection; - return (collection as HashSet); - } - - /// - /// Adds an operation and invokes locally. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void AddOperation(SyncHashSetOperation operation, T item) - { - if (!base.IsRegistered) - return; - - bool asServerInvoke = (!base.IsNetworkInitialized || base.NetworkBehaviour.IsServer); - - if (asServerInvoke) - { - _valuesChanged = true; - if (base.Dirty()) - { - ChangeData change = new ChangeData(operation, item); - _changed.Add(change); - } - } - - InvokeOnChange(operation, item, asServerInvoke); - } - - /// - /// Called after OnStartXXXX has occurred. - /// - /// True if OnStartServer was called, false if OnStartClient. - public override void OnStartCallback(bool asServer) - { - base.OnStartCallback(asServer); - List collection = (asServer) ? _serverOnChanges : _clientOnChanges; - if (OnChange != null) - { - foreach (CachedOnChange item in collection) - OnChange.Invoke(item.Operation, item.Item, asServer); - } - - collection.Clear(); - } - - /// - /// Writes all changed values. - /// - /// - ///True to set the next time data may sync. - public override void WriteDelta(PooledWriter writer, bool resetSyncTick = true) - { - //If sending all then clear changed and write full. - if (_sendAll) - { - _sendAll = false; - _changed.Clear(); - WriteFull(writer); - } - else - { - base.WriteDelta(writer, resetSyncTick); - //False for not full write. - writer.WriteBoolean(false); - writer.WriteInt32(_changed.Count); - - for (int i = 0; i < _changed.Count; i++) - { - ChangeData change = _changed[i]; - writer.WriteByte((byte)change.Operation); - - //Clear does not need to write anymore data so it is not included in checks. - if (change.Operation == SyncHashSetOperation.Add || change.Operation == SyncHashSetOperation.Remove || change.Operation == SyncHashSetOperation.Update) - { - writer.Write(change.Item); - } - } - - _changed.Clear(); - } - } - - /// - /// Writes all values if not initial values. - /// - /// - public override void WriteFull(PooledWriter writer) - { - if (!_valuesChanged) - return; - - base.WriteHeader(writer, false); - //True for full write. - writer.WriteBoolean(true); - int count = Collection.Count; - writer.WriteInt32(count); - foreach (T item in Collection) - { - writer.WriteByte((byte)SyncHashSetOperation.Add); - writer.Write(item); - } - } - - /// - /// Reads and sets the current values for server or client. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [APIExclude] - public override void Read(PooledReader reader, bool asServer) - { - /* When !asServer don't make changes if server is running. - * This is because changes would have already been made on - * the server side and doing so again would result in duplicates - * and potentially overwrite data not yet sent. */ - bool asClientAndHost = (!asServer && base.NetworkManager.IsServer); - ISet collection = (asClientAndHost) ? ClientHostCollection : Collection; - - //Clear collection since it's a full write. - bool fullWrite = reader.ReadBoolean(); - if (fullWrite) - collection.Clear(); - - int changes = reader.ReadInt32(); - for (int i = 0; i < changes; i++) - { - SyncHashSetOperation operation = (SyncHashSetOperation)reader.ReadByte(); - T next = default; - - //Add. - if (operation == SyncHashSetOperation.Add) - { - next = reader.Read(); - collection.Add(next); - } - //Clear. - else if (operation == SyncHashSetOperation.Clear) - { - collection.Clear(); - } - //Remove. - else if (operation == SyncHashSetOperation.Remove) - { - next = reader.Read(); - collection.Remove(next); - } - //Updated. - else if (operation == SyncHashSetOperation.Update) - { - next = reader.Read(); - collection.Remove(next); - collection.Add(next); - } - - InvokeOnChange(operation, next, false); - } - - //If changes were made invoke complete after all have been read. - if (changes > 0) - InvokeOnChange(SyncHashSetOperation.Complete, default, false); - } - - /// - /// Invokes OnChanged callback. - /// - private void InvokeOnChange(SyncHashSetOperation operation, T item, bool asServer) - { - if (asServer) - { - if (base.NetworkBehaviour.OnStartServerCalled) - OnChange?.Invoke(operation, item, asServer); - else - _serverOnChanges.Add(new CachedOnChange(operation, item)); - } - else - { - if (base.NetworkBehaviour.OnStartClientCalled) - OnChange?.Invoke(operation, item, asServer); - else - _clientOnChanges.Add(new CachedOnChange(operation, item)); - } - } - - /// - /// Resets to initialized values. - /// - public override void Reset() - { - base.Reset(); - _sendAll = false; - _changed.Clear(); - Collection.Clear(); - ClientHostCollection.Clear(); - - foreach (T item in _initialValues) - { - Collection.Add(item); - ClientHostCollection.Add(item); - } - } - - /// - /// Adds value. - /// - /// - public bool Add(T item) - { - return Add(item, true); - } - private bool Add(T item, bool asServer) - { - if (!base.CanNetworkSetValues(true)) - return false; - - bool result = Collection.Add(item); - //Only process if remove was successful. - if (result && asServer) - { - if (base.NetworkManager == null) - ClientHostCollection.Add(item); - AddOperation(SyncHashSetOperation.Add, item); - } - - return result; - } - /// - /// Adds a range of values. - /// - /// - public void AddRange(IEnumerable range) - { - foreach (T entry in range) - Add(entry, true); - } - - /// - /// Clears all values. - /// - public void Clear() - { - Clear(true); - } - private void Clear(bool asServer) - { - if (!base.CanNetworkSetValues(true)) - return; - - Collection.Clear(); - if (asServer) - { - if (base.NetworkManager == null) - ClientHostCollection.Clear(); - AddOperation(SyncHashSetOperation.Clear, default); - } - } - - /// - /// Returns if value exist. - /// - /// - /// - public bool Contains(T item) - { - return Collection.Contains(item); - } - - /// - /// Removes a value. - /// - /// - /// - public bool Remove(T item) - { - return Remove(item, true); - } - private bool Remove(T item, bool asServer) - { - if (!base.CanNetworkSetValues(true)) - return false; - - bool result = Collection.Remove(item); - //Only process if remove was successful. - if (result && asServer) - { - if (base.NetworkManager == null) - ClientHostCollection.Remove(item); - AddOperation(SyncHashSetOperation.Remove, item); - } - - return result; - } - - /// - /// Dirties the entire collection forcing a full send. - /// - public void DirtyAll() - { - if (!base.IsRegistered) - return; - if (!base.CanNetworkSetValues(true)) - return; - - if (base.Dirty()) - _sendAll = true; - } - - /// - /// Looks up obj in Collection and if found marks it's index as dirty. - /// This operation can be very expensive, will cause allocations, and may fail if your value cannot be compared. - /// - /// Object to lookup. - public void Dirty(T obj) - { - if (!base.IsRegistered) - return; - if (!base.CanNetworkSetValues(true)) - return; - - foreach (T item in Collection) - { - if (item.Equals(obj)) - { - AddOperation(SyncHashSetOperation.Update, obj); - return; - } - } - - //Not found. - base.NetworkManager.LogError($"Could not find object within SyncHashSet, dirty will not be set."); - } - - /// - /// Returns Enumerator for collection. - /// - /// - public IEnumerator GetEnumerator() => Collection.GetEnumerator(); - [APIExclude] - IEnumerator IEnumerable.GetEnumerator() => Collection.GetEnumerator(); - [APIExclude] - IEnumerator IEnumerable.GetEnumerator() => Collection.GetEnumerator(); - - public void ExceptWith(IEnumerable other) - { - //Again, removing from self is a clear. - if (other == Collection) - { - Clear(); - } - else - { - foreach (T item in other) - Remove(item); - } - } - - public void IntersectWith(IEnumerable other) - { - ISet set; - if (other is ISet setA) - set = setA; - else - set = new HashSet(other); - - IntersectWith(set); - } - - private void IntersectWith(ISet other) - { - Intersect(Collection); - if (base.NetworkManager == null) - Intersect(ClientHostCollection); - - void Intersect(ISet collection) - { - if (_listCache == null) - _listCache = new ListCache(); - else - _listCache.Reset(); - - _listCache.AddValues(collection); - - int count = _listCache.Written; - for (int i = 0; i < count; i++) - { - T entry = _listCache.Collection[i]; - if (!other.Contains(entry)) - Remove(entry); - } - } - - } - - public bool IsProperSubsetOf(IEnumerable other) - { - return Collection.IsProperSubsetOf(other); - } - - public bool IsProperSupersetOf(IEnumerable other) - { - return Collection.IsProperSupersetOf(other); - } - - public bool IsSubsetOf(IEnumerable other) - { - return Collection.IsSubsetOf(other); - } - - public bool IsSupersetOf(IEnumerable other) - { - return Collection.IsSupersetOf(other); - } - - public bool Overlaps(IEnumerable other) - { - bool result = Collection.Overlaps(other); - return result; - } - - public bool SetEquals(IEnumerable other) - { - return Collection.SetEquals(other); - } - - public void SymmetricExceptWith(IEnumerable other) - { - //If calling except on self then that is the same as a clear. - if (other == Collection) - { - Clear(); - } - else - { - foreach (T item in other) - Remove(item); - } - } - - public void UnionWith(IEnumerable other) - { - if (other == Collection) - return; - - foreach (T item in other) - Add(item); - } - - /// - /// Adds an item. - /// - /// - void ICollection.Add(T item) - { - Add(item, true); - } - - /// - /// Copies values to an array. - /// - /// - /// - public void CopyTo(T[] array, int index) - { - Collection.CopyTo(array, index); - if (base.NetworkManager == null) - ClientHostCollection.CopyTo(array, index); - } - } -} diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncHashset.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/SyncHashset.cs.meta deleted file mode 100644 index 47a2d07..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncHashset.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 624322b9d999d4b43a560134460955c6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncList.cs b/Assets/FishNet/Runtime/Object/Synchronizing/SyncList.cs deleted file mode 100644 index a025196..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncList.cs +++ /dev/null @@ -1,748 +0,0 @@ -using FishNet.Documenting; -using FishNet.Managing.Logging; -using FishNet.Object.Synchronizing.Internal; -using FishNet.Serializing; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Object.Synchronizing -{ - - public class SyncList : SyncBase, IList, IReadOnlyList - { - #region Types. - /// - /// Information needed to invoke a callback. - /// - private struct CachedOnChange - { - internal readonly SyncListOperation Operation; - internal readonly int Index; - internal readonly T Previous; - internal readonly T Next; - - public CachedOnChange(SyncListOperation operation, int index, T previous, T next) - { - Operation = operation; - Index = index; - Previous = previous; - Next = next; - } - } - - /// - /// Information about how the collection has changed. - /// - private struct ChangeData - { - internal readonly SyncListOperation Operation; - internal readonly int Index; - internal readonly T Item; - - public ChangeData(SyncListOperation operation, int index, T item) - { - Operation = operation; - Index = index; - Item = item; - } - } - - /// - /// Custom enumerator to prevent garbage collection. - /// - [APIExclude] - public struct Enumerator : IEnumerator - { - public T Current { get; private set; } - private readonly SyncList _list; - private int _index; - - public Enumerator(SyncList list) - { - this._list = list; - _index = -1; - Current = default; - } - - public bool MoveNext() - { - _index++; - if (_index >= _list.Count) - return false; - Current = _list[_index]; - return true; - } - - public void Reset() => _index = -1; - object IEnumerator.Current => Current; - public void Dispose() { } - } - #endregion - - #region Public. - /// - /// Implementation from List. Not used. - /// - [APIExclude] - public bool IsReadOnly => false; - /// - /// Delegate signature for when SyncList changes. - /// - /// - /// - /// - /// - [APIExclude] - public delegate void SyncListChanged(SyncListOperation op, int index, T oldItem, T newItem, bool asServer); - /// - /// Called when the SyncList changes. - /// - public event SyncListChanged OnChange; - /// - /// Collection of objects. - /// - public readonly IList Collection; - /// - /// Copy of objects on client portion when acting as a host. - /// - public readonly IList ClientHostCollection = new List(); - /// - /// Number of objects in the collection. - /// - public int Count => Collection.Count; - #endregion - - #region Private. - /// - /// Values upon initialization. - /// - private IList _initialValues = new List(); - /// - /// Comparer to see if entries change when calling public methods. - /// - private readonly IEqualityComparer _comparer; - /// - /// Changed data which will be sent next tick. - /// - private readonly List _changed = new List(); - /// - /// Server OnChange events waiting for start callbacks. - /// - private readonly List _serverOnChanges = new List(); - /// - /// Client OnChange events waiting for start callbacks. - /// - private readonly List _clientOnChanges = new List(); - /// - /// True if values have changed since initialization. - /// The only reasonable way to reset this during a Reset call is by duplicating the original list and setting all values to it on reset. - /// - private bool _valuesChanged; - /// - /// True to send all values in the next WriteDelta. - /// - private bool _sendAll; - #endregion - - [APIExclude] - public SyncList() : this(new List(), EqualityComparer.Default) { } - [APIExclude] - public SyncList(IEqualityComparer comparer) : this(new List(), (comparer == null) ? EqualityComparer.Default : comparer) { } - [APIExclude] - public SyncList(IList collection, IEqualityComparer comparer = null) - { - this._comparer = (comparer == null) ? EqualityComparer.Default : comparer; - this.Collection = collection; - //Add each in collection to clienthostcollection. - foreach (T item in collection) - this.ClientHostCollection.Add(item); - } - - /// - /// Called when the SyncType has been registered, but not yet initialized over the network. - /// - protected override void Registered() - { - base.Registered(); - foreach (T item in Collection) - _initialValues.Add(item); - } - - /// - /// Gets the collection being used within this SyncList. - /// - /// True if returning the server value, false if client value. The values will only differ when running as host. While asServer is true the most current values on server will be returned, and while false the latest values received by client will be returned. - /// - public List GetCollection(bool asServer) - { - bool asClientAndHost = (!asServer && base.NetworkManager.IsServer); - IList collection = (asClientAndHost) ? ClientHostCollection : Collection; - return (collection as List); - } - - /// - /// Adds an operation and invokes locally. - /// - /// - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void AddOperation(SyncListOperation operation, int index, T prev, T next) - { - if (!base.IsRegistered) - return; - - /* asServer might be true if the client is setting the value - * through user code. Typically synctypes can only be set - * by the server, that's why it is assumed asServer via user code. - * However, when excluding owner for the synctype the client should - * have permission to update the value locally for use with - * prediction. */ - bool asServerInvoke = (!base.IsNetworkInitialized || base.NetworkBehaviour.IsServer); - - /* Only the adds asServer may set - * this synctype as dirty and add - * to pending changes. However, the event may still - * invoke for clientside. */ - if (asServerInvoke) - { - /* Set as changed even if cannot dirty. - * Dirty is only set when there are observers, - * but even if there are not observers - * values must be marked as changed so when - * there are observers, new values are sent. */ - _valuesChanged = true; - - /* If unable to dirty then do not add to changed. - * A dirty may fail if the server is not started - * or if there's no observers. Changed doesn't need - * to be populated in this situations because clients - * will get the full collection on spawn. If we - * were to also add to changed clients would get the full - * collection as well the changed, which would double results. */ - if (base.Dirty()) - { - ChangeData change = new ChangeData(operation, index, next); - _changed.Add(change); - } - } - - InvokeOnChange(operation, index, prev, next, asServerInvoke); - } - - /// - /// Called after OnStartXXXX has occurred. - /// - /// True if OnStartServer was called, false if OnStartClient. - public override void OnStartCallback(bool asServer) - { - base.OnStartCallback(asServer); - List collection = (asServer) ? _serverOnChanges : _clientOnChanges; - - if (OnChange != null) - { - foreach (CachedOnChange item in collection) - OnChange.Invoke(item.Operation, item.Index, item.Previous, item.Next, asServer); - } - - collection.Clear(); - } - - /// - /// Writes all changed values. - /// - /// - ///True to set the next time data may sync. - public override void WriteDelta(PooledWriter writer, bool resetSyncTick = true) - { - //If sending all then clear changed and write full. - if (_sendAll) - { - _sendAll = false; - _changed.Clear(); - WriteFull(writer); - } - else - { - base.WriteDelta(writer, resetSyncTick); - //False for not full write. - writer.WriteBoolean(false); - writer.WriteInt32(_changed.Count); - - for (int i = 0; i < _changed.Count; i++) - { - ChangeData change = _changed[i]; - writer.WriteByte((byte)change.Operation); - - //Clear does not need to write anymore data so it is not included in checks. - if (change.Operation == SyncListOperation.Add) - { - writer.Write(change.Item); - } - else if (change.Operation == SyncListOperation.RemoveAt) - { - writer.WriteInt32(change.Index); - } - else if (change.Operation == SyncListOperation.Insert || change.Operation == SyncListOperation.Set) - { - writer.WriteInt32(change.Index); - writer.Write(change.Item); - } - } - - _changed.Clear(); - } - } - - /// - /// Writes all values if not initial values. - /// - /// - public override void WriteFull(PooledWriter writer) - { - if (!_valuesChanged) - return; - - base.WriteHeader(writer, false); - //True for full write. - writer.WriteBoolean(true); - writer.WriteInt32(Collection.Count); - for (int i = 0; i < Collection.Count; i++) - { - writer.WriteByte((byte)SyncListOperation.Add); - writer.Write(Collection[i]); - } - } - - /// - /// Reads and sets the current values for server or client. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [APIExclude] - public override void Read(PooledReader reader, bool asServer) - { - /* When !asServer don't make changes if server is running. - * This is because changes would have already been made on - * the server side and doing so again would result in duplicates - * and potentially overwrite data not yet sent. */ - bool asClientAndHost = (!asServer && base.NetworkManager.IsServer); - IList collection = (asClientAndHost) ? ClientHostCollection : Collection; - - //Clear collection since it's a full write. - bool fullWrite = reader.ReadBoolean(); - if (fullWrite) - collection.Clear(); - - int changes = reader.ReadInt32(); - - for (int i = 0; i < changes; i++) - { - SyncListOperation operation = (SyncListOperation)reader.ReadByte(); - int index = -1; - T prev = default; - T next = default; - - //Add. - if (operation == SyncListOperation.Add) - { - next = reader.Read(); - index = collection.Count; - collection.Add(next); - } - //Clear. - else if (operation == SyncListOperation.Clear) - { - collection.Clear(); - } - //Insert. - else if (operation == SyncListOperation.Insert) - { - index = reader.ReadInt32(); - next = reader.Read(); - collection.Insert(index, next); - } - //RemoveAt. - else if (operation == SyncListOperation.RemoveAt) - { - index = reader.ReadInt32(); - prev = collection[index]; - collection.RemoveAt(index); - } - //Set - else if (operation == SyncListOperation.Set) - { - index = reader.ReadInt32(); - next = reader.Read(); - prev = collection[index]; - collection[index] = next; - } - - InvokeOnChange(operation, index, prev, next, false); - } - - //If changes were made invoke complete after all have been read. - if (changes > 0) - InvokeOnChange(SyncListOperation.Complete, -1, default, default, false); - } - - /// - /// Invokes OnChanged callback. - /// - private void InvokeOnChange(SyncListOperation operation, int index, T prev, T next, bool asServer) - { - if (asServer) - { - if (base.NetworkBehaviour.OnStartServerCalled) - OnChange?.Invoke(operation, index, prev, next, asServer); - else - _serverOnChanges.Add(new CachedOnChange(operation, index, prev, next)); - } - else - { - if (base.NetworkBehaviour.OnStartClientCalled) - OnChange?.Invoke(operation, index, prev, next, asServer); - else - _clientOnChanges.Add(new CachedOnChange(operation, index, prev, next)); - } - } - - /// - /// Resets to initialized values. - /// - public override void Reset() - { - base.Reset(); - _sendAll = false; - _changed.Clear(); - ClientHostCollection.Clear(); - Collection.Clear(); - - foreach (T item in _initialValues) - { - Collection.Add(item); - ClientHostCollection.Add(item); - } - } - - - /// - /// Adds value. - /// - /// - public void Add(T item) - { - Add(item, true); - } - private void Add(T item, bool asServer) - { - if (!base.CanNetworkSetValues(true)) - return; - - Collection.Add(item); - if (asServer) - { - if (base.NetworkManager == null) - ClientHostCollection.Add(item); - AddOperation(SyncListOperation.Add, Collection.Count - 1, default, item); - } - } - /// - /// Adds a range of values. - /// - /// - public void AddRange(IEnumerable range) - { - foreach (T entry in range) - Add(entry, true); - } - - /// - /// Clears all values. - /// - public void Clear() - { - Clear(true); - } - private void Clear(bool asServer) - { - if (!base.CanNetworkSetValues(true)) - return; - - Collection.Clear(); - if (asServer) - { - if (base.NetworkManager == null) - ClientHostCollection.Clear(); - AddOperation(SyncListOperation.Clear, -1, default, default); - } - } - - /// - /// Returns if value exist. - /// - /// - /// - public bool Contains(T item) - { - return (IndexOf(item) >= 0); - } - - /// - /// Copies values to an array. - /// - /// - /// - public void CopyTo(T[] array, int index) - { - Collection.CopyTo(array, index); - } - - /// - /// Gets the index of value. - /// - /// - /// - public int IndexOf(T item) - { - for (int i = 0; i < Collection.Count; ++i) - if (_comparer.Equals(item, Collection[i])) - return i; - return -1; - } - - /// - /// Finds index using match. - /// - /// - /// - public int FindIndex(Predicate match) - { - for (int i = 0; i < Collection.Count; ++i) - if (match(Collection[i])) - return i; - return -1; - } - - /// - /// Finds value using match. - /// - /// - /// - public T Find(Predicate match) - { - int i = FindIndex(match); - return (i != -1) ? Collection[i] : default; - } - - /// - /// Finds all values using match. - /// - /// - /// - public List FindAll(Predicate match) - { - List results = new List(); - for (int i = 0; i < Collection.Count; ++i) - if (match(Collection[i])) - results.Add(Collection[i]); - return results; - } - - /// - /// Inserts value at index. - /// - /// - /// - public void Insert(int index, T item) - { - Insert(index, item, true); - } - private void Insert(int index, T item, bool asServer) - { - if (!base.CanNetworkSetValues(true)) - return; - - Collection.Insert(index, item); - if (asServer) - { - if (base.NetworkManager == null) - ClientHostCollection.Insert(index, item); - AddOperation(SyncListOperation.Insert, index, default, item); - } - } - - /// - /// Inserts a range of values. - /// - /// - /// - public void InsertRange(int index, IEnumerable range) - { - foreach (T entry in range) - { - Insert(index, entry); - index++; - } - } - - /// - /// Removes a value. - /// - /// - /// - public bool Remove(T item) - { - int index = IndexOf(item); - bool result = index >= 0; - if (result) - RemoveAt(index); - - return result; - } - - /// - /// Removes value at index. - /// - /// - /// - public void RemoveAt(int index) - { - RemoveAt(index, true); - } - private void RemoveAt(int index, bool asServer) - { - if (!base.CanNetworkSetValues(true)) - return; - - T oldItem = Collection[index]; - Collection.RemoveAt(index); - if (asServer) - { - if (base.NetworkManager == null) - ClientHostCollection.RemoveAt(index); - AddOperation(SyncListOperation.RemoveAt, index, oldItem, default); - } - } - - /// - /// Removes all values within the collection. - /// - /// - /// - public int RemoveAll(Predicate match) - { - List toRemove = new List(); - for (int i = 0; i < Collection.Count; ++i) - if (match(Collection[i])) - toRemove.Add(Collection[i]); - - foreach (T entry in toRemove) - Remove(entry); - - return toRemove.Count; - } - - /// - /// Gets or sets value at an index. - /// - /// - /// - public T this[int i] - { - get => Collection[i]; - set => Set(i, value, true, true); - } - - /// - /// Dirties the entire collection forcing a full send. - /// This will not invoke the callback on server. - /// - public void DirtyAll() - { - if (!base.IsRegistered) - return; - - if (base.NetworkManager != null && !base.NetworkBehaviour.IsServer) - { - base.NetworkManager.LogWarning($"Cannot complete operation as server when server is not active."); - return; - } - - if (base.Dirty()) - _sendAll = true; - } - - /// - /// Looks up obj in Collection and if found marks it's index as dirty. - /// While using this operation previous value will be the same as next. - /// This operation can be very expensive, and may fail if your value cannot be compared. - /// - /// Object to lookup. - public void Dirty(T obj) - { - int index = Collection.IndexOf(obj); - if (index != -1) - Dirty(index); - else - base.NetworkManager.LogError($"Could not find object within SyncList, dirty will not be set."); - } - /// - /// Marks an index as dirty. - /// While using this operation previous value will be the same as next. - /// - /// - public void Dirty(int index) - { - if (!base.CanNetworkSetValues(true)) - return; - - bool asServer = true; - T value = Collection[index]; - if (asServer) - AddOperation(SyncListOperation.Set, index, value, value); - } - /// - /// Sets value at index. - /// - /// - /// - public void Set(int index, T value, bool force = true) - { - Set(index, value, true, force); - } - private void Set(int index, T value, bool asServer, bool force) - { - if (!base.CanNetworkSetValues(true)) - return; - - bool sameValue = (!force && !_comparer.Equals(Collection[index], value)); - if (!sameValue) - { - T prev = Collection[index]; - Collection[index] = value; - if (asServer) - { - if (base.NetworkManager == null) - ClientHostCollection[index] = value; - AddOperation(SyncListOperation.Set, index, prev, value); - } - } - } - - - /// - /// Returns Enumerator for collection. - /// - /// - public Enumerator GetEnumerator() => new Enumerator(this); - [APIExclude] - IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this); - [APIExclude] - IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this); - - } -} diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncList.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/SyncList.cs.meta deleted file mode 100644 index ba053ad..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncList.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2f3a4c0d0a34e5142be66143d732c079 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncListOperation.cs b/Assets/FishNet/Runtime/Object/Synchronizing/SyncListOperation.cs deleted file mode 100644 index 324ac62..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncListOperation.cs +++ /dev/null @@ -1,35 +0,0 @@ - -using FishNet.Documenting; - -namespace FishNet.Object.Synchronizing -{ - [APIExclude] - public enum SyncListOperation : byte - { - /// - /// An item is added to the collection. - /// - Add, - /// - /// An item is inserted into the collection. - /// - Insert, - /// - /// An item is set in the collection. - /// - Set, - /// - /// An item is removed from the collection. - /// - RemoveAt, - /// - /// Collection is cleared. - /// - Clear, - /// - /// All operations for the tick have been processed. This only occurs on clients as the server is unable to be aware of when the user is done modifying the list. - /// - Complete - } - -} diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncListOperation.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/SyncListOperation.cs.meta deleted file mode 100644 index a87c886..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncListOperation.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4fa53fc807605df4997f0b63a6570bcf -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncVar.cs b/Assets/FishNet/Runtime/Object/Synchronizing/SyncVar.cs deleted file mode 100644 index bce03fa..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncVar.cs +++ /dev/null @@ -1,290 +0,0 @@ -using FishNet.Documenting; -using FishNet.Object.Helping; -using FishNet.Object.Synchronizing; -using FishNet.Object.Synchronizing.Internal; -using FishNet.Serializing; -using FishNet.Serializing.Helping; -using FishNet.Transporting; -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using UnityEngine; - -namespace FishNet.Object.Synchronizing -{ - [APIExclude] - [StructLayout(LayoutKind.Auto, CharSet = CharSet.Auto)] - public class SyncVar : SyncBase - { - #region Types. - /// - /// Information needed to invoke a callback. - /// - private struct CachedOnChange - { - internal readonly T Previous; - internal readonly T Next; - - public CachedOnChange(T previous, T next) - { - Previous = previous; - Next = next; - } - } - #endregion - - #region Public. - /// - /// Called when the SyncDictionary changes. - /// - public event Action OnChange; - #endregion - - #region Private. - /// - /// Server OnChange event waiting for start callbacks. - /// - private CachedOnChange? _serverOnChange; - /// - /// Client OnChange event waiting for start callbacks. - /// - private CachedOnChange? _clientOnChange; - /// - /// Value before the network is initialized on the containing object. - /// - private T _initialValue; - /// - /// Previous value on the client. - /// - private T _previousClientValue; - /// - /// Current value on the server, or client. - /// - private T _value; - #endregion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public SyncVar(NetworkBehaviour nb, uint syncIndex, WritePermission writePermission, ReadPermission readPermission, float sendRate, Channel channel, T value) - { - SetInitialValues(value); - base.InitializeInstance(nb, syncIndex, writePermission, readPermission, sendRate, channel, false); - } - - /// - /// Called when the SyncType has been registered, but not yet initialized over the network. - /// - protected override void Registered() - { - base.Registered(); - _initialValue = _value; - } - - /// - /// Sets initial values to next. - /// - /// - private void SetInitialValues(T next) - { - _initialValue = next; - UpdateValues(next); - } - /// - /// Sets current and previous values. - /// - /// - private void UpdateValues(T next) - { - _previousClientValue = next; - _value = next; - } - /// - /// Sets current value and marks the SyncVar dirty when able to. Returns if able to set value. - /// - /// True if SetValue was called in response to user code. False if from automated code. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SetValue(T nextValue, bool calledByUser) - { - /* If not registered then that means Awake - * has not completed on the owning class. This would be true - * when setting values within awake on the owning class. Registered - * is called at the end of awake, so it would be unset until awake completed. - * - * Registered however will be true when setting from another script, - * even if the owning class of this was just spawned. This is because - * the unity cycle will fire awake on the object soon as it's spawned, - * completing awake, and the user would set the value after. */ - if (!base.IsRegistered) - return; - - /* If not client or server then set skipChecks - * as true. When neither is true it's likely user is changing - * value before object is initialized. This is allowed - * but checks cannot be processed because they would otherwise - * stop setting the value. */ - bool isNetworkInitialized = base.IsNetworkInitialized; - - //Object is deinitializing. - if (isNetworkInitialized && CodegenHelper.NetworkObject_Deinitializing(this.NetworkBehaviour)) - return; - - //If being set by user code. - if (calledByUser) - { - if (!base.CanNetworkSetValues(true)) - return; - - /* We will only be this far if the network is not active yet, - * server is active, or client has setting permissions. - * We only need to set asServerInvoke to false if the network - * is initialized and the server is not active. */ - bool asServerInvoke = (!isNetworkInitialized || base.NetworkBehaviour.IsServer); - - /* If the network has not been network initialized then - * Value is expected to be set on server and client since - * it's being set before the object is initialized. */ - if (!isNetworkInitialized) - { - T prev = _value; - UpdateValues(nextValue); - //Still call invoke because change will be cached for when the network initializes. - InvokeOnChange(prev, _value, calledByUser); - } - else - { - if (Comparers.EqualityCompare(_value, nextValue)) - return; - - T prev = _value; - _value = nextValue; - InvokeOnChange(prev, _value, asServerInvoke); - } - - TryDirty(asServerInvoke); - } - //Not called by user. - else - { - /* Previously clients were not allowed to set values - * but this has been changed because clients may want - * to update values locally while occasionally - * letting the syncvar adjust their side. */ - T prev = _previousClientValue; - if (Comparers.EqualityCompare(prev, nextValue)) - return; - - /* If also server do not update value. - * Server side has say of the current value. */ - if (!base.NetworkManager.IsServer) - UpdateValues(nextValue); - else - _previousClientValue = nextValue; - - InvokeOnChange(prev, nextValue, calledByUser); - } - - - /* Tries to dirty so update - * is sent over network. This needs to be called - * anytime the data changes because there is no way - * to know if the user set the value on both server - * and client or just one side. */ - void TryDirty(bool asServer) - { - //Cannot dirty when network is not initialized. - if (!isNetworkInitialized) - return; - - if (asServer) - base.Dirty(); - } - } - - /// - /// Invokes OnChanged callback. - /// - private void InvokeOnChange(T prev, T next, bool asServer) - { - if (asServer) - { - if (base.NetworkBehaviour.OnStartServerCalled) - OnChange?.Invoke(prev, next, asServer); - else - _serverOnChange = new CachedOnChange(prev, next); - } - else - { - if (base.NetworkBehaviour.OnStartClientCalled) - OnChange?.Invoke(prev, next, asServer); - else - _clientOnChange = new CachedOnChange(prev, next); - } - } - - - /// - /// Called after OnStartXXXX has occurred. - /// - /// True if OnStartServer was called, false if OnStartClient. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void OnStartCallback(bool asServer) - { - base.OnStartCallback(asServer); - - if (OnChange != null) - { - CachedOnChange? change = (asServer) ? _serverOnChange : _clientOnChange; - if (change != null) - InvokeOnChange(change.Value.Previous, change.Value.Next, asServer); - } - - if (asServer) - _serverOnChange = null; - else - _clientOnChange = null; - } - - /// - /// Writes current value. - /// - /// True to set the next time data may sync. - public override void WriteDelta(PooledWriter writer, bool resetSyncTick = true) - { - base.WriteDelta(writer, resetSyncTick); - writer.Write(_value); - } - - /// - /// Writes current value if not initialized value. - /// m> - public override void WriteFull(PooledWriter obj0) - { - if (Comparers.EqualityCompare(_initialValue, _value)) - return; - /* SyncVars only hold latest value, so just - * write current delta. */ - WriteDelta(obj0, false); - } - - //Read isn't used by SyncVar, it's done within the NB. - //public override void Read(PooledReader reader) { } - - /// - /// Gets current value. - /// - /// - /// - public T GetValue(bool calledByUser) => (calledByUser) ? _value : _previousClientValue; - - /// - /// Resets to initialized values. - /// - public override void Reset() - { - base.Reset(); - _value = _initialValue; - _previousClientValue = _initialValue; - } - } -} - - diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/SyncVar.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/SyncVar.cs.meta deleted file mode 100644 index 5ae840f..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/SyncVar.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f319403eec508734a93d723617ab1136 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/WritePermissions.cs b/Assets/FishNet/Runtime/Object/Synchronizing/WritePermissions.cs deleted file mode 100644 index fbd2d15..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/WritePermissions.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace FishNet.Object.Synchronizing -{ - /// - /// Which clients or server may write updates. - /// - public enum WritePermission - { - ServerOnly - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Object/Synchronizing/WritePermissions.cs.meta b/Assets/FishNet/Runtime/Object/Synchronizing/WritePermissions.cs.meta deleted file mode 100644 index d1fb70b..0000000 --- a/Assets/FishNet/Runtime/Object/Synchronizing/WritePermissions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2696d0da2ff02e8499a8351a3021008f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Object/TransformProperties.cs b/Assets/FishNet/Runtime/Object/TransformProperties.cs deleted file mode 100644 index bbe05ee..0000000 --- a/Assets/FishNet/Runtime/Object/TransformProperties.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UnityEngine; - -namespace FishNet.Object -{ - [System.Serializable] - public struct TransformProperties - { - public readonly Vector3 Position; - public readonly Quaternion Rotation; - public readonly Vector3 LocalScale; - - public TransformProperties(Vector3 position, Quaternion rotation, Vector3 localScale) - { - Position = position; - Rotation = rotation; - LocalScale = localScale; - } - } -} - diff --git a/Assets/FishNet/Runtime/Object/TransformProperties.cs.meta b/Assets/FishNet/Runtime/Object/TransformProperties.cs.meta deleted file mode 100644 index ec7f7aa..0000000 --- a/Assets/FishNet/Runtime/Object/TransformProperties.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8e4ce2bc25fe8364d8b443f5ac7591ae -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing.meta b/Assets/FishNet/Runtime/Observing.meta deleted file mode 100644 index e4085bd..0000000 --- a/Assets/FishNet/Runtime/Observing.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e0cd196f74e1a994ebbc7a4cbd36eaf4 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/Conditions.meta b/Assets/FishNet/Runtime/Observing/Conditions.meta deleted file mode 100644 index 4b1cbbd..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 96ad2addbde8a81458e695b6797ae56e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/Conditions/DistanceCondition.cs b/Assets/FishNet/Runtime/Observing/Conditions/DistanceCondition.cs deleted file mode 100644 index c1c5ee8..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/DistanceCondition.cs +++ /dev/null @@ -1,143 +0,0 @@ -using FishNet.Connection; -using FishNet.Object; -using FishNet.Observing; -using FishNet.Utility.Extension; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Component.Observing -{ - /// - /// When this observer condition is placed on an object, a client must be within the specified distance to view the object. - /// - [CreateAssetMenu(menuName = "FishNet/Observers/Distance Condition", fileName = "New Distance Condition")] - public class DistanceCondition : ObserverCondition - { - #region Serialized. - /// - /// - /// - [Tooltip("Maximum distance a client must be within this object to see it.")] - [SerializeField] - private float _maximumDistance = 100f; - /// - /// Maximum distance a client must be within this object to see it. - /// - public float MaximumDistance { get => _maximumDistance; set => _maximumDistance = value; } - /// - /// Additional percent of distance client must be until this object is hidden. For example, if distance was 100f and percent was 0.5f the client must be 150f units away before this object is hidden again. This can be useful for keeping objects from regularly appearing and disappearing. - /// - [Tooltip("Additional percent of distance client must be until this object is hidden. For example, if distance was 100f and percent was 0.5f the client must be 150f units away before this object is hidden again. This can be useful for keeping objects from regularly appearing and disappearing.")] - [Range(0f, 1f)] - [SerializeField] - private float _hideDistancePercent = 0.1f; - /// - /// - /// - [Tooltip("How often this condition may change for a connection. This prevents objects from appearing and disappearing rapidly. A value of 0f will cause the object the update quickly as possible while any other value will be used as a delay.")] - [Range(0f, 60f)] - [SerializeField] - private float _updateFrequency; - /// - /// How often this condition may change for a connection. This prevents objects from appearing and disappearing rapidly. A value of 0f will cause the object the update quickly as possible while any other value will be used as a delay. - /// - public float UpdateFrequency { get => _updateFrequency; set => _updateFrequency = value; } - #endregion - - #region Private. - /// - /// Tracks when connections may be updated for this object. - /// - private Dictionary _timedUpdates = new Dictionary(); - #endregion - - public void ConditionConstructor(float maximumDistance, float updateFrequency) - { - MaximumDistance = maximumDistance; - _updateFrequency = updateFrequency; - } - - /// - /// Returns if the object which this condition resides should be visible to connection. - /// - /// Connection which the condition is being checked for. - /// True if the connection currently has visibility of this object. - /// True if the condition was not processed. This can be used to skip processing for performance. While output as true this condition result assumes the previous ConditionMet value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override bool ConditionMet(NetworkConnection connection, bool currentlyAdded, out bool notProcessed) - { - if (_updateFrequency > 0f) - { - float nextAllowedUpdate; - float currentTime = Time.time; - if (!_timedUpdates.TryGetValueIL2CPP(connection, out nextAllowedUpdate)) - { - _timedUpdates[connection] = (currentTime + _updateFrequency); - } - else - { - //Not enough time to process again. - if (currentTime < nextAllowedUpdate) - { - notProcessed = true; - //The return does not really matter since notProcessed is returned. - return false; - } - //Can process again. - else - { - _timedUpdates[connection] = (currentTime + _updateFrequency); - } - } - } - //If here then checks are being processed. - notProcessed = false; - - float sqrMaximumDistance; - /* If already visible then use additional - * distance to determine when to hide. */ - if (currentlyAdded) - { - float maxModified = (MaximumDistance * (1f + _hideDistancePercent)); - sqrMaximumDistance = (maxModified * maxModified); - } - //Not visible, use normal distance. - else - { - sqrMaximumDistance = (MaximumDistance * MaximumDistance); - } - - Vector3 thisPosition = NetworkObject.transform.position; - foreach (NetworkObject nob in connection.Objects) - { - //If within distance. - if (Vector3.SqrMagnitude(nob.transform.position - thisPosition) <= sqrMaximumDistance) - return true; - } - - /* If here no client objects are within distance. */ - return false; - } - - /// - /// True if the condition requires regular updates. - /// - /// - public override bool Timed() - { - return true; - } - - /// - /// Clones referenced ObserverCondition. This must be populated with your conditions settings. - /// - /// - public override ObserverCondition Clone() - { - DistanceCondition copy = ScriptableObject.CreateInstance(); - copy.ConditionConstructor(MaximumDistance, _updateFrequency); - return copy; - } - } -} diff --git a/Assets/FishNet/Runtime/Observing/Conditions/DistanceCondition.cs.meta b/Assets/FishNet/Runtime/Observing/Conditions/DistanceCondition.cs.meta deleted file mode 100644 index 0ee3ca9..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/DistanceCondition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7c3e28fa2e37d1d41b4f63c8a0cc2553 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/Conditions/HostOnlyCondition.cs b/Assets/FishNet/Runtime/Observing/Conditions/HostOnlyCondition.cs deleted file mode 100644 index 3de1c14..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/HostOnlyCondition.cs +++ /dev/null @@ -1,30 +0,0 @@ -using FishNet.Connection; -using FishNet.Observing; -using UnityEngine; - -namespace FishNet.Component.Observing -{ - [CreateAssetMenu(menuName = "FishNet/Observers/Host Only Condition", fileName = "New Host Only Condition")] - public class HostOnlyCondition : ObserverCondition - { - public override bool ConditionMet(NetworkConnection connection, bool currentlyAdded, out bool notProcessed) - { - notProcessed = false; - /* Only return true if connection is the local client. - * This check only runs on the server, so if local client - * is true then they must also be the server (clientHost). */ - return (base.NetworkObject.ClientManager.Connection == connection); - } - - public override bool Timed() - { - return false; - } - - public override ObserverCondition Clone() - { - HostOnlyCondition copy = ScriptableObject.CreateInstance(); - return copy; - } - } -} diff --git a/Assets/FishNet/Runtime/Observing/Conditions/HostOnlyCondition.cs.meta b/Assets/FishNet/Runtime/Observing/Conditions/HostOnlyCondition.cs.meta deleted file mode 100644 index 2af0f62..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/HostOnlyCondition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: aa62c0af0c0a4da46b03309dcd3858c3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/Conditions/MatchCondition.cs b/Assets/FishNet/Runtime/Observing/Conditions/MatchCondition.cs deleted file mode 100644 index c4b8f60..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/MatchCondition.cs +++ /dev/null @@ -1,585 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing; -using FishNet.Managing.Logging; -using FishNet.Managing.Server; -using FishNet.Object; -using FishNet.Observing; -using FishNet.Utility.Extension; -using FishNet.Utility.Performance; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Component.Observing -{ - /// - /// When this observer condition is placed on an object, a client must be within the same match to view the object. - /// - [CreateAssetMenu(menuName = "FishNet/Observers/Match Condition", fileName = "New Match Condition")] - public class MatchCondition : ObserverCondition - { - #region Private. - /// - /// - /// - private static Dictionary> _matchConnections = new Dictionary>(); - /// - /// Matches and connections in each match. - /// - public static IReadOnlyDictionary> MatchConnections => _matchConnections; - /// - /// - /// - /// //todo this needs to hold hashset so conns can be in multiple matches. - private static Dictionary _connectionMatch = new Dictionary(); - /// - /// Match a connection is in. - /// - public static IReadOnlyDictionary ConnectionMatch => _connectionMatch; - /// - /// - /// - private static Dictionary> _matchObjects = new Dictionary>(); - /// - /// Matches and connections in each match. - /// - public static IReadOnlyDictionary> MatchObjects => _matchObjects; - /// - /// - /// - /// //todo this needs to hold hashset so conns can be in multiple matches. - private static Dictionary _objectMatch = new Dictionary(); - /// - /// Match a connection is in. - /// - public static IReadOnlyDictionary ObjectMatch => _objectMatch; - #endregion - - public void ConditionConstructor() { } - - #region Add to match NetworkConnection. - /// - /// Adds a connection to a match. - /// - /// Match to add conn to. - /// Connection to add to match. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - /// True to replace other matches with the new match. - public static void AddToMatch(int match, NetworkConnection conn, NetworkManager manager = null, bool replaceMatch = false) - { - if (replaceMatch) - RemoveFromMatchWithoutRebuild(conn, manager); - - HashSet results; - if (!_matchConnections.TryGetValueIL2CPP(match, out results)) - { - results = new HashSet(); - _matchConnections.Add(match, results); - } - - bool r = results.Add(conn); - _connectionMatch[conn] = match; - if (r) - FinalizeChange(match, results, manager); - } - /// - /// Adds connections to a match. - /// - /// Match to add conns to. - /// Connections to add to match. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - /// True to replace other matches with the new match. - public static void AddToMatch(int match, NetworkConnection[] conns, NetworkManager manager = null, bool replaceMatch = false) - { - AddToMatch(match, conns.ToList(), manager, replaceMatch); - } - /// - /// Adds connections to a match. - /// - /// Match to add conns to. - /// Connections to add to match. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - /// True to replace other matches with the new match. - public static void AddToMatch(int match, List conns, NetworkManager manager = null, bool replaceMatch = false) - { - if (replaceMatch) - { - foreach (NetworkConnection nc in conns) - RemoveFromMatchWithoutRebuild(nc, manager); - } - - HashSet results; - if (!_matchConnections.TryGetValueIL2CPP(match, out results)) - { - results = new HashSet(); - _matchConnections.Add(match, results); - } - - bool r = false; - for (int i = 0; i < conns.Count; i++) - { - NetworkConnection c = conns[i]; - r |= results.Add(c); - _connectionMatch[c] = match; - } - - if (r) - FinalizeChange(match, results, manager); - } - #endregion - - #region Add to match NetworkObject. - /// - /// Adds an object to a match. - /// - /// Match to add conn to. - /// Connection to add to match. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - /// True to replace other matches with the new match. - public static void AddToMatch(int match, NetworkObject nob, NetworkManager manager = null, bool replaceMatch = false) - { - if (replaceMatch) - RemoveFromMatchWithoutRebuild(nob, manager); - - HashSet results; - if (!_matchObjects.TryGetValueIL2CPP(match, out results)) - { - results = new HashSet(); - _matchObjects.Add(match, results); - } - - bool r = results.Add(nob); - _objectMatch[nob] = match; - - if (r) - FinalizeChange(match, results, nob, manager); - } - /// - /// Adds objects to a match. - /// - /// Match to add conns to. - /// Connections to add to match. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - /// True to replace other matches with the new match. - public static void AddToMatch(int match, NetworkObject[] nobs, NetworkManager manager = null, bool replaceMatch = false) - { - AddToMatch(match, nobs.ToList(), manager, replaceMatch); - } - /// - /// Adds objects to a match. - /// - /// Match to add conns to. - /// Connections to add to match. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - /// True to replace other matches with the new match. - public static void AddToMatch(int match, List nobs, NetworkManager manager = null, bool replaceMatch = false) - { - if (replaceMatch) - { - foreach (NetworkObject n in nobs) - RemoveFromMatchWithoutRebuild(n, manager); - } - - HashSet results; - if (!_matchObjects.TryGetValueIL2CPP(match, out results)) - { - results = new HashSet(); - _matchObjects.Add(match, results); - } - - bool r = false; - for (int i = 0; i < nobs.Count; i++) - { - NetworkObject n = nobs[i]; - r |= results.Add(n); - _objectMatch[n] = match; - } - - if (r) - FinalizeChange(match, results, nobs, manager); - } - #endregion - - #region Remove from match NetworkConnection. - /// - /// Removes a connection from any match without rebuilding observers. - /// - /// Connection to remove from matches. - /// NetworkManager connection belongs to. This is not currently used. - internal static bool RemoveFromMatchWithoutRebuild(NetworkConnection conn, NetworkManager manager) - { - bool removed = false; - //If found to be in a match. - if (_connectionMatch.TryGetValueIL2CPP(conn, out int match)) - { - //If match is found. - if (_matchConnections.TryGetValue(match, out HashSet conns)) - { - removed |= conns.Remove(conn); - //If no more in hashset remove match. - if (conns.Count == 0) - _matchConnections.Remove(match); - } - } - - //Remove from connectionMatch. - _connectionMatch.Remove(conn); - return removed; - } - /// - /// Removes a connection from all matches. - /// - /// NetworkConnection to remove. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - public static void RemoveFromMatch(NetworkConnection conn, NetworkManager manager) - { - bool removed = RemoveFromMatchWithoutRebuild(conn, manager); - if (removed) - GetServerObjects(manager).RebuildObservers(); - } - /// - /// Removes a connection from a match. - /// - /// Match to remove conn from. - /// Connection to remove from match. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemoveFromMatch(int match, NetworkConnection conn, NetworkManager manager) - { - if (_matchConnections.TryGetValueIL2CPP(match, out HashSet results)) - { - bool r = results.Remove(conn); - _connectionMatch.Remove(conn); - if (r) - FinalizeChange(match, results, manager); - } - } - /// - /// Removes connections from a match. - /// - /// Match to remove conns from. - /// Connections to remove from match. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemoveFromMatch(int match, NetworkConnection[] conns, NetworkManager manager) - { - if (_matchConnections.TryGetValueIL2CPP(match, out HashSet results)) - { - bool r = false; - for (int i = 0; i < conns.Length; i++) - { - NetworkConnection c = conns[i]; - r |= results.Remove(c); - _connectionMatch.Remove(c); - } - - if (r) - FinalizeChange(match, results, manager); - } - } - /// - /// Removes connections from a match. - /// - /// Match to remove conns from. - /// Connections to remove from match. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemoveFromMatch(int match, List conns, NetworkManager manager) - { - if (_matchConnections.TryGetValueIL2CPP(match, out HashSet results)) - { - bool r = false; - for (int i = 0; i < conns.Count; i++) - { - NetworkConnection c = conns[i]; - r |= results.Remove(c); - _connectionMatch.Remove(c); - } - - if (r) - FinalizeChange(match, results, manager); - } - } - #endregion - - #region Remove from match NetworkObject. - /// - /// Removes a network object from any match without rebuilding observers. - /// - /// NetworkObject to remove. - /// Manager which the network object belongs to. This value is not yet used. - internal static bool RemoveFromMatchWithoutRebuild(NetworkObject nob, NetworkManager manager = null) - { - bool removed = false; - //If found to be in a match. - if (_objectMatch.TryGetValueIL2CPP(nob, out int match)) - { - //If match is found. - if (_matchObjects.TryGetValue(match, out HashSet nobs)) - { - removed |= nobs.Remove(nob); - //If no more in hashset remove match. - if (nobs.Count == 0) - _matchObjects.Remove(match); - } - } - - //Remove from connectionMatch. - _objectMatch.Remove(nob); - return removed; - } - /// - /// Removes nob from all matches. - /// - /// NetworkObject to remove. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - public static void RemoveFromMatch(NetworkObject nob, NetworkManager manager = null) - { - bool removed = RemoveFromMatchWithoutRebuild(nob, manager); - if (removed) - GetServerObjects(manager).RebuildObservers(nob); - } - /// - /// Removes a network object from all matches. - /// - /// NetworkObjects to remove. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - public static void RemoveFromMatch(NetworkObject[] nobs, NetworkManager manager = null) - { - RemoveFromMatch(nobs.ToList(), manager); - } - /// - /// Removes network objects from all matches. - /// - /// NetworkObjects to remove. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - public static void RemoveFromMatch(List nobs, NetworkManager manager = null) - { - bool removed = false; - foreach (NetworkObject n in nobs) - removed |= RemoveFromMatchWithoutRebuild(n, manager); - - if (removed) - GetServerObjects(manager).RebuildObservers(nobs); - } - /// - /// Removes a network object from a match. - /// - /// Match to remove conn from. - /// NetworkObject to remove from match. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemoveFromMatch(int match, NetworkObject nob, NetworkManager manager = null) - { - if (_matchObjects.TryGetValueIL2CPP(match, out HashSet results)) - { - bool r = results.Remove(nob); - _objectMatch.Remove(nob); - if (r) - FinalizeChange(match, results, nob, manager); - } - } - /// - /// Removes network objects from a match. - /// - /// Match to remove conns from. - /// NetworkObjects to remove from match. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemoveFromMatch(int match, NetworkObject[] nobs, NetworkManager manager = null) - { - if (_matchObjects.TryGetValueIL2CPP(match, out HashSet results)) - { - bool r = false; - for (int i = 0; i < nobs.Length; i++) - { - NetworkObject n = nobs[i]; - r |= results.Remove(n); - _objectMatch.Remove(n); - } - - if (r) - FinalizeChange(match, results, nobs, manager); - } - } - /// - /// Removes network objects from a match. - /// - /// Match to remove conns from. - /// NetworkObjects to remove from match. - /// NetworkManager to rebuild observers on. If null InstanceFinder.NetworkManager will be used. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemoveFromMatch(int match, List nobs, NetworkManager manager = null) - { - if (_matchObjects.TryGetValueIL2CPP(match, out HashSet results)) - { - bool r = false; - for (int i = 0; i < nobs.Count; i++) - { - NetworkObject n = nobs[i]; - r |= results.Remove(n); - _objectMatch.Remove(n); - } - - if (r) - FinalizeChange(match, results, nobs, manager); - } - } - #endregion - - #region FinalizeChange NetworkConnection. - /// - /// Finalizes changes to observers. - /// - private static void FinalizeChange(int match, HashSet remainingConnsInMatch, NetworkManager manager) - { - if (remainingConnsInMatch.Count == 0) - _matchConnections.Remove(match); - - /* Observers on all objects and all conditions have to be rebuilt. - * This is because the connection changing matches could - * require the connection to be visible for other players in the match, - * as well make other connections in the same match visible. - * But also make all the objects not associated with connections - * of that match visible. In result to tick all of those boxes - * all objects need to be rebuilt for all connections. */ - GetServerObjects(manager).RebuildObservers(); - } - #endregion - - #region FinalizeChange NetworkObject. - /// - /// Finalizes changes to observers. - /// - private static void FinalizeChange(int match, HashSet results, List nobs, NetworkManager manager) - { - ListCache cache = ListCaches.GetNetworkObjectCache(); - cache.AddValues(nobs); - FinalizeChange(match, results, cache, manager); - ListCaches.StoreCache(cache); - } - /// - /// Finalizes changes to observers. - /// - private static void FinalizeChange(int match, HashSet results, NetworkObject[] nobs, NetworkManager manager) - { - ListCache cache = ListCaches.GetNetworkObjectCache(); - cache.AddValues(nobs); - FinalizeChange(match, results, cache, manager); - ListCaches.StoreCache(cache); - } - /// - /// Finalizes changes to observers. - /// - private static void FinalizeChange(int match, HashSet results, NetworkObject nob, NetworkManager manager) - { - ListCache cache = ListCaches.GetNetworkObjectCache(); - cache.AddValue(nob); - FinalizeChange(match, results, cache, manager); - ListCaches.StoreCache(cache); - } - /// - /// Finalizes changes to observers. - /// - private static void FinalizeChange(int match, HashSet results, ListCache nobs, NetworkManager manager) - { - if (results.Count == 0) - _matchConnections.Remove(match); - - GetServerObjects(manager).RebuildObservers(nobs); - } - #endregion - - /// - /// Returns if the object which this condition resides should be visible to connection. - /// - /// Connection which the condition is being checked for. - /// True if the connection currently has visibility of this object. - /// True if the condition was not processed. This can be used to skip processing for performance. While output as true this condition result assumes the previous ConditionMet value. - public override bool ConditionMet(NetworkConnection connection, bool alreadyAdded, out bool notProcessed) - { - //If here then checks are being processed. - notProcessed = false; - NetworkConnection owner = base.NetworkObject.Owner; - /* If object is owned then check if owner - * and connection share a match. */ - if (owner.IsValid) - { - //Connection isn't in a match. - if (!_connectionMatch.TryGetValueIL2CPP(connection, out int match)) - { - //Return if this owner is also not in a match. - return !_connectionMatch.TryGetValueIL2CPP(owner, out int _); - } - //Match isn't found. - if (!_matchConnections.TryGetValueIL2CPP(match, out HashSet conns)) - return false; - //If owner is in same match return true. - return conns.Contains(owner); - } - /* If no owner see if the object is in a match and if so - * then compare that. */ - else - { - //Object isn't in a match. - if (!_objectMatch.TryGetValueIL2CPP(base.NetworkObject, out int objectMatch)) - return true; - /* See if connection is in the same match as the object. - * If connection isn't in a match then it fails. */ - if (!_connectionMatch.TryGetValueIL2CPP(connection, out int connectionMatch)) - return false; - return (connectionMatch == objectMatch); - } - } - - - /// - /// Returns which ServerObjects to rebuild observers on. - /// - /// - /// - private static ServerObjects GetServerObjects(NetworkManager manager) - { - return (manager == null) ? InstanceFinder.ServerManager.Objects : manager.ServerManager.Objects; - } - - - /* //todo this needs to be passing in the network manager to clear on, - * otherwise only a single instance of NM is supported. - * Users are already forced to specify which NM to add - * matches for but the functionality separating different NMs in relation - * to such isn't done yet. */ - /// - /// Clears all match information without rebuilding. - /// - internal static void ClearMatchesWithoutRebuilding() - { - _connectionMatch.Clear(); - _matchConnections.Clear(); - _objectMatch.Clear(); - _matchObjects.Clear(); - } - - - /// - /// True if the condition requires regular updates. - /// - /// - public override bool Timed() - { - return false; - } - - /// - /// Clones referenced ObserverCondition. This must be populated with your conditions settings. - /// - /// - public override ObserverCondition Clone() - { - MatchCondition copy = ScriptableObject.CreateInstance(); - copy.ConditionConstructor(); - return copy; - } - } -} diff --git a/Assets/FishNet/Runtime/Observing/Conditions/MatchCondition.cs.meta b/Assets/FishNet/Runtime/Observing/Conditions/MatchCondition.cs.meta deleted file mode 100644 index 60e6e9e..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/MatchCondition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5afdd6c2de1c76f4faa6840cc29fda8a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/Conditions/OwnerOnlyCondition.cs b/Assets/FishNet/Runtime/Observing/Conditions/OwnerOnlyCondition.cs deleted file mode 100644 index bd3a7ec..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/OwnerOnlyCondition.cs +++ /dev/null @@ -1,47 +0,0 @@ -using FishNet.Connection; -using FishNet.Observing; -using UnityEngine; - -namespace FishNet.Component.Observing -{ - /// - /// This condition makes an object only visible to the owner. - /// - [CreateAssetMenu(menuName = "FishNet/Observers/Owner Only Condition", fileName = "New Owner Only Condition")] - public class OwnerOnlyCondition : ObserverCondition - { - - /// - /// Returns if the object which this condition resides should be visible to connection. - /// - /// Connection which the condition is being checked for. - /// True if the connection currently has visibility of this object. - /// True if the condition was not processed. This can be used to skip processing for performance. While output as true this condition result assumes the previous ConditionMet value. - public override bool ConditionMet(NetworkConnection connection, bool currentlyAdded, out bool notProcessed) - { - notProcessed = false; - /* Returning false immediately indicates no connection will - * meet this condition. */ - return false; - } - - /// - /// True if the condition requires regular updates. - /// - /// - public override bool Timed() - { - return false; - } - - /// - /// Clones referenced ObserverCondition. This must be populated with your conditions settings. - /// - /// - public override ObserverCondition Clone() - { - OwnerOnlyCondition copy = ScriptableObject.CreateInstance(); - return copy; - } - } -} diff --git a/Assets/FishNet/Runtime/Observing/Conditions/OwnerOnlyCondition.cs.meta b/Assets/FishNet/Runtime/Observing/Conditions/OwnerOnlyCondition.cs.meta deleted file mode 100644 index 3a99b3d..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/OwnerOnlyCondition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1ca3d8a36a10fd344806a2df999f3eda -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/Conditions/SceneCondition.cs b/Assets/FishNet/Runtime/Observing/Conditions/SceneCondition.cs deleted file mode 100644 index f049814..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/SceneCondition.cs +++ /dev/null @@ -1,88 +0,0 @@ -using FishNet.Connection; -using FishNet.Observing; -using UnityEngine; -using UnityEngine.SceneManagement; - -namespace FishNet.Component.Observing -{ - - /// - /// When this observer condition is placed on an object, a client must be within the same scene to view the object. - /// - [CreateAssetMenu(menuName = "FishNet/Observers/Scene Condition", fileName = "New Scene Condition")] - public class SceneCondition : ObserverCondition - { - #region Serialized. - ///// - ///// True to synchronize which scene the object was spawned in to clients. When true this object will be moved to the clients equivelant of the scene it was spawned in on the server. This setting does not continously move this object to the same scene. - ///// - //[Tooltip("True to synchronize which scene the object was spawned in to clients. When true this object will be moved to the clients equivelant of the scene it was spawned in on the server. This setting does not continously move this object to the same scene.")] - //[SerializeField] - //private bool _synchronizeScene; - #endregion - - public void ConditionConstructor() - { - //_synchronizeScene = synchronizeScene; - } - - /// - /// Returns if the object which this condition resides should be visible to connection. - /// - /// Connection which the condition is being checked for. - /// True if the connection currently has visibility of this object. - /// True if the condition was not processed. This can be used to skip processing for performance. While output as true this condition result assumes the previous ConditionMet value. - public override bool ConditionMet(NetworkConnection connection, bool currentlyAdded, out bool notProcessed) - { - notProcessed = false; - /* If this objects connection is valid then check if - * connection and this objects owner shares any scenes. - * Don't check if the object resides in the same scene - * because thats not reliable as server might be moving - * objects. */ - if (base.NetworkObject.Owner.IsValid) - { - foreach (Scene s in base.NetworkObject.Owner.Scenes) - { - //Scenes match. - if (connection.Scenes.Contains(s)) - return true; - } - - //Fall through, no scenes shared. - return false; - } - /* If there is no owner as a fallback see if - * the connection is in the same scene as this object. */ - else - { - /* When there is no owner only then is the gameobject - * scene checked. That's the only way to know at this point. */ - return connection.Scenes.Contains(base.NetworkObject.gameObject.scene); - } - } - - /// - /// True if the condition requires regular updates. - /// - /// - public override bool Timed() - { - return false; - } - - - /// - /// Clones referenced ObserverCondition. This must be populated with your conditions settings. - /// - /// - public override ObserverCondition Clone() - { - SceneCondition copy = ScriptableObject.CreateInstance(); - //copy.ConditionConstructor(_synchronizeScene); - copy.ConditionConstructor(); - return copy; - } - - } -} diff --git a/Assets/FishNet/Runtime/Observing/Conditions/SceneCondition.cs.meta b/Assets/FishNet/Runtime/Observing/Conditions/SceneCondition.cs.meta deleted file mode 100644 index edff5be..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/SceneCondition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fab85d1c51ee2c344b7dd914dc262ec4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects.meta b/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects.meta deleted file mode 100644 index 35a6fe4..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 3d6d71fdcee27584d8d47bef4455a5f9 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/DistanceCondition.asset b/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/DistanceCondition.asset deleted file mode 100644 index 10a9cb4..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/DistanceCondition.asset +++ /dev/null @@ -1,18 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 7c3e28fa2e37d1d41b4f63c8a0cc2553, type: 3} - m_Name: DistanceCondition - m_EditorClassIdentifier: - NetworkObject: {fileID: 0} - _maximumDistance: 10 - _hideDistancePercent: 0.1 - _updateFrequency: 0 diff --git a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/DistanceCondition.asset.meta b/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/DistanceCondition.asset.meta deleted file mode 100644 index 1ba0a6e..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/DistanceCondition.asset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 5f33eb0e5b83b5546822cfe42a305657 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 11400000 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/HostOnlyCondition.asset b/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/HostOnlyCondition.asset deleted file mode 100644 index 939ae62..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/HostOnlyCondition.asset +++ /dev/null @@ -1,15 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: aa62c0af0c0a4da46b03309dcd3858c3, type: 3} - m_Name: HostOnlyCondition - m_EditorClassIdentifier: - NetworkObject: {fileID: 0} diff --git a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/HostOnlyCondition.asset.meta b/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/HostOnlyCondition.asset.meta deleted file mode 100644 index 497d938..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/HostOnlyCondition.asset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 9ff842b44ec59314d9efcecbcdbaac04 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 11400000 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/MatchCondition.asset b/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/MatchCondition.asset deleted file mode 100644 index 0d44d4f..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/MatchCondition.asset +++ /dev/null @@ -1,15 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5afdd6c2de1c76f4faa6840cc29fda8a, type: 3} - m_Name: MatchCondition - m_EditorClassIdentifier: - NetworkObject: {fileID: 0} diff --git a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/MatchCondition.asset.meta b/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/MatchCondition.asset.meta deleted file mode 100644 index 39dd07a..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/MatchCondition.asset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: efcd7f0dfd341ed4e8671079e91e0544 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 11400000 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/OwnerOnlyCondition.asset b/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/OwnerOnlyCondition.asset deleted file mode 100644 index 625e5f1..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/OwnerOnlyCondition.asset +++ /dev/null @@ -1,15 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 1ca3d8a36a10fd344806a2df999f3eda, type: 3} - m_Name: OwnerOnlyCondition - m_EditorClassIdentifier: - NetworkObject: {fileID: 0} diff --git a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/OwnerOnlyCondition.asset.meta b/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/OwnerOnlyCondition.asset.meta deleted file mode 100644 index 389066f..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/OwnerOnlyCondition.asset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: bcf92670d91dbb74dad77c56b9b8712e -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 11400000 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/SceneCondition.asset b/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/SceneCondition.asset deleted file mode 100644 index 0877337..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/SceneCondition.asset +++ /dev/null @@ -1,17 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fab85d1c51ee2c344b7dd914dc262ec4, type: 3} - m_Name: SceneCondition - m_EditorClassIdentifier: - NetworkObject: {fileID: 0} - _synchronizeScene: 1 - _timed: 0 diff --git a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/SceneCondition.asset.meta b/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/SceneCondition.asset.meta deleted file mode 100644 index 6cc77dd..0000000 --- a/Assets/FishNet/Runtime/Observing/Conditions/ScriptableObjects/SceneCondition.asset.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 2033f54fd2794464bae08fa5a55c8996 -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 11400000 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/HostVisibilityUpdateTypes.cs b/Assets/FishNet/Runtime/Observing/HostVisibilityUpdateTypes.cs deleted file mode 100644 index 4699aca..0000000 --- a/Assets/FishNet/Runtime/Observing/HostVisibilityUpdateTypes.cs +++ /dev/null @@ -1,17 +0,0 @@ - -namespace FishNet.Observing -{ - [System.Flags] - public enum HostVisibilityUpdateTypes : byte - { - /// - /// Include this flag to update manager. - /// - Manager = 1, - /// - /// Include this flag to update spawned. - /// - Spawned = 2, - } - -} diff --git a/Assets/FishNet/Runtime/Observing/HostVisibilityUpdateTypes.cs.meta b/Assets/FishNet/Runtime/Observing/HostVisibilityUpdateTypes.cs.meta deleted file mode 100644 index 671c6cb..0000000 --- a/Assets/FishNet/Runtime/Observing/HostVisibilityUpdateTypes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: dc90636a96cf14d47812768a9ce3a4d8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/NetworkObserver.cs b/Assets/FishNet/Runtime/Observing/NetworkObserver.cs deleted file mode 100644 index 7ad3657..0000000 --- a/Assets/FishNet/Runtime/Observing/NetworkObserver.cs +++ /dev/null @@ -1,404 +0,0 @@ -using FishNet.Connection; -using FishNet.Documenting; -using FishNet.Object; -using FishNet.Transporting; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; -using UnityEngine.Serialization; - -namespace FishNet.Observing -{ - /// - /// Controls which clients can see and get messages for an object. - /// - [DisallowMultipleComponent] - [AddComponentMenu("FishNet/Component/NetworkObserver")] - public sealed class NetworkObserver : MonoBehaviour - { - #region Types. - /// - /// How ObserverManager conditions are used. - /// - public enum ConditionOverrideType - { - /// - /// Keep current conditions, add new conditions from manager. - /// - AddMissing = 1, - /// - /// Replace current conditions with manager conditions. - /// - UseManager = 2, - /// - /// Keep current conditions, ignore manager conditions. - /// - IgnoreManager = 3, - } - #endregion - - #region Serialized. - /// - /// - /// - [Tooltip("How ObserverManager conditions are used.")] - [SerializeField] - private ConditionOverrideType _overrideType = ConditionOverrideType.IgnoreManager; - /// - /// How ObserverManager conditions are used. - /// - public ConditionOverrideType OverrideType - { - get => _overrideType; - internal set => _overrideType = value; - } - - /// - /// - /// - [Tooltip("True to update visibility for clientHost based on if they are an observer or not.")] - [FormerlySerializedAs("_setHostVisibility")] - [SerializeField] - private bool _updateHostVisibility = true; - /// - /// True to update visibility for clientHost based on if they are an observer or not. - /// - public bool UpdateHostVisibility - { - get => _updateHostVisibility; - private set => _updateHostVisibility = value; - } - /// - /// - /// - [Tooltip("Conditions connections must met to be added as an observer. Multiple conditions may be used.")] - [SerializeField] - internal List _observerConditions = new List(); - /// - /// Conditions connections must met to be added as an observer. Multiple conditions may be used. - /// - public IReadOnlyList ObserverConditions => _observerConditions; - [APIExclude] -#if MIRROR - public List ObserverConditionsInternal -#else - internal List ObserverConditionsInternal -#endif - { - get => _observerConditions; - set => _observerConditions = value; - } - #endregion - - #region Private. - /// - /// Conditions under this component which are timed. - /// - private List _timedConditions = new List(); - /// - /// Connections which have all non-timed conditions met. - /// - private HashSet _nonTimedMet = new HashSet(); - /// - /// NetworkObject this belongs to. - /// - private NetworkObject _networkObject; - /// - /// Becomes true when registered with ServerObjects as Timed observers. - /// - private bool _registeredAsTimed; - /// - /// True if already pre-initialized. - /// - private bool _preintiialized; - /// - /// True if ParentNetworkObject was visible last iteration. - /// This value will also be true if there is no ParentNetworkObject. - /// - private bool _lastParentVisible; - #endregion - - private void OnEnable() - { - if (_networkObject != null && _networkObject.IsServer) - RegisterTimedConditions(); - } - private void OnDisable() - { - if (_networkObject != null && _networkObject.IsDeinitializing) - { - _lastParentVisible = false; - _nonTimedMet.Clear(); - UnregisterTimedConditions(); - } - } - private void OnDestroy() - { - if (_networkObject != null) - UnregisterTimedConditions(); - } - - internal void Deinitialize() - { - if (_networkObject != null && _networkObject.IsDeinitializing) - { - _networkObject.ServerManager.OnRemoteConnectionState -= ServerManager_OnRemoteConnectionState; - UnregisterTimedConditions(); - } - } - - /// - /// Initializes this script for use. - /// - /// - internal void PreInitialize(NetworkObject networkObject) - { - if (!_preintiialized) - { - _preintiialized = true; - _networkObject = networkObject; - bool ignoringManager = (OverrideType == ConditionOverrideType.IgnoreManager); - - //Check to override SetHostVisibility. - if (!ignoringManager) - UpdateHostVisibility = networkObject.ObserverManager.UpdateHostVisibility; - - bool observerFound = false; - for (int i = 0; i < _observerConditions.Count; i++) - { - if (_observerConditions[i] != null) - { - observerFound = true; - - /* Make an instance of each condition so values are - * not overwritten when the condition exist more than - * once in the scene. Double edged sword of using scriptable - * objects for conditions. */ - _observerConditions[i] = _observerConditions[i].Clone(); - ObserverCondition oc = _observerConditions[i]; - oc.InitializeOnce(_networkObject); - //If timed also register as containing timed conditions. - if (oc.Timed()) - _timedConditions.Add(oc); - } - else - { - _observerConditions.RemoveAt(i); - i--; - } - } - - //No observers specified, do not need to take further action. - if (!observerFound) - return; - - _networkObject.ServerManager.OnRemoteConnectionState += ServerManager_OnRemoteConnectionState; - } - - RegisterTimedConditions(); - } - - /// - /// Returns a condition if found within Conditions. - /// - /// - public ObserverCondition GetObserverCondition() where T : ObserverCondition - { - /* Do not bother setting local variables, - * condition collections aren't going to be long - * enough to make doing so worth while. */ - - System.Type conditionType = typeof(T); - for (int i = 0; i < _observerConditions.Count; i++) - { - if (_observerConditions[i].GetType() == conditionType) - return _observerConditions[i]; - } - - //Fall through, not found. - return null; - } - - /// - /// Returns ObserverStateChange by comparing conditions for a connection. - /// - /// True if added to Observers. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal ObserverStateChange RebuildObservers(NetworkConnection connection, bool timedOnly) - { - bool currentlyAdded = (_networkObject.Observers.Contains(connection)); - //True if all conditions are met. - bool allConditionsMet = true; - - //Only need to check beyond this if conditions exist. - if (_observerConditions.Count > 0) - { - /* If cnnection is owner then they can see the object. */ - bool notOwner = (connection != _networkObject.Owner); - - /* Only check conditions if not owner. Owner will always - * have visibility. */ - if (notOwner) - { - bool parentVisible = true; - if (_networkObject.ParentNetworkObject != null) - { - parentVisible = _networkObject.ParentNetworkObject.Observers.Contains(connection); - /* If parent is visible but was not previously - * then unset timedOnly to make sure all conditions - * are checked again. This ensures that the _nonTimedMet - * collection is updated. */ - if (parentVisible && !_lastParentVisible) - timedOnly = false; - _lastParentVisible = parentVisible; - } - - //If parent is not visible no further checks are required. - if (!parentVisible) - { - allConditionsMet = false; - } - //Parent is visible, perform checks. - else - { - //True if connection starts with meeting non-timed conditions. - bool startNonTimedMet = _nonTimedMet.Contains(connection); - /* If a timed update an1d nonTimed - * have not been met then there's - * no reason to check timed. */ - if (timedOnly && !startNonTimedMet) - { - allConditionsMet = false; - } - else - { - //Becomes true if a non-timed condition fails. - bool nonTimedMet = true; - - List collection = (timedOnly) ? _timedConditions : _observerConditions; - for (int i = 0; i < collection.Count; i++) - { - ObserverCondition condition = collection[i]; - /* If any observer returns removed then break - * from loop and return removed. If one observer has - * removed then there's no reason to iterate - * the rest. - * - * A condition is automatically met if it's not enabled. */ - bool notProcessed = false; - bool conditionMet = (!condition.GetIsEnabled() || condition.ConditionMet(connection, currentlyAdded, out notProcessed)); - - if (notProcessed) - conditionMet = currentlyAdded; - - //Condition not met. - if (!conditionMet) - { - allConditionsMet = false; - if (!condition.Timed()) - nonTimedMet = false; - break; - } - } - - //If all conditions are being checked and nonTimedMet has updated. - if (!timedOnly && (startNonTimedMet != nonTimedMet)) - { - if (nonTimedMet) - _nonTimedMet.Add(connection); - else - _nonTimedMet.Remove(connection); - } - } - } - } - } - - //If all conditions met. - if (allConditionsMet) - return ReturnPassedConditions(currentlyAdded); - else - return ReturnFailedCondition(currentlyAdded); - } - - /// - /// Registers timed observer conditions. - /// - private void RegisterTimedConditions() - { - if (_timedConditions.Count == 0) - return; - //Already registered or no timed conditions. - if (_registeredAsTimed) - return; - - _registeredAsTimed = true; - _networkObject.NetworkManager.ServerManager.Objects.AddTimedNetworkObserver(_networkObject); - } - - /// - /// Unregisters timed conditions. - /// - private void UnregisterTimedConditions() - { - if (_timedConditions.Count == 0) - return; - if (!_registeredAsTimed) - return; - - _registeredAsTimed = false; - _networkObject.NetworkManager.ServerManager.Objects.RemoveTimedNetworkObserver(_networkObject); - } - - /// - /// Returns an ObserverStateChange when a condition fails. - /// - /// - /// - private ObserverStateChange ReturnFailedCondition(bool currentlyAdded) - { - if (currentlyAdded) - return ObserverStateChange.Removed; - else - return ObserverStateChange.Unchanged; - } - - /// - /// Returns an ObserverStateChange when all conditions pass. - /// - /// - /// - private ObserverStateChange ReturnPassedConditions(bool currentlyAdded) - { - if (currentlyAdded) - return ObserverStateChange.Unchanged; - else - return ObserverStateChange.Added; - } - - /// - /// Called when a remote client state changes with the server. - /// - private void ServerManager_OnRemoteConnectionState(NetworkConnection conn, RemoteConnectionStateArgs arg2) - { - if (arg2.ConnectionState == RemoteConnectionState.Stopped) - _nonTimedMet.Remove(conn); - } - - /// - /// Sets a new value for UpdateHostVisibility. - /// This does not immediately update renderers. - /// You may need to combine with NetworkObject.SetRenderersVisible(bool). - /// - /// New value. - public void SetUpdateHostVisibility(bool value) - { - //Unchanged. - if (value == UpdateHostVisibility) - return; - - UpdateHostVisibility = value; - } - - } -} diff --git a/Assets/FishNet/Runtime/Observing/NetworkObserver.cs.meta b/Assets/FishNet/Runtime/Observing/NetworkObserver.cs.meta deleted file mode 100644 index 0809554..0000000 --- a/Assets/FishNet/Runtime/Observing/NetworkObserver.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c71fd7f855ec523429999fc4e14a1928 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/ObserverCondition.cs b/Assets/FishNet/Runtime/Observing/ObserverCondition.cs deleted file mode 100644 index 0c0fad4..0000000 --- a/Assets/FishNet/Runtime/Observing/ObserverCondition.cs +++ /dev/null @@ -1,81 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing.Server; -using FishNet.Object; -using UnityEngine; - -namespace FishNet.Observing -{ - /// - /// Condition a connection must meet to be added as an observer. - /// This class can be inherited from for custom conditions. - /// - public abstract class ObserverCondition : ScriptableObject - { - #region Public. - /// - /// NetworkObject this condition is for. - /// - [HideInInspector] - public NetworkObject NetworkObject; - #endregion - - #region Private. - /// - /// True if this condition is enabled. - /// - private bool _isEnabled = true; - /// - /// Gets the enabled state of this condition. - /// - /// - public bool GetIsEnabled() => _isEnabled; - /// - /// Sets the enabled state of this condition. - /// If the state has changed observers will be rebuilt - /// for this object. - /// - /// - public void SetIsEnabled(bool value) - { - if (value == GetIsEnabled()) - return; - - _isEnabled = value; - //No object to rebuild for. - if (NetworkObject == null) - return; - - ServerObjects so = NetworkObject?.ServerManager?.Objects; - if (so != null) - so.RebuildObservers(NetworkObject); - } - #endregion - - /// - /// Initializes this script for use. - /// - /// - public virtual void InitializeOnce(NetworkObject networkObject) - { - NetworkObject = networkObject; - } - /// - /// Returns if the object which this condition resides should be visible to connection. - /// - /// Connection which the condition is being checked for. - /// True if the connection currently has visibility of this object. - /// True if the condition was not processed. This can be used to skip processing for performance. While output as true this condition result assumes the previous ConditionMet value. - public abstract bool ConditionMet(NetworkConnection connection, bool currentlyAdded, out bool notProcessed); - /// - /// True if the condition requires regular updates. - /// - /// - public abstract bool Timed(); - /// - /// Creates a clone of this condition to be instantiated. - /// - /// - public abstract ObserverCondition Clone(); - - } -} diff --git a/Assets/FishNet/Runtime/Observing/ObserverCondition.cs.meta b/Assets/FishNet/Runtime/Observing/ObserverCondition.cs.meta deleted file mode 100644 index 08b27fe..0000000 --- a/Assets/FishNet/Runtime/Observing/ObserverCondition.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7d496d4febcb07f4abbdc081eaa99234 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Observing/ObserverStateChange.cs b/Assets/FishNet/Runtime/Observing/ObserverStateChange.cs deleted file mode 100644 index d783cc3..0000000 --- a/Assets/FishNet/Runtime/Observing/ObserverStateChange.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace FishNet.Observing -{ - /// - /// States which observer(s) can change to. - /// - internal enum ObserverStateChange : byte - { - Unchanged = 0, - Added = 1, - Removed = 2 - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Observing/ObserverStateChange.cs.meta b/Assets/FishNet/Runtime/Observing/ObserverStateChange.cs.meta deleted file mode 100644 index 4529100..0000000 --- a/Assets/FishNet/Runtime/Observing/ObserverStateChange.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a4a8dca28b7d84548a918c5c32f684ad -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins.meta b/Assets/FishNet/Runtime/Plugins.meta deleted file mode 100644 index 0e82d79..0000000 --- a/Assets/FishNet/Runtime/Plugins.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: fc3a5558e3b83cc41a1f450b12e9ac14 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/ColliderRollback.meta b/Assets/FishNet/Runtime/Plugins/ColliderRollback.meta deleted file mode 100644 index fc14e86..0000000 --- a/Assets/FishNet/Runtime/Plugins/ColliderRollback.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 8a39159d806d05c4a9eb7a7a389d8396 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/ColliderRollback/Attributions.txt b/Assets/FishNet/Runtime/Plugins/ColliderRollback/Attributions.txt deleted file mode 100644 index b548ed0..0000000 --- a/Assets/FishNet/Runtime/Plugins/ColliderRollback/Attributions.txt +++ /dev/null @@ -1,5 +0,0 @@ -Attribution to https://assetstore.unity.com/packages/3d/environments/landscapes/low-poly-simple-nature-pack-162153 -"SimpleNaturePack" - -Attribution to Kenny.nl -"Weapon Pack" \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Plugins/ColliderRollback/Attributions.txt.meta b/Assets/FishNet/Runtime/Plugins/ColliderRollback/Attributions.txt.meta deleted file mode 100644 index a501e44..0000000 --- a/Assets/FishNet/Runtime/Plugins/ColliderRollback/Attributions.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 0b87cdb0a34a9254ab77396878d3679e -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/ColliderRollback/LICENSE.txt b/Assets/FishNet/Runtime/Plugins/ColliderRollback/LICENSE.txt deleted file mode 100644 index 54c6022..0000000 --- a/Assets/FishNet/Runtime/Plugins/ColliderRollback/LICENSE.txt +++ /dev/null @@ -1 +0,0 @@ -This software uses the license for Fish-Networking: https://github.com/FirstGearGames/FishNet/blob/main/LICENSE.md \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Plugins/ColliderRollback/LICENSE.txt.meta b/Assets/FishNet/Runtime/Plugins/ColliderRollback/LICENSE.txt.meta deleted file mode 100644 index a551d13..0000000 --- a/Assets/FishNet/Runtime/Plugins/ColliderRollback/LICENSE.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: ff1ecc2a24fd9684a862c4b99cfc2fcd -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts.meta b/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts.meta deleted file mode 100644 index 7084ba5..0000000 --- a/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: d1d5f2c3ff10faa45a45d9cb3b1bfcc1 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/ColliderRollback.cs b/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/ColliderRollback.cs deleted file mode 100644 index 9ba3166..0000000 --- a/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/ColliderRollback.cs +++ /dev/null @@ -1,23 +0,0 @@ -using FishNet.Object; -using UnityEngine; - -namespace FishNet.Component.ColliderRollback -{ - - public class ColliderRollback : NetworkBehaviour - { - - - #region Serialized. - /// - /// Objects holding colliders which can rollback. - /// - [Tooltip("Objects holding colliders which can rollback.")] - [SerializeField] - private GameObject[] _colliderParents = new GameObject[0]; - #endregion - - - } - -} diff --git a/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/ColliderRollback.cs.meta b/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/ColliderRollback.cs.meta deleted file mode 100644 index 6d18cfb..0000000 --- a/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/ColliderRollback.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 01a271dd97d875347b0cea860df29a9d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/RollbackManager.cs b/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/RollbackManager.cs deleted file mode 100644 index b23c119..0000000 --- a/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/RollbackManager.cs +++ /dev/null @@ -1,51 +0,0 @@ -using FishNet.Managing; -using FishNet.Managing.Timing; -using FishNet.Transporting; -using System; -using UnityEngine; - -namespace FishNet.Component.ColliderRollback -{ - public class RollbackManager : MonoBehaviour - { - - - - - #region Serialized. - /// - /// - /// - [Tooltip("Maximum time in the past colliders can be rolled back to.")] - [SerializeField] - private float _maximumRollbackTime = 1.25f; - /// - /// Maximum time in the past colliders can be rolled back to. - /// - internal float MaximumRollbackTime => _maximumRollbackTime; - /// - /// - /// - [Tooltip("Interpolation value for the NetworkTransform or object being rolled back.")] - [Range(0, 250)] - [SerializeField] - internal ushort Interpolation = 2; - #endregion - - - - - - /// - /// Initializes this script for use. - /// - /// - internal void InitializeOnce_Internal(NetworkManager manager) - { - - } - - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/RollbackManager.cs.meta b/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/RollbackManager.cs.meta deleted file mode 100644 index c7c510b..0000000 --- a/Assets/FishNet/Runtime/Plugins/ColliderRollback/Scripts/RollbackManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b185516acd802904383e2a5f1a666750 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/Yak.meta b/Assets/FishNet/Runtime/Plugins/Yak.meta deleted file mode 100644 index dcae338..0000000 --- a/Assets/FishNet/Runtime/Plugins/Yak.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 0bfce5a10f5315248bf3e7eaed92265d -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/Yak/CHANGELOG.txt b/Assets/FishNet/Runtime/Plugins/Yak/CHANGELOG.txt deleted file mode 100644 index 4f3eea1..0000000 --- a/Assets/FishNet/Runtime/Plugins/Yak/CHANGELOG.txt +++ /dev/null @@ -1,2 +0,0 @@ -1.0.0 - - Initial release. \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Plugins/Yak/CHANGELOG.txt.meta b/Assets/FishNet/Runtime/Plugins/Yak/CHANGELOG.txt.meta deleted file mode 100644 index 959d54e..0000000 --- a/Assets/FishNet/Runtime/Plugins/Yak/CHANGELOG.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 65389c57cd9accf47967cc3e6cb7ac1b -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/Yak/Core.meta b/Assets/FishNet/Runtime/Plugins/Yak/Core.meta deleted file mode 100644 index 7f0cd25..0000000 --- a/Assets/FishNet/Runtime/Plugins/Yak/Core.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 3b79a48228ccfcd4cbf0a0514295abeb -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/Yak/Core/ClientSocket.cs b/Assets/FishNet/Runtime/Plugins/Yak/Core/ClientSocket.cs deleted file mode 100644 index e69de29..0000000 diff --git a/Assets/FishNet/Runtime/Plugins/Yak/Core/ClientSocket.cs.meta b/Assets/FishNet/Runtime/Plugins/Yak/Core/ClientSocket.cs.meta deleted file mode 100644 index ac679e5..0000000 --- a/Assets/FishNet/Runtime/Plugins/Yak/Core/ClientSocket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 26269fe7187f5da4e957080519ea0f13 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/Yak/Core/CommonSocket.cs b/Assets/FishNet/Runtime/Plugins/Yak/Core/CommonSocket.cs deleted file mode 100644 index e69de29..0000000 diff --git a/Assets/FishNet/Runtime/Plugins/Yak/Core/CommonSocket.cs.meta b/Assets/FishNet/Runtime/Plugins/Yak/Core/CommonSocket.cs.meta deleted file mode 100644 index 02600b5..0000000 --- a/Assets/FishNet/Runtime/Plugins/Yak/Core/CommonSocket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 63afa30fa0251df44b9496aded55d795 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/Yak/Core/LocalPacket.cs b/Assets/FishNet/Runtime/Plugins/Yak/Core/LocalPacket.cs deleted file mode 100644 index 5f28270..0000000 --- a/Assets/FishNet/Runtime/Plugins/Yak/Core/LocalPacket.cs +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Plugins/Yak/Core/LocalPacket.cs.meta b/Assets/FishNet/Runtime/Plugins/Yak/Core/LocalPacket.cs.meta deleted file mode 100644 index 32c8808..0000000 --- a/Assets/FishNet/Runtime/Plugins/Yak/Core/LocalPacket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f52ce359669f91c4d981dc605a8875b7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/Yak/Core/ServerSocket.cs b/Assets/FishNet/Runtime/Plugins/Yak/Core/ServerSocket.cs deleted file mode 100644 index e69de29..0000000 diff --git a/Assets/FishNet/Runtime/Plugins/Yak/Core/ServerSocket.cs.meta b/Assets/FishNet/Runtime/Plugins/Yak/Core/ServerSocket.cs.meta deleted file mode 100644 index 16d2d4c..0000000 --- a/Assets/FishNet/Runtime/Plugins/Yak/Core/ServerSocket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9181ba25449c96446b966d0bd62e5813 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/Yak/VERSION.txt b/Assets/FishNet/Runtime/Plugins/Yak/VERSION.txt deleted file mode 100644 index afaf360..0000000 --- a/Assets/FishNet/Runtime/Plugins/Yak/VERSION.txt +++ /dev/null @@ -1 +0,0 @@ -1.0.0 \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Plugins/Yak/VERSION.txt.meta b/Assets/FishNet/Runtime/Plugins/Yak/VERSION.txt.meta deleted file mode 100644 index afecaf0..0000000 --- a/Assets/FishNet/Runtime/Plugins/Yak/VERSION.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 3f0e4449aaa7cf0499df1847fdbd5377 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Plugins/Yak/Yak.cs b/Assets/FishNet/Runtime/Plugins/Yak/Yak.cs deleted file mode 100644 index e69de29..0000000 diff --git a/Assets/FishNet/Runtime/Plugins/Yak/Yak.cs.meta b/Assets/FishNet/Runtime/Plugins/Yak/Yak.cs.meta deleted file mode 100644 index 9b936a3..0000000 --- a/Assets/FishNet/Runtime/Plugins/Yak/Yak.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 91f4cf5273666764789e6f8bada05e3e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing.meta b/Assets/FishNet/Runtime/Serializing.meta deleted file mode 100644 index a3b0ae4..0000000 --- a/Assets/FishNet/Runtime/Serializing.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 6a3426d8e19d71a4e809a5993e9e6459 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/AutoPackType.cs b/Assets/FishNet/Runtime/Serializing/AutoPackType.cs deleted file mode 100644 index c51081c..0000000 --- a/Assets/FishNet/Runtime/Serializing/AutoPackType.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace FishNet.Serializing -{ - /// - /// How to pack data when using serialization. - /// - public enum AutoPackType - { - /// - /// Data will not be compressed. - /// - Unpacked = 0, - /// - /// Data will be compressed to use the least amount of data possible. - /// - Packed = 1, - /// - /// Data will be compressed but not as much as Packed. - /// - PackedLess = 2 - } -} diff --git a/Assets/FishNet/Runtime/Serializing/AutoPackType.cs.meta b/Assets/FishNet/Runtime/Serializing/AutoPackType.cs.meta deleted file mode 100644 index 37dd541..0000000 --- a/Assets/FishNet/Runtime/Serializing/AutoPackType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2e94ebaa8f7024845a7e90ebd8246ac6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/Helping.meta b/Assets/FishNet/Runtime/Serializing/Helping.meta deleted file mode 100644 index 5ba60eb..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 29ef966943829104e8b9d8b7fd225599 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/Helping/Attributes.cs b/Assets/FishNet/Runtime/Serializing/Helping/Attributes.cs deleted file mode 100644 index 9541eef..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping/Attributes.cs +++ /dev/null @@ -1,26 +0,0 @@ -using FishNet.Utility.Constant; -using System; -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo(UtilityConstants.CODEGEN_ASSEMBLY_NAME)] -namespace FishNet.Serializing.Helping -{ - /// - /// Method is a comparer for a value type. - /// - public class CustomComparerAttribute : Attribute { } - /// - /// Method or type will be made public by codegen. - /// - internal class CodegenMakePublicAttribute : Attribute { } - /// - /// Field or type will be excluded from codegen serialization. - /// - public class CodegenExcludeAttribute : Attribute { } - /// - /// THIS DOES NOT DO ANYTHING AT THIS TIME. - /// It would do -> Type will be included in codegen serialization. - /// - internal class CodegenIncludeAttribute : Attribute { } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Serializing/Helping/Attributes.cs.meta b/Assets/FishNet/Runtime/Serializing/Helping/Attributes.cs.meta deleted file mode 100644 index 72d697d..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping/Attributes.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ce079c8f32bf87b46a44681ccc8578fa -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/Helping/Broadcasts.cs b/Assets/FishNet/Runtime/Serializing/Helping/Broadcasts.cs deleted file mode 100644 index 6086557..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping/Broadcasts.cs +++ /dev/null @@ -1,38 +0,0 @@ -using FishNet.Managing.Scened; -using FishNet.Managing.Server; -using FishNet.Object.Helping; -using FishNet.Transporting; -using UnityEngine; - -namespace FishNet.Serializing.Helping -{ - - internal static class Broadcasts - { - /// - /// Writes a broadcast to writer. - /// - /// - /// - /// - /// - /// - internal static PooledWriter WriteBroadcast(PooledWriter writer, T message, Channel channel) - { - writer.WritePacketId(PacketId.Broadcast); - writer.WriteUInt16(typeof(T).FullName.GetStableHash16()); //muchlater codegen this to pass in hash. use technique similar to rpcs to limit byte/shorts. - //Write data to a new writer. - PooledWriter dataWriter = WriterPool.GetWriter(); - dataWriter.Write(message); - //Write length of data. - writer.WriteLength(dataWriter.Length); - //Write data. - writer.WriteArraySegment(dataWriter.GetArraySegment()); - - dataWriter.Dispose(); - - return writer; - } - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Serializing/Helping/Broadcasts.cs.meta b/Assets/FishNet/Runtime/Serializing/Helping/Broadcasts.cs.meta deleted file mode 100644 index 462de30..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping/Broadcasts.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0636e29429649a24795091f80edbd892 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs b/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs deleted file mode 100644 index 8f3f2db..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using UnityEngine.SceneManagement; - -namespace FishNet.Serializing.Helping -{ - - public class GeneratedComparer - { - /// - /// Compare if T is default. - /// - public static Func IsDefault { internal get; set; } - /// - /// Compare if T is the same as T2. - /// - public static Func Compare { internal get; set; } - } - - - public class Comparers - { - /// - /// Returns if A equals B using EqualityCompare. - /// - /// - /// - /// - /// - public static bool EqualityCompare(T a, T b) - { - return EqualityComparer.Default.Equals(a, b); - } - - public static bool IsDefault(T t) - { - return t.Equals(default(T)); - } - - public static bool IsEqualityCompareDefault(T a) - { - return EqualityComparer.Default.Equals(a, default(T)); - } - } - - - internal class SceneComparer : IEqualityComparer - { - public bool Equals(Scene a, Scene b) - { - if (!a.IsValid() || !b.IsValid()) - return false; - - if (a.handle != 0 || b.handle != 0) - return (a.handle == b.handle); - - return (a.name == b.name); - } - - public int GetHashCode(Scene obj) - { - return obj.GetHashCode(); - } - } - -} diff --git a/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs.meta b/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs.meta deleted file mode 100644 index c79d11e..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping/Comparers.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e912d0645f10b2c458cc2f01e24ecc27 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/Helping/Quaternion32.cs b/Assets/FishNet/Runtime/Serializing/Helping/Quaternion32.cs deleted file mode 100644 index 3fa685a..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping/Quaternion32.cs +++ /dev/null @@ -1,163 +0,0 @@ - -using System; -using UnityEngine; - -namespace FishNet.Serializing.Helping -{ - public static class Quaternion32Compression - { - private const float Maximum = +1.0f / 1.414214f; - - private const int BitsPerAxis = 10; - private const int LargestComponentShift = BitsPerAxis * 3; - private const int AShift = BitsPerAxis * 2; - private const int BShift = BitsPerAxis * 1; - private const int IntScale = (1 << (BitsPerAxis - 1)) - 1; - private const int IntMask = (1 << BitsPerAxis) - 1; - - public static uint Compress(Quaternion quaternion) - { - float absX = Mathf.Abs(quaternion.x); - float absY = Mathf.Abs(quaternion.y); - float absZ = Mathf.Abs(quaternion.z); - float absW = Mathf.Abs(quaternion.w); - - ComponentType largestComponent = ComponentType.X; - float largestAbs = absX; - float largest = quaternion.x; - - if (absY > largestAbs) - { - largestAbs = absY; - largestComponent = ComponentType.Y; - largest = quaternion.y; - } - if (absZ > largestAbs) - { - largestAbs = absZ; - largestComponent = ComponentType.Z; - largest = quaternion.z; - } - if (absW > largestAbs) - { - largestComponent = ComponentType.W; - largest = quaternion.w; - } - - float a = 0; - float b = 0; - float c = 0; - switch (largestComponent) - { - case ComponentType.X: - a = quaternion.y; - b = quaternion.z; - c = quaternion.w; - break; - case ComponentType.Y: - a = quaternion.x; - b = quaternion.z; - c = quaternion.w; - break; - case ComponentType.Z: - a = quaternion.x; - b = quaternion.y; - c = quaternion.w; - break; - case ComponentType.W: - a = quaternion.x; - b = quaternion.y; - c = quaternion.z; - break; - } - - if (largest < 0) - { - a = -a; - b = -b; - c = -c; - } - - uint integerA = ScaleToUint(a); - uint integerB = ScaleToUint(b); - uint integerC = ScaleToUint(c); - - return (((uint)largestComponent) << LargestComponentShift) | (integerA << AShift) | (integerB << BShift) | integerC; - } - - private static uint ScaleToUint(float v) - { - float normalized = v / Maximum; - return (uint)Mathf.RoundToInt(normalized * IntScale) & IntMask; - } - - private static float ScaleToFloat(uint v) - { - float unscaled = v * Maximum / IntScale; - - if (unscaled > Maximum) - unscaled -= Maximum * 2; - return unscaled; - } - - public static Quaternion Decompress(uint compressed) - { - var largestComponentType = (ComponentType)(compressed >> LargestComponentShift); - uint integerA = (compressed >> AShift) & IntMask; - uint integerB = (compressed >> BShift) & IntMask; - uint integerC = compressed & IntMask; - - float a = ScaleToFloat(integerA); - float b = ScaleToFloat(integerB); - float c = ScaleToFloat(integerC); - - Quaternion rotation; - switch (largestComponentType) - { - case ComponentType.X: - // (?) y z w - rotation.y = a; - rotation.z = b; - rotation.w = c; - rotation.x = Mathf.Sqrt(1 - rotation.y * rotation.y - - rotation.z * rotation.z - - rotation.w * rotation.w); - break; - case ComponentType.Y: - // x (?) z w - rotation.x = a; - rotation.z = b; - rotation.w = c; - rotation.y = Mathf.Sqrt(1 - rotation.x * rotation.x - - rotation.z * rotation.z - - rotation.w * rotation.w); - break; - case ComponentType.Z: - // x y (?) w - rotation.x = a; - rotation.y = b; - rotation.w = c; - rotation.z = Mathf.Sqrt(1 - rotation.x * rotation.x - - rotation.y * rotation.y - - rotation.w * rotation.w); - break; - case ComponentType.W: - // x y z (?) - rotation.x = a; - rotation.y = b; - rotation.z = c; - rotation.w = Mathf.Sqrt(1 - rotation.x * rotation.x - - rotation.y * rotation.y - - rotation.z * rotation.z); - break; - default: - // Should never happen! - throw new ArgumentOutOfRangeException("Unknown rotation component type: " + - largestComponentType); - } - - return rotation; - } - - } -} diff --git a/Assets/FishNet/Runtime/Serializing/Helping/Quaternion32.cs.meta b/Assets/FishNet/Runtime/Serializing/Helping/Quaternion32.cs.meta deleted file mode 100644 index 0158ec8..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping/Quaternion32.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f71e61ed84064a0429577ec462a8fa79 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/Helping/Quaternion64.cs b/Assets/FishNet/Runtime/Serializing/Helping/Quaternion64.cs deleted file mode 100644 index 1832ba7..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping/Quaternion64.cs +++ /dev/null @@ -1,192 +0,0 @@ - -using System; -using UnityEngine; - -namespace FishNet.Serializing.Helping -{ - /// - /// Credit to https://github.com/viliwonka - /// https://github.com/FirstGearGames/FishNet/pull/23 - /// - public static class Quaternion64Compression - { - // 64 bit quaternion compression - // [4 bits] largest component - // [21 bits] higher res - // [21 bits] higher res - // [20 bits] higher res - // sum is 64 bits - private const float Maximum = +1.0f / 1.414214f; - private const int BitsPerAxis_H = 21; // higher res, 21 bits - private const int BitsPerAxis_L = 20; // lower res, 20 bits - private const int LargestComponentShift = BitsPerAxis_H * 2 + BitsPerAxis_L * 1; - private const int AShift = BitsPerAxis_H + BitsPerAxis_L; - private const int BShift = BitsPerAxis_L; - private const int IntScale_H = (1 << (BitsPerAxis_H - 1)) - 1; - private const int IntMask_H = (1 << BitsPerAxis_H) - 1; - private const int IntScale_L = (1 << (BitsPerAxis_L - 1)) - 1; - private const int IntMask_L = (1 << BitsPerAxis_L) - 1; - - public static ulong Compress(Quaternion quaternion) - { - float absX = Mathf.Abs(quaternion.x); - float absY = Mathf.Abs(quaternion.y); - float absZ = Mathf.Abs(quaternion.z); - float absW = Mathf.Abs(quaternion.w); - - ComponentType largestComponent = ComponentType.X; - float largestAbs = absX; - float largest = quaternion.x; - - if (absY > largestAbs) - { - largestAbs = absY; - largestComponent = ComponentType.Y; - largest = quaternion.y; - } - if (absZ > largestAbs) - { - largestAbs = absZ; - largestComponent = ComponentType.Z; - largest = quaternion.z; - } - if (absW > largestAbs) - { - largestComponent = ComponentType.W; - largest = quaternion.w; - } - - float a = 0; - float b = 0; - float c = 0; - - switch (largestComponent) - { - case ComponentType.X: - a = quaternion.y; - b = quaternion.z; - c = quaternion.w; - break; - case ComponentType.Y: - a = quaternion.x; - b = quaternion.z; - c = quaternion.w; - break; - case ComponentType.Z: - a = quaternion.x; - b = quaternion.y; - c = quaternion.w; - break; - case ComponentType.W: - a = quaternion.x; - b = quaternion.y; - c = quaternion.z; - break; - } - - if (largest < 0) - { - a = -a; - b = -b; - c = -c; - } - - ulong integerA = ScaleToUint_H(a); - ulong integerB = ScaleToUint_H(b); - ulong integerC = ScaleToUint_L(c); - - return (((ulong)largestComponent) << LargestComponentShift) | (integerA << AShift) | (integerB << BShift) | integerC; - } - - private static ulong ScaleToUint_H(float v) - { - float normalized = v / Maximum; - return (ulong)Mathf.RoundToInt(normalized * IntScale_H) & IntMask_H; - } - - private static ulong ScaleToUint_L(float v) - { - float normalized = v / Maximum; - return (ulong)Mathf.RoundToInt(normalized * IntScale_L) & IntMask_L; - } - - private static float ScaleToFloat_H(ulong v) - { - float unscaled = v * Maximum / IntScale_H; - - if (unscaled > Maximum) - unscaled -= Maximum * 2; - return unscaled; - } - - private static float ScaleToFloat_L(ulong v) - { - float unscaled = v * Maximum / IntScale_L; - - if (unscaled > Maximum) - unscaled -= Maximum * 2; - return unscaled; - } - - public static Quaternion Decompress(ulong compressed) - { - var largestComponentType = (ComponentType)(compressed >> LargestComponentShift); - ulong integerA = (compressed >> AShift) & IntMask_H; - ulong integerB = (compressed >> BShift) & IntMask_H; - ulong integerC = compressed & IntMask_L; - - float a = ScaleToFloat_H(integerA); - float b = ScaleToFloat_H(integerB); - float c = ScaleToFloat_L(integerC); - - Quaternion rotation; - switch (largestComponentType) - { - case ComponentType.X: - // (?) y z w - rotation.y = a; - rotation.z = b; - rotation.w = c; - rotation.x = Mathf.Sqrt(1 - rotation.y * rotation.y - - rotation.z * rotation.z - - rotation.w * rotation.w); - break; - case ComponentType.Y: - // x (?) z w - rotation.x = a; - rotation.z = b; - rotation.w = c; - rotation.y = Mathf.Sqrt(1 - rotation.x * rotation.x - - rotation.z * rotation.z - - rotation.w * rotation.w); - break; - case ComponentType.Z: - // x y (?) w - rotation.x = a; - rotation.y = b; - rotation.w = c; - rotation.z = Mathf.Sqrt(1 - rotation.x * rotation.x - - rotation.y * rotation.y - - rotation.w * rotation.w); - break; - case ComponentType.W: - // x y z (?) - rotation.x = a; - rotation.y = b; - rotation.z = c; - rotation.w = Mathf.Sqrt(1 - rotation.x * rotation.x - - rotation.y * rotation.y - - rotation.z * rotation.z); - break; - default: - // Should never happen! - throw new ArgumentOutOfRangeException("Unknown rotation component type: " + - largestComponentType); - } - - return rotation; - } - - - } -} diff --git a/Assets/FishNet/Runtime/Serializing/Helping/Quaternion64.cs.meta b/Assets/FishNet/Runtime/Serializing/Helping/Quaternion64.cs.meta deleted file mode 100644 index 68090e2..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping/Quaternion64.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7afd33d2ca5433f4f831dfaf0169423c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/Helping/QuaternionConverter.cs b/Assets/FishNet/Runtime/Serializing/Helping/QuaternionConverter.cs deleted file mode 100644 index 2855a06..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping/QuaternionConverter.cs +++ /dev/null @@ -1,126 +0,0 @@ - -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using UnityEngine; - -namespace FishNet.Serializing.Helping -{ - /// - /// Static class used for fast conversion of quaternion structs. Not thread safe! - /// - [StructLayout(LayoutKind.Explicit)] - public struct QuaternionConverter - { - // [FieldOffset(0)] - // public Quaternion Q; - // [FieldOffset(0)] - // public Quaternion64 Q64; - // [FieldOffset(0)] - // public Quaternion128 Q128; - - // public static QuaternionConverter StaticRef = new QuaternionConverter(); - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public static Quaternion64 QtoQ64(Quaternion quaternion64) - // { - // StaticRef.Q = quaternion64; - // return StaticRef.Q64; - // } - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public static Quaternion Q64toQ(Quaternion64 quaternion) - // { - // StaticRef.Q64 = quaternion; - // return StaticRef.Q; - // } - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public static Quaternion128 QtoQ128(Quaternion quaternion128) - // { - // StaticRef.Q = quaternion128; - // return StaticRef.Q128; - // } - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public static Quaternion Q128toQ(Quaternion128 quaternion) - // { - // StaticRef.Q128 = quaternion; - // return StaticRef.Q; - // } - //} - - //public struct Quaternion64 - //{ - // public float x; - // public float y; - // public float z; - // public float w; - - // public Quaternion64(float x, float y, float z, float w) - // { - // this.x = x; - // this.y = y; - // this.z = z; - // this.w = w; - // } - - // public Quaternion64(Quaternion q) - // { - // this.x = q.x; - // this.y = q.y; - // this.z = q.z; - // this.w = q.w; - // } - - // /*[MethodImpl(MethodImplOptions.AggressiveInlining)] - // public static implicit operator Quaternion64(Quaternion q) => new Quaternion64(q); - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public static implicit operator Quaternion(Quaternion64 q) => new Quaternion(q.x, q.y, q.z, q.w);*/ - //} - - //public struct Quaternion128 - //{ - // public float x; - // public float y; - // public float z; - // public float w; - // public Quaternion128(float x, float y, float z, float w) - // { - // this.x = x; - // this.y = y; - // this.z = z; - // this.w = w; - // } - - // public Quaternion128(Quaternion q) - // { - // x = q.x; - // y = q.y; - // z = q.z; - // w = q.w; - // } - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public static implicit operator Quaternion128(Quaternion q) => new Quaternion128(q); - - // [MethodImpl(MethodImplOptions.AggressiveInlining)] - // public static implicit operator Quaternion(Quaternion128 q) => new Quaternion(q.x, q.y, q.z, q.w); - //} - - /// - /// Credit to this man for converting gaffer games c code to c# - /// https://gist.github.com/fversnel/0497ad7ab3b81e0dc1dd - /// - } - - public enum ComponentType : uint - { - X = 0, - Y = 1, - Z = 2, - W = 3 - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Serializing/Helping/QuaternionConverter.cs.meta b/Assets/FishNet/Runtime/Serializing/Helping/QuaternionConverter.cs.meta deleted file mode 100644 index 0238ab7..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping/QuaternionConverter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b7ac59ce12259104fa28fc837fb17ccf -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/Helping/ValueConversions.cs b/Assets/FishNet/Runtime/Serializing/Helping/ValueConversions.cs deleted file mode 100644 index 48153c7..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping/ValueConversions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Runtime.InteropServices; - -namespace FishNet.Serializing.Helping -{ - - - // -- helpers for float conversion without allocations -- - [StructLayout(LayoutKind.Explicit)] - internal struct UIntFloat - { - [FieldOffset(0)] - public float FloatValue; - - [FieldOffset(0)] - public uint UIntValue; - } - - [StructLayout(LayoutKind.Explicit)] - internal struct UIntDouble - { - [FieldOffset(0)] - public double DoubleValue; - - [FieldOffset(0)] - public ulong LongValue; - } - - [StructLayout(LayoutKind.Explicit)] - internal struct UIntDecimal - { - [FieldOffset(0)] - public ulong LongValue1; - - [FieldOffset(8)] - public ulong LongValue2; - - [FieldOffset(0)] - public decimal DecimalValue; - } - -} diff --git a/Assets/FishNet/Runtime/Serializing/Helping/ValueConversions.cs.meta b/Assets/FishNet/Runtime/Serializing/Helping/ValueConversions.cs.meta deleted file mode 100644 index 21b772b..0000000 --- a/Assets/FishNet/Runtime/Serializing/Helping/ValueConversions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 008e79d0f22a2674189acc7eff64408f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/Reader.cs b/Assets/FishNet/Runtime/Serializing/Reader.cs deleted file mode 100644 index 17e0d50..0000000 --- a/Assets/FishNet/Runtime/Serializing/Reader.cs +++ /dev/null @@ -1,1421 +0,0 @@ -using FishNet.Connection; -using FishNet.Documenting; -using FishNet.Managing; -using FishNet.Object; -using FishNet.Object.Prediction; -using FishNet.Serializing.Helping; -using FishNet.Transporting; -using FishNet.Utility.Constant; -using FishNet.Utility.Extension; -using FishNet.Utility.Performance; -using System; -using System.Collections.Generic; -using System.IO; -using System.Runtime.CompilerServices; -using UnityEngine; - - -[assembly: InternalsVisibleTo(UtilityConstants.GENERATED_ASSEMBLY_NAME)] -//Required for internal tests. -[assembly: InternalsVisibleTo(UtilityConstants.TEST_ASSEMBLY_NAME)] -namespace FishNet.Serializing -{ - /// - /// Used for read references to generic types. - /// - /// - [APIExclude] - public static class GenericReader - { - public static Func Read { internal get; set; } - public static Func ReadAutoPack { internal get; set; } - } - - /// - /// Reads data from a buffer. - /// - public class Reader - { - #region Public. - /// - /// Capacity of the buffer. - /// - public int Capacity => _buffer.Length; - /// - /// NetworkManager for this reader. Used to lookup objects. - /// - public NetworkManager NetworkManager; - /// - /// Offset within the buffer when the reader was created. - /// - public int Offset { get; private set; } - /// - /// Position for the next read. - /// - public int Position; - /// - /// Total number of bytes available within the buffer. - /// - public int Length { get; private set; } - /// - /// Bytes remaining to be read. This value is Length - Position. - /// - public int Remaining => ((Length + Offset) - Position); - #endregion - - #region Internal. - /// - /// NetworkConnection that this data came from. - /// Value may not always be set. - /// - public NetworkConnection NetworkConnection { get; private set; } -#if UNITY_EDITOR || DEVELOPMENT_BUILD - /// - /// Last NetworkObject parsed. - /// - public static NetworkObject LastNetworkObject { get; private set; } - /// - /// Last NetworkBehaviour parsed. - /// - public static NetworkBehaviour LastNetworkBehaviour { get; private set; } -#endif - #endregion - - #region Private. - /// - /// Data being read. - /// - private byte[] _buffer; - #endregion - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Reader(byte[] bytes, NetworkManager networkManager, NetworkConnection networkConnection = null) - { - Initialize(bytes, networkManager, networkConnection); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Reader(ArraySegment segment, NetworkManager networkManager, NetworkConnection networkConnection = null) - { - Initialize(segment, networkManager, networkConnection); - } - - /// - /// Outputs reader to string. - /// - /// - public override string ToString() - { - return $"Position: {Position}, Length: {Length}, Buffer: {BitConverter.ToString(_buffer, Offset, Length)}."; - } - - /// - /// Initializes this reader with data. - /// - /// - /// - internal void Initialize(ArraySegment bytes, NetworkManager networkManager, NetworkConnection networkConnection = null) - { - if (bytes.Array == null) - { - if (_buffer == null) - _buffer = new byte[0]; - } - else - { - _buffer = bytes.Array; - } - - Position = bytes.Offset; - Offset = bytes.Offset; - Length = bytes.Count; - NetworkManager = networkManager; - NetworkConnection = networkConnection; - } - /// - /// Initializes this reader with data. - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void Initialize(byte[] bytes, NetworkManager networkManager, NetworkConnection networkConnection = null) - { - Initialize(new ArraySegment(bytes), networkManager, networkConnection); - } - - - /// - /// Reads a dictionary. - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [Obsolete("Use ReadDictionaryAllocated.")] - public Dictionary ReadDictionary() - { - return ReadDictionaryAllocated(); - } - - /// - /// Reads a dictionary. - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Dictionary ReadDictionaryAllocated() - { - bool isNull = ReadBoolean(); - if (isNull) - return null; - - int count = ReadInt32(); - - Dictionary result = new Dictionary(count); - for (int i = 0; i < count; i++) - { - TKey key = Read(); - TValue value = Read(); - result.Add(key, value); - } - - return result; - } - - - /// - /// Reads length. This method is used to make debugging easier. - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal int ReadLength() - { - return ReadInt32(); - } - - /// - /// Reads a packetId. - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal PacketId ReadPacketId() - { - return (PacketId)ReadUInt16(); - } - - /// - /// Returns a ushort without advancing the reader. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal PacketId PeekPacketId() - { - int currentPosition = Position; - PacketId result = ReadPacketId(); - Position = currentPosition; - return result; - } - - /// - /// Skips a number of bytes in the reader. - /// - /// Number of bytes to skip. - [CodegenExclude] - public void Skip(int value) - { - if (value < 1 || Remaining < value) - return; - - Position += value; - } - /// - /// Clears remaining bytes to be read. - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Clear() - { - if (Remaining > 0) - Skip(Remaining); - } - - /// - /// Returns the buffer as an ArraySegment. - /// - /// - public ArraySegment GetArraySegmentBuffer() - { - return new ArraySegment(_buffer, Offset, Length); - } - /// - /// Returns the buffer as bytes. This does not trim excessive bytes. - /// - /// - public byte[] GetByteBuffer() - { - return _buffer; - } - /// - /// Returns the buffer as bytes and allocates into a new array. - /// - /// - public byte[] GetByteBufferAllocated() - { - byte[] result = new byte[Length]; - Buffer.BlockCopy(_buffer, Offset, result, 0, Length); - return result; - } - /// - /// BlockCopies data from the reader to target and advances reader. - /// - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void BlockCopy(ref byte[] target, int targetOffset, int count) - { - Buffer.BlockCopy(_buffer, Position, target, targetOffset, count); - Position += count; - } - - /// - /// Reads a byte. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public byte ReadByte() - { - byte r = _buffer[Position]; - Position += 1; - return r; - } - - /// - /// Read bytes from position into target. - /// - /// Buffer to read bytes into. - /// Number of bytes to read. - [CodegenExclude] - public void ReadBytes(ref byte[] buffer, int count) - { - if (buffer == null) - throw new EndOfStreamException($"Target is null."); - //Target isn't large enough. - if (count > buffer.Length) - throw new EndOfStreamException($"Count of {count} exceeds target length of {buffer.Length}."); - - BlockCopy(ref buffer, 0, count); - } - - /// - /// Creates an ArraySegment by reading a number of bytes from position. - /// - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegment ReadArraySegment(int count) - { - ArraySegment result = new ArraySegment(_buffer, Position, count); - Position += count; - return result; - } - - /// - /// Reads a sbyte. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public sbyte ReadSByte() - { - return (sbyte)ReadByte(); - } - - /// - /// Reads a char. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public char ReadChar() => (char)ReadUInt16(); - - /// - /// Reads a boolean. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool ReadBoolean() - { - byte result = ReadByte(); - return (result == 1) ? true : false; - } - - /// - /// Reads an int16. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ushort ReadUInt16() - { - ushort result = 0; - result |= _buffer[Position++]; - result |= (ushort)(_buffer[Position++] << 8); - - return result; - } - - /// - /// Reads a uint16. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public short ReadInt16() => (short)ReadUInt16(); - - /// - /// Reads an int32. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public uint ReadUInt32(AutoPackType packType = AutoPackType.Packed) - { - if (packType == AutoPackType.Packed) - return (uint)ReadPackedWhole(); - - uint result = 0; - result |= _buffer[Position++]; - result |= (uint)_buffer[Position++] << 8; - result |= (uint)_buffer[Position++] << 16; - result |= (uint)_buffer[Position++] << 24; - - return result; - } - /// - /// Reads a uint32. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int ReadInt32(AutoPackType packType = AutoPackType.Packed) - { - if (packType == AutoPackType.Packed) - return (int)(long)ZigZagDecode(ReadPackedWhole()); - - return (int)ReadUInt32(packType); - } - - /// - /// Reads a uint64. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public long ReadInt64(AutoPackType packType = AutoPackType.Packed) - { - if (packType == AutoPackType.Packed) - return (long)ZigZagDecode(ReadPackedWhole()); - - return (long)ReadUInt64(packType); - } - - /// - /// Reads an int64. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ulong ReadUInt64(AutoPackType packType = AutoPackType.Packed) - { - if (packType == AutoPackType.Packed) - return (ulong)ReadPackedWhole(); - - ulong result = 0; - result |= _buffer[Position++]; - result |= (ulong)_buffer[Position++] << 8; - result |= (ulong)_buffer[Position++] << 16; - result |= (ulong)_buffer[Position++] << 24; - result |= (ulong)_buffer[Position++] << 32; - result |= (ulong)_buffer[Position++] << 40; - result |= (ulong)_buffer[Position++] << 48; - result |= (ulong)_buffer[Position++] << 56; - - return result; - } - - - /// - /// Reads a single. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float ReadSingle(AutoPackType packType = AutoPackType.Unpacked) - { - if (packType == AutoPackType.Unpacked) - { - UIntFloat converter = new UIntFloat(); - converter.UIntValue = ReadUInt32(AutoPackType.Unpacked); - return converter.FloatValue; - } - else - { - long converter = (long)ReadPackedWhole(); - return (float)(converter / 100f); - } - } - - /// - /// Reads a double. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double ReadDouble() - { - UIntDouble converter = new UIntDouble(); - converter.LongValue = ReadUInt64(AutoPackType.Unpacked); - return converter.DoubleValue; - } - - /// - /// Reads a decimal. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public decimal ReadDecimal() - { - UIntDecimal converter = new UIntDecimal(); - converter.LongValue1 = ReadUInt64(AutoPackType.Unpacked); - converter.LongValue2 = ReadUInt64(AutoPackType.Unpacked); - return converter.DecimalValue; - } - - /// - /// Reads a string. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string ReadString() - { - int size = ReadInt32(); - //Null string. - if (size == Writer.UNSET_COLLECTION_SIZE_VALUE) - return null; - else if (size == 0) - return string.Empty; - - if (!CheckAllocationAttack(size)) - return string.Empty; - ArraySegment data = ReadArraySegment(size); - return ReaderStatics.GetString(data); - } - - /// - /// Creates a byte array and reads bytes and size into it. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public byte[] ReadBytesAndSizeAllocated() - { - int size = ReadInt32(); - if (size == Writer.UNSET_COLLECTION_SIZE_VALUE) - return null; - else - return ReadBytesAllocated(size); - } - - /// - /// Reads bytes and size and copies results into target. Returns UNSET if null was written. - /// - /// Bytes read. - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int ReadBytesAndSize(ref byte[] target) - { - int size = ReadInt32(); - if (size > 0) - ReadBytes(ref target, size); - - return size; - } - - /// - /// Reads bytes and size and returns as an ArraySegment. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ArraySegment ReadArraySegmentAndSize() - { - int size = ReadInt32(); - /* UNSET would be written for null. But since - * ArraySegments cannot be null return default if - * length is unset or 0. */ - if (size == Writer.UNSET_COLLECTION_SIZE_VALUE || size == 0) - return default; - - return ReadArraySegment(size); - } - - /// - /// Reads a Vector2. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector2 ReadVector2() - { - return new Vector2(ReadSingle(), ReadSingle()); - } - - /// - /// Reads a Vector3. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector3 ReadVector3() - { - return new Vector3(ReadSingle(), ReadSingle(), ReadSingle()); - } - - /// - /// Reads a Vector4. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector4 ReadVector4() - { - return new Vector4(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle()); - } - - /// - /// Reads a Vector2Int. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector2Int ReadVector2Int(AutoPackType packType = AutoPackType.Packed) - { - return new Vector2Int(ReadInt32(packType), ReadInt32(packType)); - } - - /// - /// Reads a Vector3Int. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector3Int ReadVector3Int(AutoPackType packType = AutoPackType.Packed) - { - return new Vector3Int(ReadInt32(packType), ReadInt32(packType), ReadInt32(packType)); - } - - /// - /// Reads a color. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Color ReadColor(AutoPackType packType = AutoPackType.Packed) - { - float r, g, b, a; - if (packType == AutoPackType.Unpacked) - { - r = ReadSingle(); - g = ReadSingle(); - b = ReadSingle(); - a = ReadSingle(); - } - else - { - r = (float)(ReadByte() / 100f); - g = (float)(ReadByte() / 100f); - b = (float)(ReadByte() / 100f); - a = (float)(ReadByte() / 100f); - } - return new Color(r, g, b, a); - } - - /// - /// Reads a Color32. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Color32 ReadColor32() - { - return new Color32(ReadByte(), ReadByte(), ReadByte(), ReadByte()); - } - - /// - /// Reads a Quaternion. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Quaternion ReadQuaternion(AutoPackType packType = AutoPackType.Packed) - { - if (packType == AutoPackType.Packed) - { - uint result = ReadUInt32(AutoPackType.Unpacked); - return Quaternion32Compression.Decompress(result); - } - else if (packType == AutoPackType.PackedLess) - { - ulong result = ReadUInt64(AutoPackType.Unpacked); - return Quaternion64Compression.Decompress(result); - } - else - { - return new Quaternion( - ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle() - ); - } - } - - /// - /// Reads a Rect. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Rect ReadRect() - { - return new Rect(ReadSingle(), ReadSingle(), ReadSingle(), ReadSingle()); - } - - /// - /// Plane. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Plane ReadPlane() - { - return new Plane(ReadVector3(), ReadSingle()); - } - - /// - /// Reads a Ray. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ray ReadRay() - { - Vector3 position = ReadVector3(); - Vector3 direction = ReadVector3(); - return new Ray(position, direction); - } - - /// - /// Reads a Ray. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ray2D ReadRay2D() - { - Vector3 position = ReadVector2(); - Vector2 direction = ReadVector2(); - return new Ray2D(position, direction); - } - - /// - /// Reads a Matrix4x4. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Matrix4x4 ReadMatrix4x4() - { - Matrix4x4 result = new Matrix4x4 - { - m00 = ReadSingle(), - m01 = ReadSingle(), - m02 = ReadSingle(), - m03 = ReadSingle(), - m10 = ReadSingle(), - m11 = ReadSingle(), - m12 = ReadSingle(), - m13 = ReadSingle(), - m20 = ReadSingle(), - m21 = ReadSingle(), - m22 = ReadSingle(), - m23 = ReadSingle(), - m30 = ReadSingle(), - m31 = ReadSingle(), - m32 = ReadSingle(), - m33 = ReadSingle() - }; - - return result; - } - - /// - /// Creates a new byte array and reads bytes into it. - /// - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public byte[] ReadBytesAllocated(int count) - { - byte[] bytes = new byte[count]; - ReadBytes(ref bytes, count); - return bytes; - } - - /// - /// Reads a Guid. - /// - /// - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public System.Guid ReadGuid() - { - byte[] buffer = ReaderStatics.GetGuidBuffer(); - ReadBytes(ref buffer, 16); - return new System.Guid(buffer); - } - - - /// - /// Reads a GameObject. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public GameObject ReadGameObject() - { - NetworkObject nob = ReadNetworkObject(); - return (nob == null) ? null : nob.gameObject; - } - - - /// - /// Reads a Transform. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Transform ReadTransform() - { - NetworkObject nob = ReadNetworkObject(); - return (nob == null) ? null : nob.transform; - } - - - /// - /// Reads a NetworkObject. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public NetworkObject ReadNetworkObject() - { - return ReadNetworkObject(out _); - } - - /// - /// Reads a NetworkObject. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public NetworkObject ReadNetworkObject(out int objectOrPrefabId) - { -#if UNITY_EDITOR || DEVELOPMENT_BUILD - LastNetworkBehaviour = null; -#endif - objectOrPrefabId = ReadNetworkObjectId(); - bool isSpawned; - /* UNSET indicates that the object - * is null or no PrefabId is set. - * PrefabIds are set in Awake within - * the NetworkManager so that should - * never happen so long as nob isn't null. */ - if (objectOrPrefabId == NetworkObject.UNSET_OBJECTID_VALUE) - return null; - else - isSpawned = ReadBoolean(); - - bool isServer = NetworkManager.ServerManager.Started; - bool isClient = NetworkManager.ClientManager.Started; - - NetworkObject result; - //Is spawned. - if (isSpawned) - { - result = null; - /* Try to get the object client side first if client - * is running. When acting as a host generally the object - * will be available in the server and client list - * but there can be occasions where the server side - * deinitializes the object, making it unavailable, while - * it is still available in the client side. Since FishNet doesn't - * use a fake host connection like some lesser solutions the client - * has to always be treated as it's own entity. */ - if (isClient) - NetworkManager.ClientManager.Objects.Spawned.TryGetValueIL2CPP(objectOrPrefabId, out result); - //If not found on client and server is running then try server. - if (result == null && isServer) - NetworkManager.ServerManager.Objects.Spawned.TryGetValueIL2CPP(objectOrPrefabId, out result); - } - //Not spawned. - else - { - //Only look up asServer if not client, otherwise use client. - bool asServer = !isClient; - //Look up prefab. - result = NetworkManager.GetPrefab(objectOrPrefabId, asServer); - } - -#if UNITY_EDITOR || DEVELOPMENT_BUILD - LastNetworkObject = result; -#endif - return result; - } - - /// - /// Reads a NetworkObjectId and nothing else. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int ReadNetworkObjectId() - { - return ReadUInt16(); - } - - /// - /// Reads the Id for a NetworkObject and outputs spawn settings. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal int ReadNetworkObjectForSpawn(out sbyte initializeOrder, out ushort collectionid, out bool spawned) - { - int objectId = ReadNetworkObjectId(); - - bool isNull = (objectId == NetworkObject.UNSET_OBJECTID_VALUE); - if (isNull) - { - initializeOrder = 0; - collectionid = 0; - spawned = false; - } - else - { - collectionid = ReadUInt16(); - initializeOrder = ReadSByte(); - spawned = ReadBoolean(); - } - - return objectId; - } - - - /// - /// Reads the Id for a NetworkObject and outputs despawn settings. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal int ReadNetworkObjectForDepawn(out DespawnType dt) - { - int objectId = ReadNetworkObjectId(); - dt = (DespawnType)ReadByte(); - return objectId; - } - - - /// - /// Reads a NetworkBehaviourId and ObjectId. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal byte ReadNetworkBehaviourId(out int objectId) - { - objectId = ReadNetworkObjectId(); - if (objectId != NetworkObject.UNSET_OBJECTID_VALUE) - return ReadByte(); - else - return 0; - } - - /// - /// Reads a NetworkBehaviour. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public NetworkBehaviour ReadNetworkBehaviour(out int objectId, out byte componentIndex) - { - NetworkObject nob = ReadNetworkObject(out objectId); - componentIndex = ReadByte(); - - NetworkBehaviour result; - if (nob == null) - { - result = null; - } - else - { - if (componentIndex >= nob.NetworkBehaviours.Length) - { - NetworkManager.LogError($"ComponentIndex of {componentIndex} is out of bounds on {nob.gameObject.name} [id {nob.ObjectId}]. This may occur if you have modified your gameObject/prefab without saving it, or the scene."); - result = null; - } - else - { - result = nob.NetworkBehaviours[componentIndex]; - } - } - -#if UNITY_EDITOR || DEVELOPMENT_BUILD - LastNetworkBehaviour = result; -#endif - return result; - } - - /// - /// Reads a NetworkBehaviour. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public NetworkBehaviour ReadNetworkBehaviour() - { - return ReadNetworkBehaviour(out _, out _); - } - - /// - /// Reads a DateTime. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public DateTime ReadDateTime() - { - DateTime result = DateTime.FromBinary(ReadInt64()); - return result; - } - - - /// - /// Reads a transport channel. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Channel ReadChannel() - { - return (Channel)ReadByte(); - } - - /// - /// Reads the Id for a NetworkConnection. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int ReadNetworkConnectionId() - { - return ReadInt16(); - } - - /// - /// Writes a NetworkConnection. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public NetworkConnection ReadNetworkConnection() - { - int value = ReadNetworkConnectionId(); - if (value == NetworkConnection.UNSET_CLIENTID_VALUE) - { - return FishNet.Managing.NetworkManager.EmptyConnection; - } - else - { - //Prefer server. - if (NetworkManager.IsServer) - { - NetworkConnection result; - if (NetworkManager.ServerManager.Clients.TryGetValueIL2CPP(value, out result)) - { - return result; - } - //If also client then try client side data. - else if (NetworkManager.IsClient) - { - //If found in client collection then return. - if (NetworkManager.ClientManager.Clients.TryGetValueIL2CPP(value, out result)) - return result; - /* Otherwise make a new instance. - * We do not know if this is for the server or client so - * initialize it either way. Connections rarely come through - * without being in server/client side collection. */ - else - return new NetworkConnection(NetworkManager, value, true); - - } - //Only server and not found. - else - { - NetworkManager.LogWarning($"Unable to find connection for read Id {value}. An empty connection will be returned."); - return FishNet.Managing.NetworkManager.EmptyConnection; - } - } - //Try client side, will only be able to fetch against local connection. - else - { - //If value is self then return self. - if (value == NetworkManager.ClientManager.Connection.ClientId) - return NetworkManager.ClientManager.Connection; - //Try client side dictionary. - else if (NetworkManager.ClientManager.Clients.TryGetValueIL2CPP(value, out NetworkConnection result)) - return result; - /* Otherwise make a new instance. - * We do not know if this is for the server or client so - * initialize it either way. Connections rarely come through - * without being in server/client side collection. */ - else - return new NetworkConnection(NetworkManager, value, true); - } - - } - } - - /// - /// Checks if the size could possibly be an allocation attack. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool CheckAllocationAttack(int size) - { - /* Possible attacks. Impossible size, or size indicates - * more elements in collection or more bytes needed - * than what bytes are available. */ - if (size != Writer.UNSET_COLLECTION_SIZE_VALUE && size < 0) - { - NetworkManager.LogError($"Size of {size} is invalid."); - return false; - } - if (size > Remaining) - { - NetworkManager.LogError($"Read size of {size} is larger than remaining data of {Remaining}."); - return false; - } - - //Checks pass. - return true; - } - - - #region Packed readers. - /// - /// ZigZag decode an integer. Move the sign bit back to the left. - /// - public ulong ZigZagDecode(ulong value) - { - ulong sign = value << 63; - if (sign > 0) - return ~(value >> 1) | sign; - return value >> 1; - } - /// - /// Reads a packed whole number. - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ulong ReadPackedWhole() - { - byte data = ReadByte(); - ulong result = (ulong)(data & 0x7F); - if ((data & 0x80) == 0) return result; - - data = ReadByte(); - result |= (ulong)(data & 0x7F) << 7; - if ((data & 0x80) == 0) return result; - - data = ReadByte(); - result |= (ulong)(data & 0x7F) << 14; - if ((data & 0x80) == 0) return result; - - data = ReadByte(); - result |= (ulong)(data & 0x7F) << 21; - if ((data & 0x80) == 0) return result; - - data = ReadByte(); - result |= (ulong)(data & 0x0F) << 28; - int extraBytes = data >> 4; - - switch (extraBytes) - { - case 0: - break; - case 1: - result |= (ulong)ReadByte() << 32; - break; - case 2: - result |= (ulong)ReadByte() << 32; - result |= (ulong)ReadByte() << 40; - break; - case 3: - result |= (ulong)ReadByte() << 32; - result |= (ulong)ReadByte() << 40; - result |= (ulong)ReadByte() << 48; - break; - case 4: - result |= (ulong)ReadByte() << 32; - result |= (ulong)ReadByte() << 40; - result |= (ulong)ReadByte() << 48; - result |= (ulong)ReadByte() << 56; - break; - } - return result; - } - #endregion - - #region Generators. - /// - /// Reads a replicate into collection and returns item count read. - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal int ReadReplicate(ref T[] collection, uint tick) where T : IReplicateData - { - //Number of entries written. - int count = (int)ReadByte(); - if (collection == null || collection.Length < count) - collection = new T[count]; - - /* Subtract count total minus 1 - * from starting tick. This sets the tick to what the first entry would be. - * EG packet came in as tick 100, so that was passed as tick. - * if there are 3 replicates then 2 would be subtracted (count - 1). - * The new tick would be 98. - * Ticks would be assigned to read values from oldest to - * newest as 98, 99, 100. Which is the correct result. In order for this to - * work properly past replicates cannot skip ticks. This will be ensured - * in another part of the code. */ - tick -= (uint)(count - 1); - - int fullPackType = ReadByte(); - //Read once and apply to all entries. - if (fullPackType > 0) - { - T value; - if (fullPackType == Writer.REPLICATE_ALL_DEFAULT_BYTE) - { - value = default(T); - } - else if (fullPackType == Writer.REPLICATE_REPEATING_BYTE) - { - value = Read(); - } - else - { - value = default(T); - NetworkManager?.LogError($"Unhandled Replicate pack type {fullPackType}."); - } - - for (int i = 0; i < count; i++) - { - collection[i] = value; - collection[i].SetTick(tick + (uint)i); - } - } - //Values vary, read each indicator. - else - { - T lastData = default; - - for (int i = 0; i < count; i++) - { - T value = default; - byte indicatorB = ReadByte(); - if (indicatorB == Writer.REPLICATE_DUPLICATE_BYTE) - { - value = lastData; - } - else if (indicatorB == Writer.REPLICATE_UNIQUE_BYTE) - { - value = Read(); - lastData = value; - } - else if (indicatorB == Writer.REPLICATE_DEFAULT_BYTE) - { - value = default(T); - } - - //Apply tick. - value.SetTick(tick + (uint)i); - //Assign to collection. - collection[i] = value; - } - } - - return count; - } - - /// - /// Reads a ListCache with allocations. - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ListCache ReadListCacheAllocated() - { - List lst = ReadListAllocated(); - ListCache lc = new ListCache(); - lc.Collection = lst; - return lc; - } - /// - /// Reads a ListCache and returns the item count read. - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int ReadListCache(ref ListCache listCache) - { - listCache.Collection = ReadListAllocated(); - return listCache.Collection.Count; - } - /// - /// Reads a list with allocations. - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List ReadListAllocated() - { - List result = null; - ReadList(ref result); - return result; - } - - /// - /// Reads into collection and returns item count read. - /// - /// - /// True to allow the referenced collection to be nullified when receiving a null collection read. - /// Number of values read into the collection. UNSET is returned if the collection were read as null. - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int ReadList(ref List collection, bool allowNullification = false) - { - int count = ReadInt32(); - if (count == Writer.UNSET_COLLECTION_SIZE_VALUE) - { - if (allowNullification) - collection = null; - return Writer.UNSET_COLLECTION_SIZE_VALUE; - } - else - { - if (collection == null) - collection = new List(count); - else - collection.Clear(); - - - for (int i = 0; i < count; i++) - collection.Add(Read()); - - return count; - } - } - /// - /// Reads an array. - /// - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public T[] ReadArrayAllocated() - { - T[] result = null; - ReadArray(ref result); - return result; - } - /// - /// Reads into collection and returns amount read. - /// - /// - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int ReadArray(ref T[] collection) - { - int count = ReadInt32(); - if (count == Writer.UNSET_COLLECTION_SIZE_VALUE) - { - return 0; - } - else if (count == 0) - { - if (collection == null) - collection = new T[0]; - - return 0; - } - else - { - //Initialize buffer if not already done. - if (collection == null) - collection = new T[count]; - else if (collection.Length < count) - Array.Resize(ref collection, count); - - for (int i = 0; i < count; i++) - collection[i] = Read(); - - return count; - } - } - - /// - /// Reads any supported type. - /// - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public T Read() - { - System.Type type = typeof(T); - if (IsAutoPackType(type, out AutoPackType packType)) - { - Func autopackDel = GenericReader.ReadAutoPack; - if (autopackDel == null) - { - LogError(GetLogMessage()); - return default; - } - else - { - return autopackDel.Invoke(this, packType); - } - } - else - { - Func del = GenericReader.Read; - if (del == null) - { - LogError(GetLogMessage()); - return default; - } - else - { - return del.Invoke(this); - } - } - - string GetLogMessage() => $"Read method not found for {type.FullName}. Use a supported type or create a custom serializer."; - } - - /// - /// Logs an error. - /// - /// - private void LogError(string msg) - { - if (NetworkManager == null) - NetworkManager.StaticLogError(msg); - else - NetworkManager.LogError(msg); - } - - /// - /// Returns if T takes AutoPackType argument. - /// - /// Outputs the default pack type for T. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal bool IsAutoPackType(out AutoPackType packType) => Writer.IsAutoPackType(out packType); - /// - /// Returns if T takes AutoPackType argument. - /// - /// Outputs the default pack type for T. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal bool IsAutoPackType(Type type, out AutoPackType packType) => Writer.IsAutoPackType(type, out packType); - #endregion - } -} diff --git a/Assets/FishNet/Runtime/Serializing/Reader.cs.meta b/Assets/FishNet/Runtime/Serializing/Reader.cs.meta deleted file mode 100644 index 228c99c..0000000 --- a/Assets/FishNet/Runtime/Serializing/Reader.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 680939c6cee93b64ba149da2029f4308 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/ReaderExtensions.cs b/Assets/FishNet/Runtime/Serializing/ReaderExtensions.cs deleted file mode 100644 index 5fc5767..0000000 --- a/Assets/FishNet/Runtime/Serializing/ReaderExtensions.cs +++ /dev/null @@ -1,18 +0,0 @@ -using FishNet.Connection; -using FishNet.Documenting; -using FishNet.Object; -using FishNet.Serializing.Helping; -using FishNet.Transporting; -using System; -using UnityEngine; - -namespace FishNet.Serializing -{ - /// - /// Extensions to Read methods. Used by Read. - /// - [APIExclude] - public static class ReaderExtensions - { - } -} diff --git a/Assets/FishNet/Runtime/Serializing/ReaderExtensions.cs.meta b/Assets/FishNet/Runtime/Serializing/ReaderExtensions.cs.meta deleted file mode 100644 index 1319c52..0000000 --- a/Assets/FishNet/Runtime/Serializing/ReaderExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: abcc77fe436138b4082ee27da3055bb3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/ReaderPool.cs b/Assets/FishNet/Runtime/Serializing/ReaderPool.cs deleted file mode 100644 index da918c0..0000000 --- a/Assets/FishNet/Runtime/Serializing/ReaderPool.cs +++ /dev/null @@ -1,68 +0,0 @@ -using FishNet.Managing; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace FishNet.Serializing -{ - /// - /// Reader which is reused to save on garbage collection and performance. - /// - public sealed class PooledReader : Reader, IDisposable - { - internal PooledReader(byte[] bytes, NetworkManager networkManager) : base(bytes, networkManager) { } - internal PooledReader(ArraySegment segment, NetworkManager networkManager) : base(segment, networkManager) { } - public void Dispose() => ReaderPool.Recycle(this); - } - - /// - /// Collection of PooledReader. Stores and gets PooledReader. - /// - public static class ReaderPool - { - #region Private. - /// - /// Pool of readers. - /// - private static readonly Stack _pool = new Stack(); - #endregion - - /// - /// Get the next reader in the pool - /// If pool is empty, creates a new Reader - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PooledReader GetReader(byte[] bytes, NetworkManager networkManager) - { - return GetReader(new ArraySegment(bytes), networkManager); - } - - /// - /// Get the next reader in the pool or creates a new one if none are available. - /// - public static PooledReader GetReader(ArraySegment segment, NetworkManager networkManager) - { - PooledReader result; - if (_pool.Count > 0) - { - result = _pool.Pop(); - result.Initialize(segment, networkManager); - } - else - { - result = new PooledReader(segment, networkManager); - } - - return result; - } - - /// - /// Puts reader back into pool - /// When pool is full, the extra reader is left for the GC - /// - public static void Recycle(PooledReader reader) - { - _pool.Push(reader); - } - } -} diff --git a/Assets/FishNet/Runtime/Serializing/ReaderPool.cs.meta b/Assets/FishNet/Runtime/Serializing/ReaderPool.cs.meta deleted file mode 100644 index eb0bdae..0000000 --- a/Assets/FishNet/Runtime/Serializing/ReaderPool.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 318b117dd2ebd1b4b9e2021796b45eee -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/ReaderStatics.cs b/Assets/FishNet/Runtime/Serializing/ReaderStatics.cs deleted file mode 100644 index d99bec2..0000000 --- a/Assets/FishNet/Runtime/Serializing/ReaderStatics.cs +++ /dev/null @@ -1,47 +0,0 @@ -using FishNet.Documenting; -using System; -using System.Text; - -namespace FishNet.Serializing -{ - - /// - /// Writes data to a buffer. - /// - [APIExclude] - internal class ReaderStatics - { - /* Since serializing occurs on the main thread this value may - * be shared among all readers. //multithread - */ - - #region Private. - /// - /// Buffer to copy Guids into. - /// - private static byte[] _guidBuffer = new byte[16]; - /// - /// Used to encode strings. - /// - private static readonly UTF8Encoding _encoding = new UTF8Encoding(false, true); - #endregion - - /// - /// Gets the GUID Buffer. - /// - /// - public static byte[] GetGuidBuffer() - { - return _guidBuffer; - } - - /// - /// Returns a string from data. - /// - public static string GetString(ArraySegment data) - { - return _encoding.GetString(data.Array, data.Offset, data.Count); - } - - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Serializing/ReaderStatics.cs.meta b/Assets/FishNet/Runtime/Serializing/ReaderStatics.cs.meta deleted file mode 100644 index 9c2ea4a..0000000 --- a/Assets/FishNet/Runtime/Serializing/ReaderStatics.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c1f98beaf8f697d4b8bb1e6b6ef32d42 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/SceneComparer.cs b/Assets/FishNet/Runtime/Serializing/SceneComparer.cs deleted file mode 100644 index 0e4c687..0000000 --- a/Assets/FishNet/Runtime/Serializing/SceneComparer.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections.Generic; -using UnityEngine.SceneManagement; - -namespace FishNet.Serializing.Helping -{ - internal sealed class SceneHandleEqualityComparer : EqualityComparer - { - public override bool Equals(Scene a, Scene b) - { - return (a.handle == b.handle); - } - - public override int GetHashCode(Scene obj) - { - return obj.handle; - } - } -} diff --git a/Assets/FishNet/Runtime/Serializing/SceneComparer.cs.meta b/Assets/FishNet/Runtime/Serializing/SceneComparer.cs.meta deleted file mode 100644 index 0e09f91..0000000 --- a/Assets/FishNet/Runtime/Serializing/SceneComparer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 161dbbe3995ff53479fc4e259f86549d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/TransformPackingData.cs b/Assets/FishNet/Runtime/Serializing/TransformPackingData.cs deleted file mode 100644 index 4d1d8d9..0000000 --- a/Assets/FishNet/Runtime/Serializing/TransformPackingData.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace FishNet.Serializing -{ - [System.Serializable] - internal class TransformPackingData - { - public AutoPackType Position = AutoPackType.Packed; - public AutoPackType Rotation = AutoPackType.Packed; - public AutoPackType Scale = AutoPackType.Packed; - } -} diff --git a/Assets/FishNet/Runtime/Serializing/TransformPackingData.cs.meta b/Assets/FishNet/Runtime/Serializing/TransformPackingData.cs.meta deleted file mode 100644 index 2c3013a..0000000 --- a/Assets/FishNet/Runtime/Serializing/TransformPackingData.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 80a80dabe02daf6428cce0f16ea49877 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/Writer.cs b/Assets/FishNet/Runtime/Serializing/Writer.cs deleted file mode 100644 index a7dd6c7..0000000 --- a/Assets/FishNet/Runtime/Serializing/Writer.cs +++ /dev/null @@ -1,1331 +0,0 @@ -using FishNet.Connection; -using FishNet.Documenting; -using FishNet.Managing; -using FishNet.Object; -using FishNet.Serializing.Helping; -using FishNet.Transporting; -using FishNet.Utility.Constant; -using FishNet.Utility.Performance; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -[assembly: InternalsVisibleTo(UtilityConstants.GENERATED_ASSEMBLY_NAME)] -namespace FishNet.Serializing -{ - - /// - /// Used for write references to generic types. - /// - /// - [APIExclude] - public static class GenericWriter - { - public static Action Write { get; set; } - public static Action WriteAutoPack { get; set; } - } - - /// - /// Writes data to a buffer. - /// - public class Writer - { - #region Public. - /// - /// Capacity of the buffer. - /// - public int Capacity => _buffer.Length; - /// - /// Current write position. - /// - public int Position; - /// - /// Number of bytes writen to the buffer. - /// - public int Length; - /// - /// NetworkManager associated with this writer. May be null. - /// - public NetworkManager NetworkManager; - #endregion - - #region Private. - /// - /// Buffer to prevent new allocations. This will grow as needed. - /// - private byte[] _buffer = new byte[64]; - #endregion - - #region Const. - /// - /// Replicate data is default of T. - /// - internal const byte REPLICATE_DEFAULT_BYTE = 0; - /// - /// Replicate data is the same as the previous. - /// - internal const byte REPLICATE_DUPLICATE_BYTE = 1; - /// - /// Replicate data is different from the previous. - /// - internal const byte REPLICATE_UNIQUE_BYTE = 2; - /// - /// Replicate data is repeating for every entry. - /// - internal const byte REPLICATE_REPEATING_BYTE = 3; - /// - /// All datas in the replicate are default. - /// - internal const byte REPLICATE_ALL_DEFAULT_BYTE = 4; - /// - /// Value used when a collection is unset, as in null. - /// - public const int UNSET_COLLECTION_SIZE_VALUE = -1; - #endregion - - /// - /// Resets the writer as though it was unused. Does not reset buffers. - /// - public void Reset(NetworkManager manager = null) - { - Length = 0; - Position = 0; - NetworkManager = manager; - } - - /// - /// Writes a dictionary. - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteDictionary(Dictionary dict) - { - if (dict == null) - { - WriteBoolean(true); - return; - } - else - { - WriteBoolean(false); - } - - WriteInt32(dict.Count); - foreach (KeyValuePair item in dict) - { - Write(item.Key); - Write(item.Value); - } - } - - /// - /// Ensures the buffer Capacity is of minimum count. - /// - /// - public void EnsureBufferCapacity(int count) - { - if (Capacity < count) - Array.Resize(ref _buffer, count); - } - - /// - /// Ensure a number of bytes to be available in the buffer from current position. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void EnsureBufferLength(int count) - { - if (Position + count > _buffer.Length) - { - int nextSize = (_buffer.Length * 2) + count; - Array.Resize(ref _buffer, nextSize); - } - } - - /// - /// Returns the buffer. The returned value will be the full buffer, even if not all of it is used. - /// - /// - public byte[] GetBuffer() - { - return _buffer; - } - - /// - /// Returns the used portion of the buffer as an ArraySegment. - /// - /// - public ArraySegment GetArraySegment() - { - return new ArraySegment(_buffer, 0, Length); - } - - /// - /// Reserves a number of bytes from current position. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Reserve(int count) - { - EnsureBufferLength(count); - Position += count; - Length = Math.Max(Length, Position); - } - - /// - /// Writes length. This method is used to make debugging easier. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void WriteLength(int length) - { - WriteInt32(length); - } - - /// - /// Sends a packetId. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void WritePacketId(PacketId pid) - { - WriteUInt16((ushort)pid); - } - - /// - /// Inserts value at index within the buffer. - /// This method does not perform error checks. - /// - /// - /// - [CodegenExclude] - public void FastInsertByte(byte value, int index) - { - _buffer[index] = value; - } - - /// - /// Writes a byte. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteByte(byte value) - { - EnsureBufferLength(1); - _buffer[Position++] = value; - - Length = Math.Max(Length, Position); - } - - /// - /// Writes bytes. - /// - /// - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteBytes(byte[] value, int offset, int count) - { - EnsureBufferLength(count); - Buffer.BlockCopy(value, offset, _buffer, Position, count); - Position += count; - Length = Math.Max(Length, Position); - } - - /// - /// Writes bytes and length of bytes. - /// - /// - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteBytesAndSize(byte[] value, int offset, int count) - { - if (value == null) - { - WriteInt32(Writer.UNSET_COLLECTION_SIZE_VALUE); - } - else - { - WriteInt32(count); - WriteBytes(value, offset, count); - } - } - - /// - /// Writes all bytes in value and length of bytes. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteBytesAndSize(byte[] value) - { - int size = (value == null) ? 0 : value.Length; - // buffer might be null, so we can't use .Length in that case - WriteBytesAndSize(value, 0, size); - } - - - /// - /// Writes a sbyte. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteSByte(sbyte value) - { - EnsureBufferLength(1); - _buffer[Position++] = (byte)value; - Length = Math.Max(Length, Position); - } - - /// - /// Writes a char. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteChar(char value) - { - EnsureBufferLength(2); - _buffer[Position++] = (byte)value; - _buffer[Position++] = (byte)(value >> 8); - Length = Math.Max(Length, Position); - } - - /// - /// Writes a boolean. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteBoolean(bool value) - { - EnsureBufferLength(1); - _buffer[Position++] = (value) ? (byte)1 : (byte)0; - Length = Math.Max(Length, Position); - } - - /// - /// Writes a uint16. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteUInt16(ushort value) - { - EnsureBufferLength(2); - _buffer[Position++] = (byte)value; - _buffer[Position++] = (byte)(value >> 8); - Length = Math.Max(Length, Position); - } - - /// - /// Writes a int16. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteInt16(short value) - { - EnsureBufferLength(2); - _buffer[Position++] = (byte)value; - _buffer[Position++] = (byte)(value >> 8); - Length = Math.Max(Length, Position); - } - - /// - /// Writes a int32. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteInt32(int value, AutoPackType packType = AutoPackType.Packed) - { - if (packType == AutoPackType.Packed) - WritePackedWhole(ZigZagEncode((ulong)value)); - else - WriteUInt32((uint)value, packType); - } - /// - /// Writes a uint32. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteUInt32(uint value, AutoPackType packType = AutoPackType.Packed) - { - if (packType == AutoPackType.Unpacked) - { - EnsureBufferLength(4); - WriterExtensions.WriteUInt32(_buffer, value, ref Position); - Length = Math.Max(Length, Position); - } - else - { - WritePackedWhole(value); - } - } - - /// - /// Writes an int64. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteInt64(long value, AutoPackType packType = AutoPackType.Packed) - { - if (packType == AutoPackType.Packed) - WritePackedWhole(ZigZagEncode((ulong)value)); - else - WriteUInt64((ulong)value, packType); - } - /// - /// Writes a uint64. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteUInt64(ulong value, AutoPackType packType = AutoPackType.Packed) - { - if (packType == AutoPackType.Unpacked) - { - EnsureBufferLength(8); - _buffer[Position++] = (byte)value; - _buffer[Position++] = (byte)(value >> 8); - _buffer[Position++] = (byte)(value >> 16); - _buffer[Position++] = (byte)(value >> 24); - _buffer[Position++] = (byte)(value >> 32); - _buffer[Position++] = (byte)(value >> 40); - _buffer[Position++] = (byte)(value >> 48); - _buffer[Position++] = (byte)(value >> 56); - - Length = Math.Max(Position, Length); - } - else - { - WritePackedWhole(value); - } - } - - /// - /// Writes a single (float). - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteSingle(float value, AutoPackType packType = AutoPackType.Unpacked) - { - if (packType == AutoPackType.Unpacked) - { - UIntFloat converter = new UIntFloat { FloatValue = value }; - WriteUInt32(converter.UIntValue, AutoPackType.Unpacked); - } - else - { - long converter = (long)(value * 100f); - WritePackedWhole((ulong)converter); - } - } - - /// - /// Writes a double. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteDouble(double value) - { - UIntDouble converter = new UIntDouble { DoubleValue = value }; - WriteUInt64(converter.LongValue, AutoPackType.Unpacked); - } - - /// - /// Writes a decimal. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteDecimal(decimal value) - { - UIntDecimal converter = new UIntDecimal { DecimalValue = value }; - WriteUInt64(converter.LongValue1, AutoPackType.Unpacked); - WriteUInt64(converter.LongValue2, AutoPackType.Unpacked); - } - - /// - /// Writes a string. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteString(string value) - { - if (value == null) - { - WriteInt32(Writer.UNSET_COLLECTION_SIZE_VALUE); - return; - } - else if (value.Length == 0) - { - WriteInt32(0); - return; - } - - /* Resize string buffer as needed. There's no harm in - * increasing buffer on writer side because sender will - * never intentionally inflict allocations on itself. - * Reader ensures string count cannot exceed received - * packet size. */ - int size; - byte[] stringBuffer = WriterStatics.GetStringBuffer(value, out size); - WriteInt32(size); - WriteBytes(stringBuffer, 0, size); - } - - /// - /// Writes a byte ArraySegment and it's size. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteArraySegmentAndSize(ArraySegment value) - { - WriteBytesAndSize(value.Array, value.Offset, value.Count); - } - - /// - /// Writes an ArraySegment without size. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteArraySegment(ArraySegment value) - { - WriteBytes(value.Array, value.Offset, value.Count); - } - - /// - /// Writes a Vector2. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector2(Vector2 value) - { - UIntFloat converter; - converter = new UIntFloat { FloatValue = value.x }; - WriteUInt32(converter.UIntValue, AutoPackType.Unpacked); - converter = new UIntFloat { FloatValue = value.y }; - WriteUInt32(converter.UIntValue, AutoPackType.Unpacked); - } - - /// - /// Writes a Vector3 - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector3(Vector3 value) - { - UIntFloat converter; - converter = new UIntFloat { FloatValue = value.x }; - WriteUInt32(converter.UIntValue, AutoPackType.Unpacked); - converter = new UIntFloat { FloatValue = value.y }; - WriteUInt32(converter.UIntValue, AutoPackType.Unpacked); - converter = new UIntFloat { FloatValue = value.z }; - WriteUInt32(converter.UIntValue, AutoPackType.Unpacked); - } - - /// - /// Writes a Vector4. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector4(Vector4 value) - { - UIntFloat converter; - converter = new UIntFloat { FloatValue = value.x }; - WriteUInt32(converter.UIntValue, AutoPackType.Unpacked); - converter = new UIntFloat { FloatValue = value.y }; - WriteUInt32(converter.UIntValue, AutoPackType.Unpacked); - converter = new UIntFloat { FloatValue = value.z }; - WriteUInt32(converter.UIntValue, AutoPackType.Unpacked); - converter = new UIntFloat { FloatValue = value.w }; - WriteUInt32(converter.UIntValue, AutoPackType.Unpacked); - } - - /// - /// Writes a Vector2Int. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector2Int(Vector2Int value, AutoPackType packType = AutoPackType.Packed) - { - WriteInt32(value.x, packType); - WriteInt32(value.y, packType); - } - - /// - /// Writes a Vector3Int. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector3Int(Vector3Int value, AutoPackType packType = AutoPackType.Packed) - { - WriteInt32(value.x, packType); - WriteInt32(value.y, packType); - WriteInt32(value.z, packType); - } - - /// - /// Writes a Color. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteColor(Color value, AutoPackType packType = AutoPackType.Packed) - { - if (packType == AutoPackType.Unpacked) - { - WriteSingle(value.r); - WriteSingle(value.g); - WriteSingle(value.b); - WriteSingle(value.a); - } - else - { - EnsureBufferLength(4); - _buffer[Position++] = (byte)(value.r * 100f); - _buffer[Position++] = (byte)(value.g * 100f); - _buffer[Position++] = (byte)(value.b * 100f); - _buffer[Position++] = (byte)(value.a * 100f); - - Length = Math.Max(Length, Position); - } - } - - /// - /// Writes a Color32. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteColor32(Color32 value) - { - EnsureBufferLength(4); - _buffer[Position++] = value.r; - _buffer[Position++] = value.g; - _buffer[Position++] = value.b; - _buffer[Position++] = value.a; - - Length = Math.Max(Length, Position); - } - - /// - /// Writes a Quaternion. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteQuaternion(Quaternion value, AutoPackType packType = AutoPackType.Packed) - { - if (packType == AutoPackType.Packed) - { - EnsureBufferLength(4); - uint result = Quaternion32Compression.Compress(value); - WriterExtensions.WriteUInt32(_buffer, result, ref Position); - Length = Math.Max(Length, Position); - } - else if (packType == AutoPackType.PackedLess) - { - EnsureBufferLength(8); - ulong result = Quaternion64Compression.Compress(value); - WriterExtensions.WriteUInt64(_buffer, result, ref Position); - Length = Math.Max(Length, Position); - } - else - { - EnsureBufferLength(16); - WriteSingle(value.x); - WriteSingle(value.y); - WriteSingle(value.z); - WriteSingle(value.w); - } - } - - /// - /// Writes a rect. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteRect(Rect value) - { - WriteSingle(value.xMin); - WriteSingle(value.yMin); - WriteSingle(value.width); - WriteSingle(value.height); - } - - /// - /// Writes a plane. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WritePlane(Plane value) - { - WriteVector3(value.normal); - WriteSingle(value.distance); - } - - /// - /// Writes a Ray. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteRay(Ray value) - { - WriteVector3(value.origin); - WriteVector3(value.direction); - } - - /// - /// Writes a Ray2D. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteRay2D(Ray2D value) - { - WriteVector2(value.origin); - WriteVector2(value.direction); - } - - - /// - /// Writes a Matrix4x4. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteMatrix4x4(Matrix4x4 value) - { - WriteSingle(value.m00); - WriteSingle(value.m01); - WriteSingle(value.m02); - WriteSingle(value.m03); - WriteSingle(value.m10); - WriteSingle(value.m11); - WriteSingle(value.m12); - WriteSingle(value.m13); - WriteSingle(value.m20); - WriteSingle(value.m21); - WriteSingle(value.m22); - WriteSingle(value.m23); - WriteSingle(value.m30); - WriteSingle(value.m31); - WriteSingle(value.m32); - WriteSingle(value.m33); - } - - /// - /// Writes a Guid. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteGuidAllocated(System.Guid value) - { - byte[] data = value.ToByteArray(); - WriteBytes(data, 0, data.Length); - } - - /// - /// Writes a GameObject. GameObject must be spawned over the network already or be a prefab with a NetworkObject attached. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteGameObject(GameObject go) - { - if (go == null) - { - WriteNetworkObject(null); - } - else - { - NetworkObject nob = go.GetComponent(); - WriteNetworkObject(nob); - } - } - - /// - /// Writes a Transform. Transform must be spawned over the network already or be a prefab with a NetworkObject attached. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteTransform(Transform t) - { - if (t == null) - { - WriteNetworkObject(null); - } - else - { - NetworkObject nob = t.GetComponent(); - WriteNetworkObject(nob); - } - } - - - /// - /// Writes a NetworkObject. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteNetworkObject(NetworkObject nob) - { - WriteNetworkObject(nob, false); - } - - /// - /// Writes a NetworkObject.ObjectId. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteNetworkObjectId(NetworkObject nob) - { - if (nob == null) - WriteUInt16(NetworkObject.UNSET_OBJECTID_VALUE); - else - WriteNetworkObjectId(nob.ObjectId); - } - - /// - /// Writes a NetworkObject while optionally including the initialization order. - /// - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void WriteNetworkObject(NetworkObject nob, bool forSpawn) - { - if (nob == null) - { - WriteUInt16(NetworkObject.UNSET_OBJECTID_VALUE); - } - else - { - bool spawned = nob.IsSpawned; - if (spawned) - WriteNetworkObjectId(nob.ObjectId); - else - WriteNetworkObjectId(nob.PrefabId); - - //Has to be written after objectId since that's expected first in reader. - if (forSpawn) - { - WriteUInt16(nob.SpawnableCollectionId); - WriteSByte(nob.GetInitializeOrder()); - } - - WriteBoolean(spawned); - } - } - - /// - /// Writes a NetworkObject for a despawn message. - /// - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void WriteNetworkObjectForDespawn(NetworkObject nob, DespawnType dt) - { - WriteNetworkObjectId(nob.ObjectId); - WriteByte((byte)dt); - } - - - /// - /// Writes an objectId. - /// - [CodegenExclude] - public void WriteNetworkObjectId(int objectId) - { - WriteUInt16((ushort)objectId); - } - - /// - /// Writes a NetworkObject for a spawn packet. - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void WriteNetworkObjectForSpawn(NetworkObject nob) - { - WriteNetworkObject(nob, true); - } - - /// - /// Writes a NetworkBehaviour. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteNetworkBehaviour(NetworkBehaviour nb) - { - if (nb == null) - { - WriteNetworkObject(null); - WriteByte(0); - } - else - { - WriteNetworkObject(nb.NetworkObject); - WriteByte(nb.ComponentIndex); - } - } - - /// - /// Writes a NetworkBehaviourId. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteNetworkBehaviourId(NetworkBehaviour nb) - { - if (nb == null) - { - WriteNetworkObjectId(null); - } - else - { - WriteNetworkObjectId(nb.NetworkObject); - WriteByte(nb.ComponentIndex); - } - } - - /// - /// Writes a DateTime. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteDateTime(DateTime dt) - { - WriteInt64(dt.ToBinary()); - } - - /// - /// Writes a transport channel. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteChannel(Channel channel) - { - WriteByte((byte)channel); - } - - /// - /// Writes a NetworkConnection. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteNetworkConnection(NetworkConnection connection) - { - int value = (connection == null) ? NetworkConnection.UNSET_CLIENTID_VALUE : connection.ClientId; - WriteInt16((short)value); - } - - /// - /// Writes a short for a connectionId. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteNetworkConnectionId(short id) - { - WriteInt16(id); - } - - /// - /// Writes a ListCache. - /// - /// ListCache to write. - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteListCache(ListCache lc) - { - WriteList(lc.Collection); - } - /// - /// Writes a list. - /// - /// Collection to write. - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteList(List value) - { - if (value == null) - WriteList(null, 0, 0); - else - WriteList(value, 0, value.Count); - } - #region Packed writers. - /// - /// ZigZag encode an integer. Move the sign bit to the right. - /// - [CodegenExclude] - public ulong ZigZagEncode(ulong value) - { - if (value >> 63 > 0) - return ~(value << 1) | 1; - return value << 1; - } - /// - /// Writes a packed whole number. - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WritePackedWhole(ulong value) - { - if (value < 0x80UL) - { - EnsureBufferLength(1); - _buffer[Position++] = (byte)(value & 0x7F); - } - else if (value < 0x4000UL) - { - EnsureBufferLength(2); - _buffer[Position++] = (byte)(0x80 | (value & 0x7F)); - _buffer[Position++] = (byte)((value >> 7) & 0x7F); - } - else if (value < 0x200000UL) - { - EnsureBufferLength(3); - _buffer[Position++] = (byte)(0x80 | (value & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 7) & 0x7F)); - _buffer[Position++] = (byte)((value >> 14) & 0x7F); - } - else if (value < 0x10000000UL) - { - EnsureBufferLength(4); - _buffer[Position++] = (byte)(0x80 | (value & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 7) & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 14) & 0x7F)); - _buffer[Position++] = (byte)((value >> 21) & 0x7F); - } - else if (value < 0x100000000UL) - { - EnsureBufferLength(5); - _buffer[Position++] = (byte)(0x80 | (value & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 7) & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 14) & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 21) & 0x7F)); - _buffer[Position++] = (byte)((value >> 28) & 0x0F); - } - else if (value < 0x10000000000UL) - { - EnsureBufferLength(6); - _buffer[Position++] = (byte)(0x80 | (value & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 7) & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 14) & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 21) & 0x7F)); - _buffer[Position++] = (byte)(0x10 | ((value >> 28) & 0x0F)); - _buffer[Position++] = (byte)((value >> 32) & 0xFF); - } - else if (value < 0x1000000000000UL) - { - EnsureBufferLength(7); - _buffer[Position++] = (byte)(0x80 | (value & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 7) & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 14) & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 21) & 0x7F)); - _buffer[Position++] = (byte)(0x20 | ((value >> 28) & 0x0F)); - _buffer[Position++] = (byte)((value >> 32) & 0xFF); - _buffer[Position++] = (byte)((value >> 40) & 0xFF); - } - else if (value < 0x100000000000000UL) - { - EnsureBufferLength(8); - _buffer[Position++] = (byte)(0x80 | (value & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 7) & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 14) & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 21) & 0x7F)); - _buffer[Position++] = (byte)(0x30 | ((value >> 28) & 0x0F)); - _buffer[Position++] = (byte)((value >> 32) & 0xFF); - _buffer[Position++] = (byte)((value >> 40) & 0xFF); - _buffer[Position++] = (byte)((value >> 48) & 0xFF); - } - else - { - EnsureBufferLength(9); - _buffer[Position++] = (byte)(0x80 | (value & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 7) & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 14) & 0x7F)); - _buffer[Position++] = (byte)(0x80 | ((value >> 21) & 0x7F)); - _buffer[Position++] = (byte)(0x40 | ((value >> 28) & 0x0F)); - _buffer[Position++] = (byte)((value >> 32) & 0xFF); - _buffer[Position++] = (byte)((value >> 40) & 0xFF); - _buffer[Position++] = (byte)((value >> 48) & 0xFF); - _buffer[Position++] = (byte)((value >> 56) & 0xFF); - } - - Length = Math.Max(Length, Position); - } - #endregion - - #region Generators. - /// - /// Writes a list. - /// - /// Collection to write. - /// Offset to begin at. - /// Entries to write. - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteList(List value, int offset, int count) - { - if (value == null) - { - WriteInt32(Writer.UNSET_COLLECTION_SIZE_VALUE); - } - else - { - //Make sure values cannot cause out of bounds. - if ((offset + count > value.Count)) - count = 0; - - WriteInt32(count); - for (int i = 0; i < count; i++) - Write(value[i + offset]); - } - } - /// - /// Writes a list. - /// - /// Collection to write. - /// Offset to begin at. - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteList(List value, int offset) - { - if (value == null) - WriteList(null, 0, 0); - else - WriteList(value, offset, value.Count - offset); - } - - /// - /// Writes a replication to the server. - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void WriteReplicate(List values, int offset) - { - /* COUNT - * - * Each Entry: - * 0 if the same as previous. - * 1 if default. */ - int collectionCount = values.Count; - //Replicate list will never be null, no need to write null check. - //Number of entries being written. - byte count = (byte)(collectionCount - offset); - WriteByte(count); - - //Get comparer. - Func compareDel = GeneratedComparer.Compare; - Func isDefaultDel = GeneratedComparer.IsDefault; - if (compareDel == null || isDefaultDel == null) - { - LogError($"ReplicateComparers not found for type {typeof(T).FullName}"); - return; - } - - T lastData = default; - /* It's possible to save more bytes by writing that they are all the same. - * Run a check, and if they are all the same then only write - * the first data with the same indicator code. */ - byte fullPackType = 0; - bool repeating = true; - bool allDefault = true; - for (int i = offset; i < collectionCount; i++) - { - T v = values[i]; - if (!isDefaultDel(v)) - allDefault = false; - - //Only check if i is larger than offset, giving us something in the past to check. - if (i > offset) - { - //Not repeating. - bool match = compareDel.Invoke(v, values[i - 1]); - if (!match) - { - repeating = false; - break; - } - } - - } - - if (allDefault) - fullPackType = REPLICATE_ALL_DEFAULT_BYTE; - else if (repeating) - fullPackType = REPLICATE_REPEATING_BYTE; - WriteByte(fullPackType); - - //If repeating only write the first entry. - if (repeating) - { - //Only write if not default. - if (!allDefault) - Write(values[offset]); - } - //Otherwise check each entry for differences. - else - { - for (int i = offset; i < collectionCount; i++) - { - T v = values[i]; - bool isDefault = isDefaultDel.Invoke(v); - //Default data, easy exit on writes. - if (isDefault) - { - WriteByte(REPLICATE_DEFAULT_BYTE); - } - //Data is not default. - else - { - //Same as last data. - bool match = compareDel.Invoke(v, lastData); - if (match) - { - WriteByte(REPLICATE_DUPLICATE_BYTE); - } - else - { - WriteByte(REPLICATE_UNIQUE_BYTE); - Write(v); - lastData = v; - } - } - } - } - } - - /// - /// Writes an array. - /// - /// Collection to write. - /// Offset to begin at. - /// Entries to write. - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteArray(T[] value, int offset, int count) - { - if (value == null) - { - WriteInt32(Writer.UNSET_COLLECTION_SIZE_VALUE); - } - else - { - //If theres no values, or offset exceeds count then write 0 for count. - if (value.Length == 0 || (offset >= count)) - { - WriteInt32(0); - } - else - { - WriteInt32(count); - for (int i = offset; i < count; i++) - Write(value[i]); - } - } - } - /// - /// Writes an array. - /// - /// Collection to write. - /// Offset to begin at. - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteArray(T[] value, int offset) - { - if (value == null) - WriteArray(null, 0, 0); - else - WriteArray(value, offset, value.Length - offset); - } - /// - /// Writes an array. - /// - /// Collection to write. - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteArray(T[] value) - { - if (value == null) - WriteArray(null, 0, 0); - else - WriteArray(value, 0, value.Length); - } - - - /// - /// Writers any supported type. - /// - /// - /// - [CodegenExclude] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Write(T value) - { - System.Type type = typeof(T); - if (IsAutoPackType(type, out AutoPackType packType)) - { - Action del = GenericWriter.WriteAutoPack; - if (del == null) - LogError(GetLogMessage()); - else - del.Invoke(this, value, packType); - } - else - { - Action del = GenericWriter.Write; - if (del == null) - LogError(GetLogMessage()); - else - del.Invoke(this, value); - } - - string GetLogMessage() => $"Write method not found for {type.FullName}. Use a supported type or create a custom serializer."; - } - - /// - /// Logs an error. - /// - /// - private void LogError(string msg) - { - if (NetworkManager == null) - NetworkManager.StaticLogError(msg); - else - NetworkManager.LogError(msg); - } - - /// - /// Returns if T takes AutoPackType argument. - /// - /// Outputs the default pack type for T. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static bool IsAutoPackType(out AutoPackType packType) - { - System.Type type = typeof(T); - return IsAutoPackType(type, out packType); - } - internal static bool IsAutoPackType(Type type, out AutoPackType packType) - { - if (WriterExtensions.DefaultPackedTypes.Contains(type)) - { - packType = AutoPackType.Packed; - return true; - } - else if (type == typeof(float)) - { - packType = AutoPackType.Unpacked; - return true; - } - else - { - packType = AutoPackType.Unpacked; - return false; - } - } - #endregion - - } -} diff --git a/Assets/FishNet/Runtime/Serializing/Writer.cs.meta b/Assets/FishNet/Runtime/Serializing/Writer.cs.meta deleted file mode 100644 index bfbcd29..0000000 --- a/Assets/FishNet/Runtime/Serializing/Writer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e2633f927065d9d43b8a4da09240266c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/WriterExtensions.cs b/Assets/FishNet/Runtime/Serializing/WriterExtensions.cs deleted file mode 100644 index 8f727c7..0000000 --- a/Assets/FishNet/Runtime/Serializing/WriterExtensions.cs +++ /dev/null @@ -1,113 +0,0 @@ -using FishNet.Connection; -using FishNet.Documenting; -using FishNet.Object; -using FishNet.Serializing.Helping; -using FishNet.Transporting; -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.Serializing -{ - - /// - /// Extensions to Write methods. Used by Write. - /// - [APIExclude] - public static class WriterExtensions - { - - /// - /// Types which are are set to auto pack by default. - /// - internal static HashSet DefaultPackedTypes = new HashSet(); - - static WriterExtensions() - { - DefaultPackedTypes.Add(typeof(int)); - DefaultPackedTypes.Add(typeof(uint)); - DefaultPackedTypes.Add(typeof(long)); - DefaultPackedTypes.Add(typeof(ulong)); - DefaultPackedTypes.Add(typeof(Color)); - DefaultPackedTypes.Add(typeof(Vector2Int)); - DefaultPackedTypes.Add(typeof(Vector3Int)); - DefaultPackedTypes.Add(typeof(Quaternion)); - } - - /// - /// Writes value to dst without error checking. - /// - [CodegenExclude] - internal static void WriteUInt32(byte[] dst, uint value, ref int position) - { - dst[position++] = (byte)value; - dst[position++] = (byte)(value >> 8); - dst[position++] = (byte)(value >> 16); - dst[position++] = (byte)(value >> 24); - } - /// - /// Writes value to dst without error checking. - /// - [CodegenExclude] - internal static void WriteUInt64(byte[] dst, ulong value, ref int position) - { - dst[position++] = (byte)value; - dst[position++] = (byte)(value >> 8); - dst[position++] = (byte)(value >> 16); - dst[position++] = (byte)(value >> 24); - dst[position++] = (byte)(value >> 32); - dst[position++] = (byte)(value >> 40); - dst[position++] = (byte)(value >> 48); - dst[position++] = (byte)(value >> 56); - } - - - //public static void WriteDictionary(this Writer writer, Dictionary dict) => writer.WriteDictionary(dict); - //public static void WriteByte(this Writer writer, byte value) => writer.WriteByte(value); - //[CodegenExclude] - //public static void WriteBytes(this Writer writer, byte[] buffer, int offset, int count) => writer.WriteBytes(buffer, offset, count); - //[CodegenExclude] - //public static void WriteBytesAndSize(this Writer writer, byte[] buffer, int offset, int count) => writer.WriteBytesAndSize(buffer, offset, count); - //public static void WriteBytesAndSize(this Writer writer, byte[] value) => writer.WriteBytesAndSize(value); - - //public static void WriteSByte(this Writer writer, sbyte value) => writer.WriteSByte(value); - //public static void WriteChar(this Writer writer, char value) => writer.WriteChar(value); - //public static void WriteBoolean(this Writer writer, bool value) => writer.WriteBoolean(value); - //public static void WriteUInt16(this Writer writer, ushort value) => writer.WriteUInt16(value); - //public static void WriteInt16(this Writer writer, short value) => writer.WriteInt16(value); - //public static void WriteInt32(this Writer writer, int value, AutoPackType packType = AutoPackType.Packed) => writer.WriteInt32(value, packType); - //public static void WriteUInt32(this Writer writer, uint value, AutoPackType packType = AutoPackType.Packed) => writer.WriteUInt32(value, packType); - //public static void WriteInt64(this Writer writer, long value, AutoPackType packType = AutoPackType.Packed) => writer.WriteInt64(value, packType); - //public static void WriteUInt64(this Writer writer, ulong value, AutoPackType packType = AutoPackType.Packed) => writer.WriteUInt64(value, packType); - //public static void WriteSingle(this Writer writer, float value, AutoPackType packType = AutoPackType.Unpacked) => writer.WriteSingle(value, packType); - //public static void WriteDouble(this Writer writer, double value) => writer.WriteDouble(value); - //public static void WriteDecimal(this Writer writer, decimal value) => writer.WriteDecimal(value); - //public static void WriteString(this Writer writer, string value) => writer.WriteString(value); - //public static void WriteArraySegmentAndSize(this Writer writer, ArraySegment value) => writer.WriteArraySegmentAndSize(value); - //[CodegenExclude] - //public static void WriteArraySegment(this Writer writer, ArraySegment value) => writer.WriteArraySegment(value); - //public static void WriteVector2(this Writer writer, Vector2 value) => writer.WriteVector2(value); - //public static void WriteVector3(this Writer writer, Vector3 value) => writer.WriteVector3(value); - //public static void WriteVector4(this Writer writer, Vector4 value) => writer.WriteVector4(value); - //public static void WriteVector2Int(this Writer writer, Vector2Int value, AutoPackType packType = AutoPackType.Packed) => writer.WriteVector2Int(value, packType); - //public static void WriteVector3Int(this Writer writer, Vector3Int value, AutoPackType packType = AutoPackType.Packed) => writer.WriteVector3Int(value, packType); - //public static void WriteColor(this Writer writer, Color value, AutoPackType packType) => writer.WriteColor(value, packType); - //public static void WriteColor32(this Writer writer, Color32 value) => writer.WriteColor32(value); - //public static void WriteQuaternion(this Writer writer, Quaternion value, AutoPackType packType = AutoPackType.Packed) => writer.WriteQuaternion(value, packType); - //public static void WriteRect(this Writer writer, Rect value) => writer.WriteRect(value); - //public static void WritePlane(this Writer writer, Plane value) => writer.WritePlane(value); - //public static void WriteRay(this Writer writer, Ray value) => writer.WriteRay(value); - //public static void WriteRay2D(this Writer writer, Ray2D value) => writer.WriteRay2D(value); - //public static void WriteMatrix4x4(this Writer writer, Matrix4x4 value) => writer.WriteMatrix4x4(value); - //public static void WriteGuidAllocated(this Writer writer, System.Guid value) => writer.WriteGuidAllocated(value); - //public static void WriteGameObject(this Writer writer, GameObject value) => writer.WriteGameObject(value); - //public static void WriteTransform(this Writer writer, Transform value) => writer.WriteTransform(value); - //public static void WriteNetworkObject(this Writer writer, NetworkObject value) => writer.WriteNetworkObject(value); - //public static void WriteNetworkBehaviour(this Writer writer, NetworkBehaviour value) => writer.WriteNetworkBehaviour(value); - //public static void WriteChannel(this Writer writer, Channel value) => writer.WriteChannel(value); - //public static void WriteNetworkConnection(this Writer writer, NetworkConnection value) => writer.WriteNetworkConnection(value); - //[CodegenExclude] - //public static void Write(this Writer writer, T value) => writer.Write(value); - - } -} diff --git a/Assets/FishNet/Runtime/Serializing/WriterExtensions.cs.meta b/Assets/FishNet/Runtime/Serializing/WriterExtensions.cs.meta deleted file mode 100644 index a2229b9..0000000 --- a/Assets/FishNet/Runtime/Serializing/WriterExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 493e880d63e9372449c0f0e63890aaef -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/WriterPool.cs b/Assets/FishNet/Runtime/Serializing/WriterPool.cs deleted file mode 100644 index 8a6f250..0000000 --- a/Assets/FishNet/Runtime/Serializing/WriterPool.cs +++ /dev/null @@ -1,159 +0,0 @@ -using FishNet.Managing; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace FishNet.Serializing -{ - /// - /// Writer which is reused to save on garbage collection and performance. - /// - public sealed class PooledWriter : Writer, IDisposable - { - public void Dispose() => WriterPool.Recycle(this); - public void DisposeLength() => WriterPool.RecycleLength(this); - } - - /// - /// Collection of PooledWriter. Stores and gets PooledWriter. - /// - public static class WriterPool - { - #region Private. - /// - /// Pool of writers where length is the minimum and increased at runtime. - /// - private static readonly Stack _pool = new Stack(); - /// - /// Pool of writers where length is of minimum key and may be increased at runtime. - /// - private static readonly Dictionary> _lengthPool = new Dictionary>(); - #endregion - - #region Const. - /// - /// Length of each bracket when using the length based writer pool. - /// - internal const int LENGTH_BRACKET = 1000; - #endregion - - /// - /// Gets a writer from the pool. - /// - public static PooledWriter GetWriter(NetworkManager networkManager) - { - PooledWriter result = (_pool.Count > 0) ? _pool.Pop() : new PooledWriter(); - result.Reset(networkManager); - return result; - } - /// - /// Gets a writer from the pool. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PooledWriter GetWriter() - { - return GetWriter(null); - } - - /// - /// Gets which index to use for length based pooled readers based on length. - /// - private static int GetDictionaryIndex(int length) - { - return (length / LENGTH_BRACKET); - } - /// - /// Gets the next writer in the pool of minimum length. - /// - /// Minimum length the writer buffer must be. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PooledWriter GetWriter(int length) - { - return GetWriter(null, length); - } - /// - /// Gets the next writer in the pool of minimum length. - /// - /// Minimum length the writer buffer must be. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PooledWriter GetWriter(NetworkManager networkManager, int length) - { - //Ensure length is the minimum. - if (length < LENGTH_BRACKET) - length = LENGTH_BRACKET; - - /* The index returned will be for writers which have - * length as a minimum capacity. - * EG: if length is 1200 / 1000 (length_bracket) result - * will be index 1. Index 0 will be up to 1000, while - * index 1 will be up to 2000. */ - int dictIndex = GetDictionaryIndex(length); - Stack stack; - //There is already one pooled. - if (_lengthPool.TryGetValue(dictIndex, out stack) && stack.Count > 0) - { - PooledWriter result = stack.Pop(); - result.Reset(networkManager); - return result; - } - //Not pooled yet. - else - { - //Get any ol' writer. - PooledWriter writer = GetWriter(networkManager); - /* Ensure length to fill it's bracket. - * Increase index by 1 since 0 index would - * just return 0 as the capacity. */ - int requiredCapacity = (dictIndex + 1) * LENGTH_BRACKET; - writer.EnsureBufferCapacity(requiredCapacity); - return writer; - } - } - - /// - /// Returns a writer to the appropriate length pool. - /// Writers must be a minimum of 1000 bytes in length to be sorted by length. - /// Writers which do not meet the minimum will be resized to 1000 bytes. - /// - public static void RecycleLength(PooledWriter writer) - { - int capacity = writer.Capacity; - /* If capacity is less than 1000 then the writer - * does not meet the minimum length bracket. This should never - * be the case unless the user perhaps manually calls this method. */ - if (capacity < LENGTH_BRACKET) - { - capacity = LENGTH_BRACKET; - writer.EnsureBufferCapacity(LENGTH_BRACKET); - } - - /* When getting the recycle index subtract one from - * the dictionary index. This is because the writer being - * recycled must meet the minimum for that index. - * EG: if LENGTH_BRACKET is 1000.... - * 1200 / 1000 = 1(after flooring). - * However, each incremeent in index should have a capacity - * of 1000, so index 1 should have a minimum capacity of 2000, - * which 1200 does not meet. By subtracting 1 from the index - * 1200 will now be placed in index 0 meeting the capacity for that index. */ - int dictIndex = GetDictionaryIndex(capacity) - 1; - Stack stack; - if (!_lengthPool.TryGetValue(dictIndex, out stack)) - { - stack = new Stack(); - _lengthPool[dictIndex] = stack; - } - - stack.Push(writer); - } - - - /// - /// Returns a writer to the pool. - /// - public static void Recycle(PooledWriter writer) - { - _pool.Push(writer); - } - } -} diff --git a/Assets/FishNet/Runtime/Serializing/WriterPool.cs.meta b/Assets/FishNet/Runtime/Serializing/WriterPool.cs.meta deleted file mode 100644 index 2507ad0..0000000 --- a/Assets/FishNet/Runtime/Serializing/WriterPool.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 99b13ccd24eb7264abf67780ef86e44a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Serializing/WriterStatics.cs b/Assets/FishNet/Runtime/Serializing/WriterStatics.cs deleted file mode 100644 index 6a3cc02..0000000 --- a/Assets/FishNet/Runtime/Serializing/WriterStatics.cs +++ /dev/null @@ -1,61 +0,0 @@ -using FishNet.Documenting; -using System; -using System.Text; - -namespace FishNet.Serializing -{ - - /// - /// Writes data to a buffer. - /// - [APIExclude] - internal class WriterStatics - { - /* Since serializing occurs on the main thread this value may - * be shared among all writers. //multithread - */ - - #region Private. - /// - /// Encoder for strings. - /// - private static readonly UTF8Encoding _encoding = new UTF8Encoding(false, true); - /// - /// StringBuffer to use with encoding. - /// - private static byte[] _stringBuffer = new byte[64]; - #endregion - - /// - /// Gets the string buffer ensuring proper length, and outputs size in bytes of string. - /// - public static byte[] GetStringBuffer(string str, out int size) - { - int strLength = str.Length; - int valueMaxBytes = _encoding.GetMaxByteCount(strLength); - if (valueMaxBytes >= _stringBuffer.Length) - { - int nextSize = (_stringBuffer.Length * 2) + valueMaxBytes; - Array.Resize(ref _stringBuffer, nextSize); - } - - size = _encoding.GetBytes(str, 0, strLength, _stringBuffer, 0); - return _stringBuffer; - - } - /// - /// Ensures the string buffer is of a minimum length and returns the buffer. - /// - public static byte[] GetStringBuffer(string str) - { - int valueMaxBytes = _encoding.GetMaxByteCount(str.Length); - if (valueMaxBytes >= _stringBuffer.Length) - { - int nextSize = (_stringBuffer.Length * 2) + valueMaxBytes; - Array.Resize(ref _stringBuffer, nextSize); - } - - return _stringBuffer; - } - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Serializing/WriterStatics.cs.meta b/Assets/FishNet/Runtime/Serializing/WriterStatics.cs.meta deleted file mode 100644 index b690420..0000000 --- a/Assets/FishNet/Runtime/Serializing/WriterStatics.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 264951af6d87de34e8809b550a7956b1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting.meta b/Assets/FishNet/Runtime/Transporting.meta deleted file mode 100644 index b4e33ce..0000000 --- a/Assets/FishNet/Runtime/Transporting.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 693688363b7a8f746a35a5a6168d82b9 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: '' - assetBundleName: '' - assetBundleVariant: '' diff --git a/Assets/FishNet/Runtime/Transporting/Channels.cs b/Assets/FishNet/Runtime/Transporting/Channels.cs deleted file mode 100644 index 195adef..0000000 --- a/Assets/FishNet/Runtime/Transporting/Channels.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace FishNet.Transporting -{ - /// - /// Channel which data is sent or received. - /// - public enum Channel : byte - { - /// - /// Data will be sent ordered reliable. - /// - Reliable = 0, - /// - /// Data will be sent unreliable. - /// - Unreliable = 1 - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Transporting/Channels.cs.meta b/Assets/FishNet/Runtime/Transporting/Channels.cs.meta deleted file mode 100644 index 1227bfa..0000000 --- a/Assets/FishNet/Runtime/Transporting/Channels.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7cd503d67a974984385164c53bd3e518 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/ConnectionStates.cs b/Assets/FishNet/Runtime/Transporting/ConnectionStates.cs deleted file mode 100644 index ba0a35b..0000000 --- a/Assets/FishNet/Runtime/Transporting/ConnectionStates.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace FishNet.Transporting -{ - - /// - /// States the local connection can be in. - /// - public enum LocalConnectionState : byte - { - /// - /// Connection is fully stopped. - /// - Stopped = 0, - /// - /// Connection is starting but not yet established. - /// - Starting = 1, - /// - /// Connection is established. - /// - Started = 2, - /// - /// Connection is stopping. - /// - Stopping = 3 - } - - /// - /// States a remote client can be in. - /// - public enum RemoteConnectionState : byte - { - /// - /// Connection is fully stopped. - /// - Stopped = 0, - /// - /// Connection is established. - /// - Started = 2, - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Transporting/ConnectionStates.cs.meta b/Assets/FishNet/Runtime/Transporting/ConnectionStates.cs.meta deleted file mode 100644 index cb22c93..0000000 --- a/Assets/FishNet/Runtime/Transporting/ConnectionStates.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 45640e2b3919981499b359ecc2154d3f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/EventStructures.cs b/Assets/FishNet/Runtime/Transporting/EventStructures.cs deleted file mode 100644 index 93ef9ae..0000000 --- a/Assets/FishNet/Runtime/Transporting/EventStructures.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; - -namespace FishNet.Transporting -{ - /// - /// Container about data received on the server. - /// - public struct ServerReceivedDataArgs - { - /// - /// Data received. - /// - public ArraySegment Data; - /// - /// Channel data was received on. - /// - public Channel Channel; - /// - /// ConnectionId from which client sent data, if data was received on the server. - /// - public int ConnectionId; - /// - /// Index of the transport that is for. - /// This is primarily used when supporting multiple transports. - /// - public int TransportIndex; - /// - /// Delegate to invoke after data is processed. - /// - /// - public Action FinalizeMethod; - - public ServerReceivedDataArgs(ArraySegment data, Channel channel, int connectionId, int transportIndex) - { - Data = data; - Channel = channel; - ConnectionId = connectionId; - TransportIndex = transportIndex; - FinalizeMethod = null; - } - public ServerReceivedDataArgs(ArraySegment data, Channel channel, int connectionId, int transportIndex, Action finalizeMethod) - { - Data = data; - Channel = channel; - ConnectionId = connectionId; - TransportIndex = transportIndex; - FinalizeMethod = finalizeMethod; - } - } - - - /// - /// Container about data received on the local client. - /// - public struct ClientReceivedDataArgs - { - /// - /// Data received. - /// - public ArraySegment Data; - /// - /// Channel data was received on. - /// - public Channel Channel; - /// - /// Index of the transport that is for. - /// This is primarily used when supporting multiple transports. - /// - public int TransportIndex; - - public ClientReceivedDataArgs(ArraySegment data, Channel channel, int transportIndex) - { - Data = data; - Channel = channel; - TransportIndex = transportIndex; - } - } - - - - /// - /// Container about a connection state change for a client. - /// - public struct RemoteConnectionStateArgs - { - /// - /// Index of the transport that is for. - /// This is primarily used when supporting multiple transports. - /// - public int TransportIndex; - /// - /// New connection state. - /// - public RemoteConnectionState ConnectionState; - /// - /// ConnectionId for which client the state changed. Will be -1 if ConnectionState was for the local server. - /// - public int ConnectionId; - - public RemoteConnectionStateArgs(RemoteConnectionState connectionState, int connectionId, int transportIndex) - { - ConnectionState = connectionState; - ConnectionId = connectionId; - TransportIndex = transportIndex; - } - } - - /// - /// Container about a connection state change for the server. - /// - public struct ServerConnectionStateArgs - { - /// - /// Index of the transport that is for. - /// This is primarily used when supporting multiple transports. - /// - public int TransportIndex; - /// - /// New connection state. - /// - public LocalConnectionState ConnectionState; - - public ServerConnectionStateArgs(LocalConnectionState connectionState, int transportIndex) - { - ConnectionState = connectionState; - TransportIndex = transportIndex; - } - } - - /// - /// Container about a connection state change for the local client. - /// - public struct ClientConnectionStateArgs - { - /// - /// New connection state. - /// - public LocalConnectionState ConnectionState; - /// - /// Index of the transport that is for. - /// This is primarily used when supporting multiple transports. - /// - public int TransportIndex; - - public ClientConnectionStateArgs(LocalConnectionState connectionState, int transportIndex) - { - ConnectionState = connectionState; - TransportIndex = transportIndex; - } - } -} - diff --git a/Assets/FishNet/Runtime/Transporting/EventStructures.cs.meta b/Assets/FishNet/Runtime/Transporting/EventStructures.cs.meta deleted file mode 100644 index 3113c88..0000000 --- a/Assets/FishNet/Runtime/Transporting/EventStructures.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 718b9d27800e70848b50b2c7b0117e5c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/IPAddressType.cs b/Assets/FishNet/Runtime/Transporting/IPAddressType.cs deleted file mode 100644 index 0cc079e..0000000 --- a/Assets/FishNet/Runtime/Transporting/IPAddressType.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace FishNet.Transporting -{ - /// - /// Channel which data is sent or received. - /// - public enum IPAddressType : byte - { - /// - /// Address is IPv4. - /// - IPv4 = 0, - /// - /// Address is IPv6. - /// - IPv6 = 1 - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Transporting/IPAddressType.cs.meta b/Assets/FishNet/Runtime/Transporting/IPAddressType.cs.meta deleted file mode 100644 index 4522f21..0000000 --- a/Assets/FishNet/Runtime/Transporting/IPAddressType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 11a2c7610ce4ce34a915683bd4607714 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/NetworkReaderLoop.cs b/Assets/FishNet/Runtime/Transporting/NetworkReaderLoop.cs deleted file mode 100644 index e5953b4..0000000 --- a/Assets/FishNet/Runtime/Transporting/NetworkReaderLoop.cs +++ /dev/null @@ -1,33 +0,0 @@ -using FishNet.Managing.Timing; -using UnityEngine; - -namespace FishNet.Transporting -{ - [DisallowMultipleComponent] - [DefaultExecutionOrder(short.MinValue)] - internal class NetworkReaderLoop : MonoBehaviour - { - #region Private. - /// - /// TimeManager this loop is for. - /// - private TimeManager _timeManager; - #endregion - - private void Awake() - { - _timeManager = GetComponent(); - } - - private void FixedUpdate() - { - _timeManager.TickFixedUpdate(); - } - private void Update() - { - _timeManager.TickUpdate(); - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Transporting/NetworkReaderLoop.cs.meta b/Assets/FishNet/Runtime/Transporting/NetworkReaderLoop.cs.meta deleted file mode 100644 index f4ed745..0000000 --- a/Assets/FishNet/Runtime/Transporting/NetworkReaderLoop.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0d359d6ef33641f41a2ae67d1abdfdd3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/NetworkWriterLoop.cs b/Assets/FishNet/Runtime/Transporting/NetworkWriterLoop.cs deleted file mode 100644 index 634ee44..0000000 --- a/Assets/FishNet/Runtime/Transporting/NetworkWriterLoop.cs +++ /dev/null @@ -1,38 +0,0 @@ -using FishNet.Managing.Timing; -using UnityEngine; - -namespace FishNet.Transporting -{ - [DisallowMultipleComponent] - [DefaultExecutionOrder(short.MaxValue)] - internal class NetworkWriterLoop : MonoBehaviour - { - #region Private. - /// - /// TimeManager this loop is for. - /// - private TimeManager _timeManager; - #endregion - - private void Awake() - { - _timeManager = GetComponent(); - } - - private void LateUpdate() - { - Iterate(); - } - - /// - /// Performs read on transport. - /// - private void Iterate() - { - _timeManager.TickLateUpdate(); - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Transporting/NetworkWriterLoop.cs.meta b/Assets/FishNet/Runtime/Transporting/NetworkWriterLoop.cs.meta deleted file mode 100644 index 3038d73..0000000 --- a/Assets/FishNet/Runtime/Transporting/NetworkWriterLoop.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2fed05d526ab23949bac6cd2bf041c35 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/PacketId.cs b/Assets/FishNet/Runtime/Transporting/PacketId.cs deleted file mode 100644 index cfb818a..0000000 --- a/Assets/FishNet/Runtime/Transporting/PacketId.cs +++ /dev/null @@ -1,33 +0,0 @@ -using FishNet.Documenting; - -namespace FishNet.Transporting -{ - - /// - /// PacketIds to indicate the type of packet which is being sent or arriving. - /// - [APIExclude] - public enum PacketId : ushort - { - Unset = 0, - Authenticated = 1, - Split = 2, - ObjectSpawn = 3, - ObjectDespawn = 4, - PredictedSpawnResult = 5, - SyncVar = 7, - ServerRpc = 8, - ObserversRpc = 9, - TargetRpc = 10, - OwnershipChange = 11, - Broadcast = 12, - SyncObject = 13, - PingPong = 14, - Replicate = 15, - Reconcile = 16, - Disconnect = 17, - TimingUpdate = 18, - NetworkLODUpdate = 19, - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Transporting/PacketId.cs.meta b/Assets/FishNet/Runtime/Transporting/PacketId.cs.meta deleted file mode 100644 index 6fa4a88..0000000 --- a/Assets/FishNet/Runtime/Transporting/PacketId.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3f3b7256982245b46a2925e2b94ce149 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transport.cs b/Assets/FishNet/Runtime/Transporting/Transport.cs deleted file mode 100644 index db012f2..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transport.cs +++ /dev/null @@ -1,243 +0,0 @@ -using FishNet.Managing; -using FishNet.Managing.Logging; -using System; -using UnityEngine; - -namespace FishNet.Transporting -{ - - /// - /// Processes connection states, and data sent to and from a socket. - /// - public abstract class Transport : MonoBehaviour - { - #region Private. - /// - /// NetworkManager for this transport. - /// - public NetworkManager NetworkManager { get; private set; } - /// - /// Index this transport belongs to when using multiple transports at once. - /// - public int Index { get; private set; } - #endregion - - #region Initialization and unity. - /// - /// Initializes the transport. Use this instead of Awake. - /// Index this transport belongs to when using multiple transports at once. - /// - public virtual void Initialize(NetworkManager networkManager, int transportIndex) - { - NetworkManager = networkManager; - Index = transportIndex; - } - #endregion - - #region ConnectionStates. - /// - /// Gets the address of a remote connection Id. - /// - /// Connectionid to get the address for. - /// - public abstract string GetConnectionAddress(int connectionId); - /// - /// Called when a connection state changes for the local client. - /// - public abstract event Action OnClientConnectionState; - /// - /// Called when a connection state changes for the local server. - /// - public abstract event Action OnServerConnectionState; - /// - /// Called when a connection state changes for a remote client. - /// - public abstract event Action OnRemoteConnectionState; - /// - /// Handles a ConnectionStateArgs for the local client. - /// - /// Data being handled. - public abstract void HandleClientConnectionState(ClientConnectionStateArgs connectionStateArgs); - /// - /// Handles a ConnectionStateArgs for the local server. - /// - /// Data being handled. - public abstract void HandleServerConnectionState(ServerConnectionStateArgs connectionStateArgs); - /// - /// Handles a ConnectionStateArgs for a remote client. - /// - /// Data being handled. - public abstract void HandleRemoteConnectionState(RemoteConnectionStateArgs connectionStateArgs); - /// - /// Gets the current local ConnectionState. - /// - /// True if getting ConnectionState for the server. - public abstract LocalConnectionState GetConnectionState(bool server); - /// - /// Gets the current ConnectionState of a client connected to the server. Can only be called on the server. - /// - /// ConnectionId to get ConnectionState for. - public abstract RemoteConnectionState GetConnectionState(int connectionId); - #endregion - - #region Sending. - /// - /// Sends to the server. - /// - /// Channel to use. - /// Data to send. - public abstract void SendToServer(byte channelId, ArraySegment segment); - /// - /// Sends to a client. - /// - /// Channel to use. - /// Data to send. - /// ConnectionId to send to. When sending to clients can be used to specify which connection to send to. - public abstract void SendToClient(byte channelId, ArraySegment segment, int connectionId); - #endregion - - #region Receiving - /// - /// Called when the client receives data. - /// - public abstract event Action OnClientReceivedData; - /// - /// Handles a ClientReceivedDataArgs. - /// - /// Data being handled. - public abstract void HandleClientReceivedDataArgs(ClientReceivedDataArgs receivedDataArgs); - /// - /// Called when the server receives data. - /// - public abstract event Action OnServerReceivedData; - /// - /// Handles a ServerReceivedDataArgs. - /// - /// Data being handled. - public abstract void HandleServerReceivedDataArgs(ServerReceivedDataArgs receivedDataArgs); - #endregion - - #region Iterating. - /// - /// Processes data received by the socket. - /// - /// True to process data received on the server. - public abstract void IterateIncoming(bool server); - /// - /// Processes data to be sent by the socket. - /// - /// True to process data received on the server. - public abstract void IterateOutgoing(bool server); - #endregion - - #region Configuration. - /// - /// Returns if the transport is only run locally, offline. - /// While true several security checks are disabled. - /// - /// - public virtual bool IsLocalTransport(int connectionid) => false; - /// - /// Gets how long in seconds until either the server or client socket must go without data before being timed out. - /// - /// True to get the timeout for the server socket, false for the client socket. - /// - public virtual float GetTimeout(bool asServer) => -1f; - /// - /// Sets how long in seconds until either the server or client socket must go without data before being timed out. - /// - /// True to set the timeout for the server socket, false for the client socket. - public virtual void SetTimeout(float value, bool asServer) { } - /// - /// Returns the maximum number of clients allowed to connect to the server. If the transport does not support this method the value -1 is returned. - /// - /// Maximum clients transport allows. - public virtual int GetMaximumClients() - { - string message = $"The current transport does not support this feature."; - if (NetworkManager == null) - NetworkManager.StaticLogWarning(message); - else - NetworkManager.LogWarning(message); - - return -1; - } - /// - /// Sets the maximum number of clients allowed to connect to the server. If applied at runtime and clients exceed this value existing clients will stay connected but new clients may not connect. - /// - /// Maximum clients to allow. - public virtual void SetMaximumClients(int value) - { - string message = $"The current transport does not support this feature."; - if (NetworkManager == null) - NetworkManager.StaticLogWarning(message); - else - NetworkManager.LogWarning(message); - } - /// - /// Sets which address the client will connect to. - /// - /// Address client will connect to. - public virtual void SetClientAddress(string address) { } - /// - /// Returns which address the client will connect to. - /// - public virtual string GetClientAddress() => string.Empty; - /// - /// Sets which address the server will bind to. - /// - /// Address server will bind to. - /// Address type to set. - public virtual void SetServerBindAddress(string address, IPAddressType addressType) { } - /// - /// Gets which address the server will bind to. - /// - /// Address type to return. - public virtual string GetServerBindAddress(IPAddressType addressType) => string.Empty; - /// - /// Sets which port to use. - /// - /// Port to use. - public virtual void SetPort(ushort port) { } - /// - /// Gets which port to use. - /// - public virtual ushort GetPort() => 0; - #endregion - - #region Start and stop. - /// - /// Starts the local server or client using configured settings. - /// - /// True to start server. - public abstract bool StartConnection(bool server); - /// - /// Stops the local server or client. - /// - /// True to stop server. - public abstract bool StopConnection(bool server); - /// - /// Stops a remote client from the server, disconnecting the client. - /// - /// ConnectionId of the client to disconnect. - /// True to abrutly stop the client socket. The technique used to accomplish immediate disconnects may vary depending on the transport. - /// When not using immediate disconnects it's recommended to perform disconnects using the ServerManager rather than accessing the transport directly. - /// - public abstract bool StopConnection(int connectionId, bool immediately); - /// - /// Stops both client and server. - /// - public abstract void Shutdown(); - #endregion - - #region Channels. - /// - /// Gets the MTU for a channel. - /// - /// Channel to get MTU for. - /// MTU of channel. - public abstract int GetMTU(byte channel); - #endregion - - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transport.cs.meta b/Assets/FishNet/Runtime/Transporting/Transport.cs.meta deleted file mode 100644 index 4f1ee6f..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transport.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 78aba14618b37ea4bb067fa95ede84e0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports.meta b/Assets/FishNet/Runtime/Transporting/Transports.meta deleted file mode 100644 index a0f770e..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: bb8b443596223e84aaca2634238adda3 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Multipass.meta b/Assets/FishNet/Runtime/Transporting/Transports/Multipass.meta deleted file mode 100644 index 421c7c8..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Multipass.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 7f35b43a13fceaa40ac25cef58d8e53b -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Multipass/CHANGELOG.txt b/Assets/FishNet/Runtime/Transporting/Transports/Multipass/CHANGELOG.txt deleted file mode 100644 index 4f3eea1..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Multipass/CHANGELOG.txt +++ /dev/null @@ -1,2 +0,0 @@ -1.0.0 - - Initial release. \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Multipass/CHANGELOG.txt.meta b/Assets/FishNet/Runtime/Transporting/Transports/Multipass/CHANGELOG.txt.meta deleted file mode 100644 index 8a99e4e..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Multipass/CHANGELOG.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 9b339dd67a0ce7f458236a3ad1d97322 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Multipass/Multipass.cs b/Assets/FishNet/Runtime/Transporting/Transports/Multipass/Multipass.cs deleted file mode 100644 index 1db39f2..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Multipass/Multipass.cs +++ /dev/null @@ -1,946 +0,0 @@ -using FishNet.Managing; -using FishNet.Utility.Extension; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Transporting.Multipass -{ - [AddComponentMenu("FishNet/Transport/Multipass")] - public class Multipass : Transport - { - #region Types. - public struct TransportIdData - { - public int TransportId; - public int TransportIndex; - - public TransportIdData(int transportId, int transportIndex) - { - TransportId = transportId; - TransportIndex = transportIndex; - } - } - #endregion - - #region Public. - /// - /// While true server actions such as starting or stopping the server will run on all transport. - /// - [Tooltip("While true server actions such as starting or stopping the server will run on all transport.")] - public bool GlobalServerActions = true; - /// - /// - /// - private Transport _clientTransport; - /// - /// Transport the client is using. - /// Use SetClientTransport to assign this value. - /// - [HideInInspector] - public Transport ClientTransport - { - get - { - //If not yet set. - if (_clientTransport == null) - { - //If there are transports to set from. - if (_transports.Count != 0) - _clientTransport = _transports[0]; - - /* Give feedback to developer that transport was not set - * before accessing this. Transport should always be set - * manually rather than assuming the default client - * transport. */ - if (_clientTransport == null) - base.NetworkManager.LogError($"ClientTransport in Multipass could not be set to the first transport. This can occur if no trnasports are specified or if the first entry is null."); - else - base.NetworkManager.LogError($"ClientTransport in Multipass is being automatically set to {_clientTransport.GetType()}. For production use SetClientTransport before attempting to access the ClientTransport."); - } - - return _clientTransport; - } - - private set => _clientTransport = value; - } - #endregion - - #region Serialized. - /// - /// - /// - [Tooltip("Transports to use.")] - [SerializeField] - private List _transports = new List(); - /// - /// Transports to use. - /// - public IList Transports => _transports; - #endregion - - #region Private. - /// - /// Key is the transport connectionid, Value is the TransportIdData. - /// - private Dictionary _multipassToTransport = new Dictionary(); - /// - /// Key is the Multipass connectionId, Value is the transport connectionId. - /// - private List> _transportToMultipass = new List>(); - /// - /// Ids available to new connections. - /// - private Queue _availableIds = new Queue(); - #endregion - - #region Const. - /// - /// Id to use for client when acting as host. - /// - internal const int CLIENT_HOST_ID = short.MaxValue; - #endregion - - public override void Initialize(NetworkManager networkManager, int transportIndex) - { - base.Initialize(networkManager, transportIndex); - - //Remove any null transports and warn. - for (int i = 0; i < _transports.Count; i++) - { - if (_transports[i] == null) - { - base.NetworkManager.LogWarning($"Transports contains a null entry on index {i}."); - _transports.RemoveAt(i); - i--; - } - } - - //No transports to use. - if (_transports.Count == 0) - { - base.NetworkManager.LogError($"No transports are set within Multipass."); - return; - } - - //Create transportsToMultipass. - for (int i = 0; i < _transports.Count; i++) - { - Dictionary dict = new Dictionary(); - _transportToMultipass.Add(dict); - } - - //Initialize each transport. - for (int i = 0; i < _transports.Count; i++) - { - _transports[i].Initialize(networkManager, i); - _transports[i].OnClientConnectionState += Multipass_OnClientConnectionState; - _transports[i].OnServerConnectionState += Multipass_OnServerConnectionState; - _transports[i].OnRemoteConnectionState += Multipass_OnRemoteConnectionState; - _transports[i].OnClientReceivedData += Multipass_OnClientReceivedData; - _transports[i].OnServerReceivedData += Multipass_OnServerReceivedData; - } - } - - private void OnDestroy() - { - //Initialize each transport. - foreach (Transport t in _transports) - t.Shutdown(); - } - - - #region ClientIds. - /// - /// Clears ClientIds when appropriate. - /// - private void TryResetClientIds(bool force) - { - //Can only clear when every transport server isnt connected. - if (!force) - { - foreach (Transport t in _transports) - { - //Cannot clear if a server is running still. - if (t.GetConnectionState(true) == LocalConnectionState.Started) - return; - } - } - - _multipassToTransport.Clear(); - foreach (Dictionary item in _transportToMultipass) - item.Clear(); - CreateAvailableIds(); - } - - /// - /// Gets the Multipass connectionId using a transport connectionid. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool GetMultipassId(int transportIndex, int transportId, out int multipassId) - { - Dictionary dict = _transportToMultipass[transportIndex]; - if (!dict.TryGetValueIL2CPP(transportId, out multipassId)) - { - multipassId = -1; - base.NetworkManager.LogError($"Multipass connectionId could not be found for transportIndex {transportIndex}, transportId of {transportId}."); - - return false; - } - - return true; - } - - /// - /// Gets the TransportIdData using a Multipass connectionId. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool GetTransportIdData(int multipassId, out TransportIdData data) - { - if (!_multipassToTransport.TryGetValueIL2CPP(multipassId, out data)) - { - //Fall through. - base.NetworkManager.LogError($"TransportIdData could not be found for Multipass connectionId of {multipassId}."); - return false; - } - - return true; - } - #endregion - - #region ConnectionStates. - /// - /// Gets the IP address of a remote connectionId. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override string GetConnectionAddress(int connectionId) - { - TransportIdData data; - if (!GetTransportIdData(connectionId, out data)) - return string.Empty; - - return _transports[data.TransportIndex].GetConnectionAddress(data.TransportId); - } - /// - /// Called when a connection state changes for the local client. - /// - public override event Action OnClientConnectionState; - /// - /// Called when a connection state changes for the local server. - /// - public override event Action OnServerConnectionState; - /// - /// Called when a connection state changes for a remote client. - /// - public override event Action OnRemoteConnectionState; - /// - /// Gets the current local ConnectionState of the first transport. - /// - /// True if getting ConnectionState for the server. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override LocalConnectionState GetConnectionState(bool server) - { - if (server) - { - base.NetworkManager.LogError($"This method is not supported for server. Use GetConnectionState(server, transportIndex) instead."); - return LocalConnectionState.Stopped; - } - - if (IsClientTransportSetWithError("GetConnectionState")) - return GetConnectionState(server, ClientTransport.Index); - else - return LocalConnectionState.Stopped; - } - /// - /// Gets the current local ConnectionState of the transport on index. - /// - /// True if getting ConnectionState for the server. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public LocalConnectionState GetConnectionState(bool server, int index) - { - if (!IndexInRange(index, true)) - return LocalConnectionState.Stopped; - - return _transports[index].GetConnectionState(server); - } - /// - /// Gets the current ConnectionState of a remote client on the server. - /// - /// ConnectionId to get ConnectionState for. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override RemoteConnectionState GetConnectionState(int connectionId) - { - - TransportIdData data; - if (!GetTransportIdData(connectionId, out data)) - return RemoteConnectionState.Stopped; - - return _transports[data.TransportIndex].GetConnectionState(data.TransportId); - } - /// - /// Gets the current ConnectionState of a remote client on the server of the transport on index. - /// - /// ConnectionId to get ConnectionState for. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RemoteConnectionState GetConnectionState(int connectionId, int index) - { - if (!IndexInRange(index, true)) - return RemoteConnectionState.Stopped; - - return _transports[index].GetConnectionState(connectionId); - } - - /// - /// Handles a ConnectionStateArgs for the local client. - /// - /// - private void Multipass_OnClientConnectionState(ClientConnectionStateArgs connectionStateArgs) - { - OnClientConnectionState?.Invoke(connectionStateArgs); - } - /// - /// Handles a ConnectionStateArgs for the local server. - /// - /// - private void Multipass_OnServerConnectionState(ServerConnectionStateArgs connectionStateArgs) - { - OnServerConnectionState?.Invoke(connectionStateArgs); - TryResetClientIds(false); - } - /// - /// Handles a ConnectionStateArgs for a remote client. - /// - /// - private void Multipass_OnRemoteConnectionState(RemoteConnectionStateArgs connectionStateArgs) - { - /* When starting Multipass needs to get a new - * connectionId to be used within FN. This is the 'ClientId' - * that is passed around for ownership, rpcs, ect. - * - * The new connectionId will be linked with the connectionId - * from the transport, named transportConnectionid. - * - * When data arrives the transportStateId is used as a key - * in fromClientIds, where Multipass Id is returned. The argument values - * are then overwritten with the MultipassId. - * - * When data is being sent the same process is performed but reversed. - * The connectionId is looked up in toClientIds, where the transportConnectionId - * is output. Then as before the argument values are overwritten with the - * transportConnectionId. */ - - int transportIndex = connectionStateArgs.TransportIndex; - int transportId = connectionStateArgs.ConnectionId; - int multipassId; - Dictionary transportToMultipass = _transportToMultipass[transportIndex]; - - //Started. - if (connectionStateArgs.ConnectionState == RemoteConnectionState.Started) - { - multipassId = _availableIds.Dequeue(); - transportToMultipass[transportId] = multipassId; - _multipassToTransport[multipassId] = new TransportIdData(transportId, transportIndex); - } - //Stopped. - else - { - if (!GetMultipassId(transportIndex, transportId, out multipassId)) - return; - - _availableIds.Enqueue(multipassId); - transportToMultipass.Remove(transportId); - _multipassToTransport.Remove(multipassId); - -#if UNITY_EDITOR || DEVELOPMENT_BUILD - //Remove packets held for connection from latency simulator. - base.NetworkManager.TransportManager.LatencySimulator.RemovePendingForConnection(multipassId); -#endif - } - - connectionStateArgs.ConnectionId = multipassId; - OnRemoteConnectionState?.Invoke(connectionStateArgs); - } - #endregion - - #region Iterating. - /// - /// Processes data received by the socket. - /// - /// True to process data received on the server. - public override void IterateIncoming(bool server) - { - foreach (Transport t in _transports) - t.IterateIncoming(server); - } - - /// - /// Processes data to be sent by the socket. - /// - /// True to process data received on the server. - public override void IterateOutgoing(bool server) - { - foreach (Transport t in _transports) - t.IterateOutgoing(server); - } - #endregion - - #region ReceivedData. - /// - /// Called when client receives data. - /// - public override event Action OnClientReceivedData; - /// - /// Handles a ClientReceivedDataArgs. - /// - /// - private void Multipass_OnClientReceivedData(ClientReceivedDataArgs receivedDataArgs) - { - OnClientReceivedData?.Invoke(receivedDataArgs); - } - /// - /// Called when server receives data. - /// - public override event Action OnServerReceivedData; - /// - /// Handles a ClientReceivedDataArgs. - /// - /// - private void Multipass_OnServerReceivedData(ServerReceivedDataArgs receivedDataArgs) - { - int multipassId; - if (!GetMultipassId(receivedDataArgs.TransportIndex, receivedDataArgs.ConnectionId, out multipassId)) - return; - - receivedDataArgs.ConnectionId = multipassId; - OnServerReceivedData?.Invoke(receivedDataArgs); - } - #endregion - - #region Sending. - /// - /// Sends to the server on ClientTransport. - /// - /// Channel to use. - /// /// Data to send. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void SendToServer(byte channelId, ArraySegment segment) - { - if (ClientTransport != null) - ClientTransport.SendToServer(channelId, segment); - } - /// - /// Sends data to a client. - /// - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void SendToClient(byte channelId, ArraySegment segment, int connectionId) - { - TransportIdData data; - if (GetTransportIdData(connectionId, out data)) - _transports[data.TransportIndex].SendToClient(channelId, segment, data.TransportId); - } - #endregion - - #region Configuration. - /// - /// Returns if GlobalServerActions is true and if not logs an error. - /// - /// - private bool UseGlobalServerActionsWithError(string methodText) - { - if (!GlobalServerActions) - { - base.NetworkManager.LogError($"Method {methodText} is not supported while GlobalServerActions is false."); - return false; - } - else - { - return true; - } - } - - /// - /// Returns if ClientTransport is set and if not logs an error. - /// - /// - /// - private bool IsClientTransportSetWithError(string methodText) - { - if (ClientTransport == null) - { - base.NetworkManager.LogError($"ClientTransport is not set. Use SetClientTransport before calling {methodText}."); - return false; - } - else - { - return true; - } - } - /// - /// Populates the availableIds collection. - /// - private void CreateAvailableIds() - { - _availableIds.Clear(); - for (int i = 0; i < short.MaxValue; i++) - _availableIds.Enqueue(i); - } - - /// - /// Sets the client transport to the first of type. - /// - /// - public void SetClientTransport() - { - int index = -1; - for (int i = 0; i < _transports.Count; i++) - { - if (_transports[i].GetType() == typeof(T)) - { - index = i; - break; - } - } - - SetClientTransport(index); - } - - /// - /// Sets the client transport to the first of type T. - /// - /// - public void SetClientTransport(Type type) - { - int index = -1; - for (int i = 0; i < _transports.Count; i++) - { - if (_transports[i].GetType() == type) - { - index = i; - break; - } - } - - SetClientTransport(index); - } - /// - /// Sets the client transport to the matching reference of transport. - /// - /// - public void SetClientTransport(Transport transport) - { - int index = -1; - for (int i = 0; i < _transports.Count; i++) - { - if (_transports[i] == transport) - { - index = i; - break; - } - } - - SetClientTransport(index); - } - /// - /// Sets the client transport to the transport on index. - /// - /// - public void SetClientTransport(int index) - { - if (!IndexInRange(index, true)) - return; - - ClientTransport = _transports[index]; - } - /// - /// Gets the Transport on index. - /// - /// - /// - public Transport GetTransport(int index) - { - if (!IndexInRange(index, true)) - return null; - - return _transports[index]; - } - /// - /// Gets the Transport on of type T. - /// - /// - /// - public T GetTransport() - { - foreach (Transport t in _transports) - { - if (t.GetType() == typeof(T)) - return (T)(object)t; - } - - return default(T); - } - /// - /// Returns if the transport for connectionId is a local transport. - /// While true several security checks are disabled. - /// - public override bool IsLocalTransport(int connectionid) - { - //If able to get transport data return value from transport. - if (GetTransportIdData(connectionid, out TransportIdData data)) - return _transports[data.TransportIndex].IsLocalTransport(data.TransportId); - //Otherwise return false forcing checks. - else - return false; - } - - /// - /// Returns the maximum number of clients allowed to connect to the server. If the transport does not support this method the value -1 is returned. - /// The first transport is used. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override int GetMaximumClients() - { - base.NetworkManager.LogError($"This method is not supported. Use GetMaximumClients(transportIndex) instead."); - - return -1; - } - /// - /// Returns the maximum number of clients allowed to connect to the server. If the transport does not support this method the value -1 is returned. - /// The first transport is used. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetMaximumClients(int transportIndex) - { - if (!IndexInRange(transportIndex, true)) - return -1; - - return _transports[transportIndex].GetMaximumClients(); - } - /// - /// Sets maximum number of clients allowed to connect to the server. If applied at runtime and clients exceed this value existing clients will stay connected but new clients may not connect. - /// This sets the value to the transport on the first index. - /// - /// - public override void SetMaximumClients(int value) - { - base.NetworkManager.LogError($"This method is not supported. Use SetMaximumClients(value, transportIndex) instead."); - } - /// - /// Sets maximum number of clients allowed to connect to the server. If applied at runtime and clients exceed this value existing clients will stay connected but new clients may not connect. - /// This sets the value to the transport on index. - /// - /// - public void SetMaximumClients(int value, int transportIndex) - { - if (!IndexInRange(transportIndex, true)) - return; - - _transports[transportIndex].SetMaximumClients(value); - } - /// - /// Sets which address the client will connect to. - /// This will set the address for every transport. - /// - /// - public override void SetClientAddress(string address) - { - foreach (Transport t in _transports) - t.SetClientAddress(address); - } - public override void SetServerBindAddress(string address, IPAddressType addressType) - { - base.NetworkManager.LogError($"This method is not supported. Use SetServerBindAddress(address, transportIndex) instead."); - } - /// Sets which address the server will bind to. - /// This is called on the transport of index. - /// - /// - public void SetServerBindAddress(string address, IPAddressType addressType, int index) - { - if (!IndexInRange(index, true)) - return; - - _transports[index].SetServerBindAddress(address, addressType); - } - /// - /// Sets which port to use on the first transport. - /// - public override void SetPort(ushort port) - { - base.NetworkManager.LogError($"This method is not supported. Use SetPort(port, transportIndex) instead."); - } - /// - /// Sets which port to use on transport of index. - /// - public void SetPort(ushort port, int index) - { - if (!IndexInRange(index, true)) - return; - - _transports[index].SetPort(port); - } - #endregion - - #region Start and stop. - /// - /// Starts the local server or client using configured settings on the first transport. - /// - /// True to start server. - public override bool StartConnection(bool server) - { - //Server. - if (server) - { - if (!UseGlobalServerActionsWithError("StartConnection")) - return false; - - bool success = true; - for (int i = 0; i < _transports.Count; i++) - { - if (!StartConnection(true, i)) - success = false; - } - - return success; - } - //Client. - else - { - if (IsClientTransportSetWithError("StartConnection")) - return StartConnection(false, ClientTransport.Index); - else - return false; - } - } - - /// - /// Starts the local server or client using configured settings on transport of index. - /// - /// True to start server. - public bool StartConnection(bool server, int index) - { - if (server) - { - return StartServer(index); - } - else - { - if (IsClientTransportSetWithError("StartConnection")) - return StartClient(); - else - return false; - } - } - - - /// - /// Stops the local server or client on the first transport. - /// - /// True to stop server. - public override bool StopConnection(bool server) - { - //Server - if (server) - { - if (!UseGlobalServerActionsWithError("StopConnection")) - return false; - - bool success = true; - for (int i = 0; i < _transports.Count; i++) - { - if (!StopConnection(true, i)) - success = false; - } - - return success; - } - //Client. - else - { - if (IsClientTransportSetWithError("StopConnection")) - return StopConnection(false, ClientTransport.Index); - else - return false; - } - } - /// - /// Stops the local server or client on transport of index. - /// - /// True to stop server. - public bool StopConnection(bool server, int index) - { - if (server) - { - return StopServer(index); - } - else - { - if (IsClientTransportSetWithError("StopConnection")) - return StopClient(); - else - return false; - } - } - - /// - /// Stops a remote client from the server, disconnecting the client. - /// - /// ConnectionId of the client to disconnect. - /// True to abrutly stp the client socket without waiting socket thread. - public override bool StopConnection(int connectionId, bool immediately) - { - return StopClient(connectionId, immediately); - } - - /// - /// Stops the server connection on transportIndex. - /// - /// True to send a disconnect message to connections before stopping them. - /// Index of transport to stop on. - public bool StopServerConnection(bool sendDisconnectMessage, int transportIndex) - { - if (sendDisconnectMessage) - { - //Get connectionIds as ServerManager knows them. - int[] multipassIds = _transportToMultipass[transportIndex].Keys.ToArray(); - //Tell serve manager to write disconnect for those ids. - base.NetworkManager.ServerManager.SendDisconnectMessages(multipassIds); - //Iterate outgoing on transport which is being stopped. - _transports[transportIndex].IterateOutgoing(true); - } - - return StopConnection(true, transportIndex); - } - - /// - /// Stops both client and server on all transports. - /// - public override void Shutdown() - { - foreach (Transport t in _transports) - { - //Stops client then server connections. - t.StopConnection(false); - t.StopConnection(true); - } - } - - #region Privates. - /// - /// Starts server of transport on index. - /// - /// True if there were no blocks. A true response does not promise a socket will or has connected. - private bool StartServer(int index) - { - if (!IndexInRange(index, true)) - return false; - - return _transports[index].StartConnection(true); - } - - /// - /// Stops server of transport on index. - /// - private bool StopServer(int index) - { - if (!IndexInRange(index, true)) - return false; - - return _transports[index].StopConnection(true); - } - - /// - /// Starts the client on ClientTransport. - /// - /// - /// True if there were no blocks. A true response does not promise a socket will or has connected. - private bool StartClient() - { - return ClientTransport.StartConnection(false); - } - - /// - /// Stops the client on ClientTransport. - /// - private bool StopClient() - { - return ClientTransport.StopConnection(false); - } - - /// - /// Stops a remote client on the server. - /// - /// - /// True to abrutly stp the client socket without waiting socket thread. - private bool StopClient(int connectionId, bool immediately) - { - TransportIdData data; - if (!GetTransportIdData(connectionId, out data)) - return false; - - return _transports[data.TransportIndex].StopConnection(data.TransportId, immediately); - } - #endregion - #endregion - - #region Channels. - /// - /// Gets the MTU for a channel on the first transport. This should take header size into consideration. - /// For example, if MTU is 1200 and a packet header for this channel is 10 in size, this method should return 1190. - /// - /// - /// - public override int GetMTU(byte channel) - { - return GetMTU(channel, 0); - } - /// - /// Gets the MTU for a channel of transport on index. This should take header size into consideration. - /// For example, if MTU is 1200 and a packet header for this channel is 10 in size, this method should return 1190. - /// - /// - /// - public int GetMTU(byte channel, int index) - { - if (!IndexInRange(index, true)) - return -1; - - return _transports[index].GetMTU(channel); - } - - #endregion - - #region Misc. - /// - /// Returns if an index is within range of the Transports collection. - /// - private bool IndexInRange(int index, bool error) - { - if (index >= _transports.Count || index < 0) - { - if (error) - base.NetworkManager.LogError($"Index of {index} is out of Transports range."); - return false; - } - else - { - return true; - } - } - - //perf change events to direct calls in transports. - public override void HandleServerConnectionState(ServerConnectionStateArgs connectionStateArgs) { } - public override void HandleRemoteConnectionState(RemoteConnectionStateArgs connectionStateArgs) { } - public override void HandleClientReceivedDataArgs(ClientReceivedDataArgs receivedDataArgs) { } - public override void HandleServerReceivedDataArgs(ServerReceivedDataArgs receivedDataArgs) { } - public override void HandleClientConnectionState(ClientConnectionStateArgs connectionStateArgs) { } - #endregion - - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Multipass/Multipass.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Multipass/Multipass.cs.meta deleted file mode 100644 index f58b9fb..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Multipass/Multipass.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 314b449d3505bd24487ba69b61c2fda5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Multipass/VERSION.txt b/Assets/FishNet/Runtime/Transporting/Transports/Multipass/VERSION.txt deleted file mode 100644 index afaf360..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Multipass/VERSION.txt +++ /dev/null @@ -1 +0,0 @@ -1.0.0 \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Multipass/VERSION.txt.meta b/Assets/FishNet/Runtime/Transporting/Transports/Multipass/VERSION.txt.meta deleted file mode 100644 index 7333afa..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Multipass/VERSION.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: e4f9d944e2ca8484587859cf4ec80b6c -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat.meta deleted file mode 100644 index eeec7bc..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 43760836a07366846a82fe7f158bd84e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core.meta deleted file mode 100644 index 1ad2510..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 4dad76b44081bb54b97e6da2e0e6f26d -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ClientSocket.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ClientSocket.cs deleted file mode 100644 index 7c945e9..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ClientSocket.cs +++ /dev/null @@ -1,307 +0,0 @@ -using FishNet.Managing.Logging; -using LiteNetLib; -using LiteNetLib.Layers; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; -using UnityEngine; - -namespace FishNet.Transporting.Tugboat.Client -{ - public class ClientSocket : CommonSocket - { - ~ClientSocket() - { - StopConnection(); - } - - #region Private. - #region Configuration. - /// - /// Address to bind server to. - /// - private string _address = string.Empty; - /// - /// Port used by server. - /// - private ushort _port; - /// - /// MTU sizes for each channel. - /// - private int _mtu; - #endregion - #region Queues. - /// - /// Changes to the sockets local connection state. - /// - private Queue _localConnectionStates = new Queue(); - /// - /// Inbound messages which need to be handled. - /// - private Queue _incoming = new Queue(); - /// - /// Outbound messages which need to be handled. - /// - private Queue _outgoing = new Queue(); - #endregion - /// - /// Client socket manager. - /// - private NetManager _client; - /// - /// How long in seconds until client times from server. - /// - private int _timeout; - /// - /// PacketLayer to use with LiteNetLib. - /// - private PacketLayerBase _packetLayer; - /// - /// Locks the NetManager to stop it. - /// - private readonly object _stopLock = new object(); - #endregion - - /// - /// Initializes this for use. - /// - /// - internal void Initialize(Transport t, int unreliableMTU, PacketLayerBase packetLayer) - { - base.Transport = t; - _mtu = unreliableMTU; - _packetLayer = packetLayer; - } - - /// - /// Updates the Timeout value as seconds. - /// - internal void UpdateTimeout(int timeout) - { - _timeout = timeout; - base.UpdateTimeout(_client, timeout); - } - - /// - /// Threaded operation to process client actions. - /// - private void ThreadedSocket() - { - EventBasedNetListener listener = new EventBasedNetListener(); - listener.NetworkReceiveEvent += Listener_NetworkReceiveEvent; - listener.PeerConnectedEvent += Listener_PeerConnectedEvent; - listener.PeerDisconnectedEvent += Listener_PeerDisconnectedEvent; - - _client = new NetManager(listener, _packetLayer); - _client.MtuOverride = (_mtu + NetConstants.FragmentedHeaderTotalSize); - - UpdateTimeout(_timeout); - - _localConnectionStates.Enqueue(LocalConnectionState.Starting); - _client.Start(); - _client.Connect(_address, _port, string.Empty); - } - - - /// - /// Stops the socket on a new thread. - /// - private void StopSocketOnThread() - { - if (_client == null) - return; - - Task t = Task.Run(() => - { - lock (_stopLock) - { - _client?.Stop(); - _client = null; - } - - //If not stopped yet also enqueue stop. - if (base.GetConnectionState() != LocalConnectionState.Stopped) - _localConnectionStates.Enqueue(LocalConnectionState.Stopped); - }); - } - - /// - /// Starts the client connection. - /// - /// - /// - /// - /// - internal bool StartConnection(string address, ushort port) - { - if (base.GetConnectionState() != LocalConnectionState.Stopped) - return false; - - base.SetConnectionState(LocalConnectionState.Starting, false); - - //Assign properties. - _port = port; - _address = address; - - ResetQueues(); - Task t = Task.Run(() => ThreadedSocket()); - - return true; - } - - - /// - /// Stops the local socket. - /// - internal bool StopConnection(DisconnectInfo? info = null) - { - if (base.GetConnectionState() == LocalConnectionState.Stopped || base.GetConnectionState() == LocalConnectionState.Stopping) - return false; - - if (info != null) - base.Transport.NetworkManager.Log($"Local client disconnect reason: {info.Value.Reason}."); - - base.SetConnectionState(LocalConnectionState.Stopping, false); - StopSocketOnThread(); - return true; - } - - /// - /// Resets queues. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ResetQueues() - { - _localConnectionStates.Clear(); - base.ClearPacketQueue(ref _incoming); - base.ClearPacketQueue(ref _outgoing); - } - - - /// - /// Called when disconnected from the server. - /// - private void Listener_PeerDisconnectedEvent(NetPeer peer, DisconnectInfo disconnectInfo) - { - StopConnection(disconnectInfo); - } - - /// - /// Called when connected to the server. - /// - private void Listener_PeerConnectedEvent(NetPeer peer) - { - _localConnectionStates.Enqueue(LocalConnectionState.Started); - } - - /// - /// Called when data is received from a peer. - /// - private void Listener_NetworkReceiveEvent(NetPeer fromPeer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod) - { - base.Listener_NetworkReceiveEvent(_incoming, fromPeer, reader, deliveryMethod, _mtu); - } - - /// - /// Dequeues and processes outgoing. - /// - private void DequeueOutgoing() - { - NetPeer peer = null; - if (_client != null) - peer = _client.FirstPeer; - //Server connection hasn't been made. - if (peer == null) - { - /* Only dequeue outgoing because other queues might have - * relevant information, such as the local connection queue. */ - base.ClearPacketQueue(ref _outgoing); - } - else - { - int count = _outgoing.Count; - for (int i = 0; i < count; i++) - { - Packet outgoing = _outgoing.Dequeue(); - - ArraySegment segment = outgoing.GetArraySegment(); - DeliveryMethod dm = (outgoing.Channel == (byte)Channel.Reliable) ? - DeliveryMethod.ReliableOrdered : DeliveryMethod.Unreliable; - - //If over the MTU. - if (outgoing.Channel == (byte)Channel.Unreliable && segment.Count > _mtu) - { - base.Transport.NetworkManager.LogWarning($"Client is sending of {segment.Count} length on the unreliable channel, while the MTU is only {_mtu}. The channel has been changed to reliable for this send."); - dm = DeliveryMethod.ReliableOrdered; - } - - peer.Send(segment.Array, segment.Offset, segment.Count, dm); - - outgoing.Dispose(); - } - } - } - - /// - /// Allows for Outgoing queue to be iterated. - /// - internal void IterateOutgoing() - { - DequeueOutgoing(); - } - - /// - /// Iterates the Incoming queue. - /// - internal void IterateIncoming() - { - _client?.PollEvents(); - - /* Run local connection states first so we can begin - * to read for data at the start of the frame, as that's - * where incoming is read. */ - while (_localConnectionStates.Count > 0) - base.SetConnectionState(_localConnectionStates.Dequeue(), false); - - //Not yet started, cannot continue. - LocalConnectionState localState = base.GetConnectionState(); - if (localState != LocalConnectionState.Started) - { - ResetQueues(); - //If stopped try to kill task. - if (localState == LocalConnectionState.Stopped) - { - StopSocketOnThread(); - return; - } - } - - /* Incoming. */ - while (_incoming.Count > 0) - { - Packet incoming = _incoming.Dequeue(); - ClientReceivedDataArgs dataArgs = new ClientReceivedDataArgs( - incoming.GetArraySegment(), - (Channel)incoming.Channel, base.Transport.Index); - base.Transport.HandleClientReceivedDataArgs(dataArgs); - //Dispose of packet. - incoming.Dispose(); - } - } - - /// - /// Sends a packet to the server. - /// - internal void SendToServer(byte channelId, ArraySegment segment) - { - //Not started, cannot send. - if (base.GetConnectionState() != LocalConnectionState.Started) - return; - - base.Send(ref _outgoing, channelId, segment, -1, _mtu); - } - - - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ClientSocket.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ClientSocket.cs.meta deleted file mode 100644 index 989bf71..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ClientSocket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7944de5e4da77594db036e276174ee60 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/CommonSocket.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/CommonSocket.cs deleted file mode 100644 index cdc77b4..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/CommonSocket.cs +++ /dev/null @@ -1,125 +0,0 @@ -using FishNet.Utility.Performance; -using LiteNetLib; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; - -namespace FishNet.Transporting.Tugboat -{ - - public abstract class CommonSocket - { - - #region Public. - /// - /// Current ConnectionState. - /// - private LocalConnectionState _connectionState = LocalConnectionState.Stopped; - /// - /// Returns the current ConnectionState. - /// - /// - internal LocalConnectionState GetConnectionState() - { - return _connectionState; - } - /// - /// Sets a new connection state. - /// - /// - protected void SetConnectionState(LocalConnectionState connectionState, bool asServer) - { - //If state hasn't changed. - if (connectionState == _connectionState) - return; - - _connectionState = connectionState; - if (asServer) - Transport.HandleServerConnectionState(new ServerConnectionStateArgs(connectionState, Transport.Index)); - else - Transport.HandleClientConnectionState(new ClientConnectionStateArgs(connectionState, Transport.Index)); - } - #endregion - - #region Protected. - /// - /// Transport controlling this socket. - /// - protected Transport Transport = null; - #endregion - - - /// - /// Sends data to connectionId. - /// - internal void Send(ref Queue queue, byte channelId, ArraySegment segment, int connectionId, int mtu) - { - if (GetConnectionState() != LocalConnectionState.Started) - return; - - //ConnectionId isn't used from client to server. - Packet outgoing = new Packet(connectionId, segment, channelId, mtu); - queue.Enqueue(outgoing); - } - - /// - /// Updates the timeout for NetManager. - /// - protected void UpdateTimeout(NetManager netManager, int timeout) - { - if (netManager == null) - return; - - timeout = (timeout == 0) ? int.MaxValue : Math.Min(int.MaxValue, (timeout * 1000)); - netManager.DisconnectTimeout = timeout; - } - /// - /// Clears a queue using Packet type. - /// - /// - internal void ClearPacketQueue(ref ConcurrentQueue queue) - { - while (queue.TryDequeue(out Packet p)) - p.Dispose(); - } - - /// - /// Clears a queue using Packet type. - /// - /// - internal void ClearPacketQueue(ref Queue queue) - { - int count = queue.Count; - for (int i = 0; i < count; i++) - { - Packet p = queue.Dequeue(); - p.Dispose(); - } - } - - /// - /// Called when data is received. - /// - internal virtual void Listener_NetworkReceiveEvent(Queue queue, NetPeer fromPeer, NetPacketReader reader, DeliveryMethod deliveryMethod, int mtu) - { - //Set buffer. - int dataLen = reader.AvailableBytes; - //Prefer to max out returned array to mtu to reduce chance of resizing. - int arraySize = Math.Max(dataLen, mtu); - byte[] data = ByteArrayPool.Retrieve(arraySize); - reader.GetBytes(data, dataLen); - //Id. - int id = fromPeer.Id; - //Channel. - byte channel = (deliveryMethod == DeliveryMethod.Unreliable) ? - (byte)Channel.Unreliable : (byte)Channel.Reliable; - //Add to packets. - Packet packet = new Packet(id, data, dataLen, channel); - queue.Enqueue(packet); - //Recycle reader. - reader.Recycle(); - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/CommonSocket.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/CommonSocket.cs.meta deleted file mode 100644 index 640e1fa..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/CommonSocket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 329169cdf51866c43a8c42e8aeb291fb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ServerSocket.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ServerSocket.cs deleted file mode 100644 index 66adaff..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ServerSocket.cs +++ /dev/null @@ -1,523 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing.Logging; -using LiteNetLib; -using LiteNetLib.Layers; -using System; -using System.Collections.Generic; -using System.Net; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; -using UnityEngine; - -namespace FishNet.Transporting.Tugboat.Server -{ - public class ServerSocket : CommonSocket - { - - #region Public. - /// - /// Gets the current ConnectionState of a remote client on the server. - /// - /// ConnectionId to get ConnectionState for. - internal RemoteConnectionState GetConnectionState(int connectionId) - { - NetPeer peer = GetNetPeer(connectionId, false); - if (peer == null || peer.ConnectionState != ConnectionState.Connected) - return RemoteConnectionState.Stopped; - else - return RemoteConnectionState.Started; - } - #endregion - - #region Private. - #region Configuration. - /// - /// Port used by server. - /// - private ushort _port; - /// - /// Maximum number of allowed clients. - /// - private int _maximumClients; - /// - /// MTU size per packet. - /// - private int _mtu; - #endregion - #region Queues. - /// - /// Changes to the sockets local connection state. - /// - private Queue _localConnectionStates = new Queue(); - /// - /// Inbound messages which need to be handled. - /// - private Queue _incoming = new Queue(); - /// - /// Outbound messages which need to be handled. - /// - private Queue _outgoing = new Queue(); - /// - /// ConnectionEvents which need to be handled. - /// - private Queue _remoteConnectionEvents = new Queue(); - #endregion - /// - /// Key required to connect. - /// - private string _key = string.Empty; - /// - /// How long in seconds until client times from server. - /// - private int _timeout; - /// - /// Server socket manager. - /// - private NetManager _server; - /// - /// IPv4 address to bind server to. - /// - private string _ipv4BindAddress; - /// - /// IPv6 address to bind server to. - /// - private string _ipv6BindAddress; - /// - /// PacketLayer to use with LiteNetLib. - /// - private PacketLayerBase _packetLayer; - /// - /// Locks the NetManager to stop it. - /// - private readonly object _stopLock = new object(); - #endregion - - ~ServerSocket() - { - StopConnection(); - } - - /// - /// Initializes this for use. - /// - /// - internal void Initialize(Transport t, int unreliableMTU, PacketLayerBase packetLayer) - { - base.Transport = t; - _mtu = unreliableMTU; - _packetLayer = packetLayer; - } - - /// - /// Updates the Timeout value as seconds. - /// - internal void UpdateTimeout(int timeout) - { - _timeout = timeout; - base.UpdateTimeout(_server, timeout); - } - - - /// - /// Threaded operation to process server actions. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ThreadedSocket() - { - EventBasedNetListener listener = new EventBasedNetListener(); - listener.ConnectionRequestEvent += Listener_ConnectionRequestEvent; - listener.PeerConnectedEvent += Listener_PeerConnectedEvent; - listener.NetworkReceiveEvent += Listener_NetworkReceiveEvent; - listener.PeerDisconnectedEvent += Listener_PeerDisconnectedEvent; - - _server = new NetManager(listener, _packetLayer); - _server.MtuOverride = (_mtu + NetConstants.FragmentedHeaderTotalSize); - - UpdateTimeout(_timeout); - - //Set bind addresses. - IPAddress ipv4; - IPAddress ipv6; - - //Set ipv4 - if (!string.IsNullOrEmpty(_ipv4BindAddress)) - { - if (!IPAddress.TryParse(_ipv4BindAddress, out ipv4)) - ipv4 = null; - - //If unable to parse try to get address another way. - if (ipv4 == null) - { - IPHostEntry hostEntry = Dns.GetHostEntry(_ipv4BindAddress); - if (hostEntry.AddressList.Length > 0) - { - ipv4 = hostEntry.AddressList[0]; - base.Transport.NetworkManager.Log($"IPv4 could not parse correctly but was resolved to {ipv4.ToString()}"); - } - } - } - else - { - IPAddress.TryParse("0.0.0.0", out ipv4); - } - - //Set ipv6. - if (!string.IsNullOrEmpty(_ipv6BindAddress)) - { - if (!IPAddress.TryParse(_ipv6BindAddress, out ipv6)) - ipv6 = null; - } - else - { - IPAddress.TryParse("0:0:0:0:0:0:0:0", out ipv6); - } - - - - string ipv4FailText = (ipv4 == null) ? $"IPv4 address {_ipv4BindAddress} failed to parse. " : string.Empty; - string ipv6FailText = (ipv6 == null) ? $"IPv6 address {_ipv6BindAddress} failed to parse. " : string.Empty; - if (ipv4FailText != string.Empty || ipv6FailText != string.Empty) - { - base.Transport.NetworkManager.Log($"{ipv4FailText}{ipv6FailText}Clear the bind address field to use any bind address."); - StopConnection(); - return; - } - - bool startResult = _server.Start(ipv4, ipv6, _port); - //If started succcessfully. - if (startResult) - { - _localConnectionStates.Enqueue(LocalConnectionState.Started); - } - //Failed to start. - else - { - base.Transport.NetworkManager.LogError($"Server failed to start. This usually occurs when the specified port is unavailable, be it closed or already in use."); - StopConnection(); - } - } - - /// - /// Stops the socket on a new thread. - /// - private void StopSocketOnThread() - { - if (_server == null) - return; - - Task t = Task.Run(() => - { - lock (_stopLock) - { - _server?.Stop(); - _server = null; - } - - //If not stopped yet also enqueue stop. - if (base.GetConnectionState() != LocalConnectionState.Stopped) - _localConnectionStates.Enqueue(LocalConnectionState.Stopped); - }); - } - - /// - /// Gets the address of a remote connection Id. - /// - /// - /// Returns string.empty if Id is not found. - internal string GetConnectionAddress(int connectionId) - { - NetPeer peer = GetNetPeer(connectionId, false); - return peer.EndPoint.Address.ToString(); - } - - /// - /// Returns a NetPeer for connectionId. - /// - /// - /// - private NetPeer GetNetPeer(int connectionId, bool connectedOnly) - { - if (_server != null) - { - NetPeer peer = _server.GetPeerById(connectionId); - if (connectedOnly && peer != null && peer.ConnectionState != ConnectionState.Connected) - peer = null; - - return peer; - } - else - { - return null; - } - } - - /// - /// Starts the server. - /// - internal bool StartConnection(ushort port, int maximumClients, string ipv4BindAddress, string ipv6BindAddress) - { - if (base.GetConnectionState() != LocalConnectionState.Stopped) - return false; - - base.SetConnectionState(LocalConnectionState.Starting, true); - - //Assign properties. - _port = port; - _maximumClients = maximumClients; - _ipv4BindAddress = ipv4BindAddress; - _ipv6BindAddress = ipv6BindAddress; - ResetQueues(); - - Task t = Task.Run(() => ThreadedSocket()); - - return true; - } - - /// - /// Stops the local socket. - /// - internal bool StopConnection() - { - if (_server == null || base.GetConnectionState() == LocalConnectionState.Stopped || base.GetConnectionState() == LocalConnectionState.Stopping) - return false; - - _localConnectionStates.Enqueue(LocalConnectionState.Stopping); - StopSocketOnThread(); - return true; - } - - /// - /// Stops a remote client disconnecting the client from the server. - /// - /// ConnectionId of the client to disconnect. - internal bool StopConnection(int connectionId) - { - //Server isn't running. - if (_server == null || base.GetConnectionState() != LocalConnectionState.Started) - return false; - - NetPeer peer = GetNetPeer(connectionId, false); - if (peer == null) - return false; - - try - { - peer.Disconnect(); - //Let LiteNetLib get the disconnect event which will enqueue a remote connection state. - //base.Transport.HandleRemoteConnectionState(new RemoteConnectionStateArgs(RemoteConnectionState.Stopped, connectionId, base.Transport.Index)); - } - catch - { - return false; - } - - return true; - } - - /// - /// Resets queues. - /// - private void ResetQueues() - { - _localConnectionStates.Clear(); - base.ClearPacketQueue(ref _incoming); - base.ClearPacketQueue(ref _outgoing); - _remoteConnectionEvents.Clear(); - } - - - /// - /// Called when a peer disconnects or times out. - /// - private void Listener_PeerDisconnectedEvent(NetPeer peer, DisconnectInfo disconnectInfo) - { - _remoteConnectionEvents.Enqueue(new RemoteConnectionEvent(false, peer.Id)); - } - - /// - /// Called when a peer completes connection. - /// - private void Listener_PeerConnectedEvent(NetPeer peer) - { - _remoteConnectionEvents.Enqueue(new RemoteConnectionEvent(true, peer.Id)); - } - - /// - /// Called when data is received from a peer. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void Listener_NetworkReceiveEvent(NetPeer fromPeer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod) - { - //If over the MTU. - if (reader.AvailableBytes > _mtu) - { - _remoteConnectionEvents.Enqueue(new RemoteConnectionEvent(false, fromPeer.Id)); - fromPeer.Disconnect(); - } - else - { - base.Listener_NetworkReceiveEvent(_incoming, fromPeer, reader, deliveryMethod, _mtu); - } - } - - - /// - /// Called when a remote connection request is made. - /// - private void Listener_ConnectionRequestEvent(ConnectionRequest request) - { - if (_server == null) - return; - - //At maximum peers. - if (_server.ConnectedPeersCount >= _maximumClients) - { - request.Reject(); - return; - } - - request.AcceptIfKey(_key); - } - - /// - /// Dequeues and processes outgoing. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DequeueOutgoing() - { - if (base.GetConnectionState() != LocalConnectionState.Started || _server == null) - { - //Not started, clear outgoing. - base.ClearPacketQueue(ref _outgoing); - } - else - { - int count = _outgoing.Count; - for (int i = 0; i < count; i++) - { - Packet outgoing = _outgoing.Dequeue(); - int connectionId = outgoing.ConnectionId; - - ArraySegment segment = outgoing.GetArraySegment(); - DeliveryMethod dm = (outgoing.Channel == (byte)Channel.Reliable) ? - DeliveryMethod.ReliableOrdered : DeliveryMethod.Unreliable; - - //If over the MTU. - if (outgoing.Channel == (byte)Channel.Unreliable && segment.Count > _mtu) - { - base.Transport.NetworkManager.LogWarning($"Server is sending of {segment.Count} length on the unreliable channel, while the MTU is only {_mtu}. The channel has been changed to reliable for this send."); - dm = DeliveryMethod.ReliableOrdered; - } - - //Send to all clients. - if (connectionId == NetworkConnection.UNSET_CLIENTID_VALUE) - { - _server.SendToAll(segment.Array, segment.Offset, segment.Count, dm); - } - //Send to one client. - else - { - NetPeer peer = GetNetPeer(connectionId, true); - //If peer is found. - if (peer != null) - peer.Send(segment.Array, segment.Offset, segment.Count, dm); - } - - outgoing.Dispose(); - } - } - } - - /// - /// Allows for Outgoing queue to be iterated. - /// - internal void IterateOutgoing() - { - DequeueOutgoing(); - } - - /// - /// Iterates the Incoming queue. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void IterateIncoming() - { - _server?.PollEvents(); - - /* Run local connection states first so we can begin - * to read for data at the start of the frame, as that's - * where incoming is read. */ - while (_localConnectionStates.Count > 0) - base.SetConnectionState(_localConnectionStates.Dequeue(), true); - - //Not yet started. - LocalConnectionState localState = base.GetConnectionState(); - if (localState != LocalConnectionState.Started) - { - ResetQueues(); - //If stopped try to kill task. - if (localState == LocalConnectionState.Stopped) - { - StopSocketOnThread(); - return; - } - } - - //Handle connection and disconnection events. - while (_remoteConnectionEvents.Count > 0) - { - RemoteConnectionEvent connectionEvent = _remoteConnectionEvents.Dequeue(); - RemoteConnectionState state = (connectionEvent.Connected) ? RemoteConnectionState.Started : RemoteConnectionState.Stopped; - base.Transport.HandleRemoteConnectionState(new RemoteConnectionStateArgs(state, connectionEvent.ConnectionId, base.Transport.Index)); - } - - //Handle packets. - while (_incoming.Count > 0) - { - Packet incoming = _incoming.Dequeue(); - //Make sure peer is still connected. - NetPeer peer = GetNetPeer(incoming.ConnectionId, true); - if (peer != null) - { - ServerReceivedDataArgs dataArgs = new ServerReceivedDataArgs( - incoming.GetArraySegment(), - (Channel)incoming.Channel, - incoming.ConnectionId, - base.Transport.Index); - - base.Transport.HandleServerReceivedDataArgs(dataArgs); - } - - incoming.Dispose(); - } - - } - - /// - /// Sends a packet to a single, or all clients. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void SendToClient(byte channelId, ArraySegment segment, int connectionId) - { - Send(ref _outgoing, channelId, segment, connectionId, _mtu); - } - - /// - /// Returns the maximum number of clients allowed to connect to the server. If the transport does not support this method the value -1 is returned. - /// - /// - internal int GetMaximumClients() - { - return _maximumClients; - } - - /// - /// Sets the MaximumClients value. - /// - /// - internal void SetMaximumClients(int value) - { - _maximumClients = value; - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ServerSocket.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ServerSocket.cs.meta deleted file mode 100644 index 9cb8afc..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/ServerSocket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5c6703e8024041e45ae92566123865ad -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/Supporting.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/Supporting.cs deleted file mode 100644 index af55ed3..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/Supporting.cs +++ /dev/null @@ -1,63 +0,0 @@ -using FishNet.Utility.Performance; -using System; - -namespace FishNet.Transporting.Tugboat -{ - - - internal struct Packet - { - public readonly int ConnectionId; - public readonly byte[] Data; - public readonly int Length; - public readonly byte Channel; - - public Packet(int connectionId, byte[] data, int length, byte channel) - { - ConnectionId = connectionId; - Data = data; - Length = length; - Channel = channel; - } - - public Packet(int sender, ArraySegment segment, byte channel, int mtu) - { - //Prefer to max out returned array to mtu to reduce chance of resizing. - int arraySize = Math.Max(segment.Count, mtu); - Data = ByteArrayPool.Retrieve(arraySize); - Buffer.BlockCopy(segment.Array, segment.Offset, Data, 0, segment.Count); - ConnectionId = sender; - Length = segment.Count; - Channel = channel; - } - - public ArraySegment GetArraySegment() - { - return new ArraySegment(Data, 0, Length); - } - - public void Dispose() - { - ByteArrayPool.Store(Data); - } - - } - - -} - -namespace FishNet.Transporting.Tugboat.Server -{ - - internal struct RemoteConnectionEvent - { - public readonly bool Connected; - public readonly int ConnectionId; - public RemoteConnectionEvent(bool connected, int connectionId) - { - Connected = connected; - ConnectionId = connectionId; - } - } -} - diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/Supporting.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/Supporting.cs.meta deleted file mode 100644 index 307a74f..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Core/Supporting.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 80c810a1a6a8f3345bb48abfb75c804a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib.meta deleted file mode 100644 index 6708b0d..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 9af335f3230cff649a5cc0c50e34a206 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/BaseChannel.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/BaseChannel.cs deleted file mode 100644 index 261839d..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/BaseChannel.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Concurrent; -using System.Threading; - -namespace LiteNetLib -{ - internal abstract class BaseChannel - { - protected readonly NetPeer Peer; - protected readonly ConcurrentQueue OutgoingQueue; - private int _isAddedToPeerChannelSendQueue; - - public int PacketsInQueue => OutgoingQueue.Count; - - protected BaseChannel(NetPeer peer) - { - Peer = peer; - OutgoingQueue = new ConcurrentQueue(); - } - - public void AddToQueue(NetPacket packet) - { - OutgoingQueue.Enqueue(packet); - AddToPeerChannelSendQueue(); - } - - protected void AddToPeerChannelSendQueue() - { - if (Interlocked.CompareExchange(ref _isAddedToPeerChannelSendQueue, 1, 0) == 0) - { - Peer.AddToReliableChannelSendQueue(this); - } - } - - public bool SendAndCheckQueue() - { - bool hasPacketsToSend = SendNextPackets(); - if (!hasPacketsToSend) - Interlocked.Exchange(ref _isAddedToPeerChannelSendQueue, 0); - - return hasPacketsToSend; - } - - protected abstract bool SendNextPackets(); - public abstract bool ProcessPacket(NetPacket packet); - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/BaseChannel.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/BaseChannel.cs.meta deleted file mode 100644 index 0d6a9bf..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/BaseChannel.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 70b7c357a9f57f5479c5d94550d26280 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ConnectionRequest.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ConnectionRequest.cs deleted file mode 100644 index 4a2cdd9..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ConnectionRequest.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System.Net; -using System.Threading; -using LiteNetLib.Utils; - -namespace LiteNetLib -{ - internal enum ConnectionRequestResult - { - None, - Accept, - Reject, - RejectForce - } - - public class ConnectionRequest - { - private readonly NetManager _listener; - private int _used; - - public NetDataReader Data => InternalPacket.Data; - - internal ConnectionRequestResult Result { get; private set; } - internal NetConnectRequestPacket InternalPacket; - - public readonly IPEndPoint RemoteEndPoint; - - internal void UpdateRequest(NetConnectRequestPacket connectRequest) - { - //old request - if (connectRequest.ConnectionTime < InternalPacket.ConnectionTime) - return; - - if (connectRequest.ConnectionTime == InternalPacket.ConnectionTime && - connectRequest.ConnectionNumber == InternalPacket.ConnectionNumber) - return; - - InternalPacket = connectRequest; - } - - private bool TryActivate() - { - return Interlocked.CompareExchange(ref _used, 1, 0) == 0; - } - - internal ConnectionRequest(IPEndPoint remoteEndPoint, NetConnectRequestPacket requestPacket, NetManager listener) - { - InternalPacket = requestPacket; - RemoteEndPoint = remoteEndPoint; - _listener = listener; - } - - public NetPeer AcceptIfKey(string key) - { - if (!TryActivate()) - return null; - try - { - if (Data.GetString() == key) - Result = ConnectionRequestResult.Accept; - } - catch - { - NetDebug.WriteError("[AC] Invalid incoming data"); - } - if (Result == ConnectionRequestResult.Accept) - return _listener.OnConnectionSolved(this, null, 0, 0); - - Result = ConnectionRequestResult.Reject; - _listener.OnConnectionSolved(this, null, 0, 0); - return null; - } - - /// - /// Accept connection and get new NetPeer as result - /// - /// Connected NetPeer - public NetPeer Accept() - { - if (!TryActivate()) - return null; - Result = ConnectionRequestResult.Accept; - return _listener.OnConnectionSolved(this, null, 0, 0); - } - - public void Reject(byte[] rejectData, int start, int length, bool force) - { - if (!TryActivate()) - return; - Result = force ? ConnectionRequestResult.RejectForce : ConnectionRequestResult.Reject; - _listener.OnConnectionSolved(this, rejectData, start, length); - } - - public void Reject(byte[] rejectData, int start, int length) - { - Reject(rejectData, start, length, false); - } - - - public void RejectForce(byte[] rejectData, int start, int length) - { - Reject(rejectData, start, length, true); - } - - public void RejectForce() - { - Reject(null, 0, 0, true); - } - - public void RejectForce(byte[] rejectData) - { - Reject(rejectData, 0, rejectData.Length, true); - } - - public void RejectForce(NetDataWriter rejectData) - { - Reject(rejectData.Data, 0, rejectData.Length, true); - } - - public void Reject() - { - Reject(null, 0, 0, false); - } - - public void Reject(byte[] rejectData) - { - Reject(rejectData, 0, rejectData.Length, false); - } - - public void Reject(NetDataWriter rejectData) - { - Reject(rejectData.Data, 0, rejectData.Length, false); - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ConnectionRequest.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ConnectionRequest.cs.meta deleted file mode 100644 index f1c5f19..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ConnectionRequest.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5e609855f95e9034889c882b51aaec68 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/INetEventListener.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/INetEventListener.cs deleted file mode 100644 index 13d8852..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/INetEventListener.cs +++ /dev/null @@ -1,272 +0,0 @@ -using System.Net; -using System.Net.Sockets; -using LiteNetLib.Utils; - -namespace LiteNetLib -{ - /// - /// Type of message that you receive in OnNetworkReceiveUnconnected event - /// - public enum UnconnectedMessageType - { - BasicMessage, - Broadcast - } - - /// - /// Disconnect reason that you receive in OnPeerDisconnected event - /// - public enum DisconnectReason - { - ConnectionFailed, - Timeout, - HostUnreachable, - NetworkUnreachable, - RemoteConnectionClose, - DisconnectPeerCalled, - ConnectionRejected, - InvalidProtocol, - UnknownHost, - Reconnect, - PeerToPeerConnection, - PeerNotFound - } - - /// - /// Additional information about disconnection - /// - public struct DisconnectInfo - { - /// - /// Additional info why peer disconnected - /// - public DisconnectReason Reason; - - /// - /// Error code (if reason is SocketSendError or SocketReceiveError) - /// - public SocketError SocketErrorCode; - - /// - /// Additional data that can be accessed (only if reason is RemoteConnectionClose) - /// - public NetPacketReader AdditionalData; - } - - public interface INetEventListener - { - /// - /// New remote peer connected to host, or client connected to remote host - /// - /// Connected peer object - void OnPeerConnected(NetPeer peer); - - /// - /// Peer disconnected - /// - /// disconnected peer - /// additional info about reason, errorCode or data received with disconnect message - void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo); - - /// - /// Network error (on send or receive) - /// - /// From endPoint (can be null) - /// Socket error - void OnNetworkError(IPEndPoint endPoint, SocketError socketError); - - /// - /// Received some data - /// - /// From peer - /// DataReader containing all received data - /// Number of channel at which packet arrived - /// Type of received packet - void OnNetworkReceive(NetPeer peer, NetPacketReader reader, byte channelNumber, DeliveryMethod deliveryMethod); - - /// - /// Received unconnected message - /// - /// From address (IP and Port) - /// Message data - /// Message type (simple, discovery request or response) - void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType); - - /// - /// Latency information updated - /// - /// Peer with updated latency - /// latency value in milliseconds - void OnNetworkLatencyUpdate(NetPeer peer, int latency); - - /// - /// On peer connection requested - /// - /// Request information (EndPoint, internal id, additional data) - void OnConnectionRequest(ConnectionRequest request); - } - - public interface IDeliveryEventListener - { - /// - /// On reliable message delivered - /// - /// - /// - void OnMessageDelivered(NetPeer peer, object userData); - } - - public interface INtpEventListener - { - /// - /// Ntp response - /// - /// - void OnNtpResponse(NtpPacket packet); - } - - public interface IPeerAddressChangedListener - { - /// - /// Called when peer address changed (when AllowPeerAddressChange is enabled) - /// - /// Peer that changed address (with new address) - /// previous IP - void OnPeerAddressChanged(NetPeer peer, IPEndPoint previousAddress); - } - - public class EventBasedNetListener : INetEventListener, IDeliveryEventListener, INtpEventListener, IPeerAddressChangedListener - { - public delegate void OnPeerConnected(NetPeer peer); - public delegate void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo); - public delegate void OnNetworkError(IPEndPoint endPoint, SocketError socketError); - public delegate void OnNetworkReceive(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod); - public delegate void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType); - public delegate void OnNetworkLatencyUpdate(NetPeer peer, int latency); - public delegate void OnConnectionRequest(ConnectionRequest request); - public delegate void OnDeliveryEvent(NetPeer peer, object userData); - public delegate void OnNtpResponseEvent(NtpPacket packet); - public delegate void OnPeerAddressChangedEvent(NetPeer peer, IPEndPoint previousAddress); - - public event OnPeerConnected PeerConnectedEvent; - public event OnPeerDisconnected PeerDisconnectedEvent; - public event OnNetworkError NetworkErrorEvent; - public event OnNetworkReceive NetworkReceiveEvent; - public event OnNetworkReceiveUnconnected NetworkReceiveUnconnectedEvent; - public event OnNetworkLatencyUpdate NetworkLatencyUpdateEvent; - public event OnConnectionRequest ConnectionRequestEvent; - public event OnDeliveryEvent DeliveryEvent; - public event OnNtpResponseEvent NtpResponseEvent; - public event OnPeerAddressChangedEvent PeerAddressChangedEvent; - - public void ClearPeerConnectedEvent() - { - PeerConnectedEvent = null; - } - - public void ClearPeerDisconnectedEvent() - { - PeerDisconnectedEvent = null; - } - - public void ClearNetworkErrorEvent() - { - NetworkErrorEvent = null; - } - - public void ClearNetworkReceiveEvent() - { - NetworkReceiveEvent = null; - } - - public void ClearNetworkReceiveUnconnectedEvent() - { - NetworkReceiveUnconnectedEvent = null; - } - - public void ClearNetworkLatencyUpdateEvent() - { - NetworkLatencyUpdateEvent = null; - } - - public void ClearConnectionRequestEvent() - { - ConnectionRequestEvent = null; - } - - public void ClearDeliveryEvent() - { - DeliveryEvent = null; - } - - public void ClearNtpResponseEvent() - { - NtpResponseEvent = null; - } - - public void ClearPeerAddressChangedEvent() - { - PeerAddressChangedEvent = null; - } - - void INetEventListener.OnPeerConnected(NetPeer peer) - { - if (PeerConnectedEvent != null) - PeerConnectedEvent(peer); - } - - void INetEventListener.OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) - { - if (PeerDisconnectedEvent != null) - PeerDisconnectedEvent(peer, disconnectInfo); - } - - void INetEventListener.OnNetworkError(IPEndPoint endPoint, SocketError socketErrorCode) - { - if (NetworkErrorEvent != null) - NetworkErrorEvent(endPoint, socketErrorCode); - } - - void INetEventListener.OnNetworkReceive(NetPeer peer, NetPacketReader reader, byte channelNumber, DeliveryMethod deliveryMethod) - { - if (NetworkReceiveEvent != null) - NetworkReceiveEvent(peer, reader, channelNumber, deliveryMethod); - } - - void INetEventListener.OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType) - { - if (NetworkReceiveUnconnectedEvent != null) - NetworkReceiveUnconnectedEvent(remoteEndPoint, reader, messageType); - } - - void INetEventListener.OnNetworkLatencyUpdate(NetPeer peer, int latency) - { - if (NetworkLatencyUpdateEvent != null) - NetworkLatencyUpdateEvent(peer, latency); - } - - void INetEventListener.OnConnectionRequest(ConnectionRequest request) - { - if (ConnectionRequestEvent != null) - ConnectionRequestEvent(request); - } - - void IDeliveryEventListener.OnMessageDelivered(NetPeer peer, object userData) - { - if (DeliveryEvent != null) - DeliveryEvent(peer, userData); - } - - void INtpEventListener.OnNtpResponse(NtpPacket packet) - { - if (NtpResponseEvent != null) - NtpResponseEvent(packet); - } - - void IPeerAddressChangedListener.OnPeerAddressChanged(NetPeer peer, IPEndPoint previousAddress) - { - if (PeerAddressChangedEvent != null) - PeerAddressChangedEvent(peer, previousAddress); - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/INetEventListener.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/INetEventListener.cs.meta deleted file mode 100644 index d4fc4bb..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/INetEventListener.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 79436ed5864cf48418ac341ea3c70a6b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/InternalPackets.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/InternalPackets.cs deleted file mode 100644 index 2eb09fe..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/InternalPackets.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System; -using System.Net; -using LiteNetLib.Utils; - -namespace LiteNetLib -{ - internal sealed class NetConnectRequestPacket - { - public const int HeaderSize = 18; - public readonly long ConnectionTime; - public byte ConnectionNumber; - public readonly byte[] TargetAddress; - public readonly NetDataReader Data; - public readonly int PeerId; - - private NetConnectRequestPacket(long connectionTime, byte connectionNumber, int localId, byte[] targetAddress, NetDataReader data) - { - ConnectionTime = connectionTime; - ConnectionNumber = connectionNumber; - TargetAddress = targetAddress; - Data = data; - PeerId = localId; - } - - public static int GetProtocolId(NetPacket packet) - { - return BitConverter.ToInt32(packet.RawData, 1); - } - - public static NetConnectRequestPacket FromData(NetPacket packet) - { - if (packet.ConnectionNumber >= NetConstants.MaxConnectionNumber) - return null; - - //Getting connection time for peer - long connectionTime = BitConverter.ToInt64(packet.RawData, 5); - - //Get peer id - int peerId = BitConverter.ToInt32(packet.RawData, 13); - - //Get target address - int addrSize = packet.RawData[HeaderSize-1]; - if (addrSize != 16 && addrSize != 28) - return null; - byte[] addressBytes = new byte[addrSize]; - Buffer.BlockCopy(packet.RawData, HeaderSize, addressBytes, 0, addrSize); - - // Read data and create request - var reader = new NetDataReader(null, 0, 0); - if (packet.Size > HeaderSize+addrSize) - reader.SetSource(packet.RawData, HeaderSize + addrSize, packet.Size); - - return new NetConnectRequestPacket(connectionTime, packet.ConnectionNumber, peerId, addressBytes, reader); - } - - public static NetPacket Make(NetDataWriter connectData, SocketAddress addressBytes, long connectTime, int localId) - { - //Make initial packet - var packet = new NetPacket(PacketProperty.ConnectRequest, connectData.Length+addressBytes.Size); - - //Add data - FastBitConverter.GetBytes(packet.RawData, 1, NetConstants.ProtocolId); - FastBitConverter.GetBytes(packet.RawData, 5, connectTime); - FastBitConverter.GetBytes(packet.RawData, 13, localId); - packet.RawData[HeaderSize-1] = (byte)addressBytes.Size; - for (int i = 0; i < addressBytes.Size; i++) - packet.RawData[HeaderSize + i] = addressBytes[i]; - Buffer.BlockCopy(connectData.Data, 0, packet.RawData, HeaderSize + addressBytes.Size, connectData.Length); - return packet; - } - } - - internal sealed class NetConnectAcceptPacket - { - public const int Size = 15; - public readonly long ConnectionTime; - public readonly byte ConnectionNumber; - public readonly int PeerId; - public readonly bool PeerNetworkChanged; - - private NetConnectAcceptPacket(long connectionTime, byte connectionNumber, int peerId, bool peerNetworkChanged) - { - ConnectionTime = connectionTime; - ConnectionNumber = connectionNumber; - PeerId = peerId; - PeerNetworkChanged = peerNetworkChanged; - } - - public static NetConnectAcceptPacket FromData(NetPacket packet) - { - if (packet.Size != Size) - return null; - - long connectionId = BitConverter.ToInt64(packet.RawData, 1); - - //check connect num - byte connectionNumber = packet.RawData[9]; - if (connectionNumber >= NetConstants.MaxConnectionNumber) - return null; - - //check reused flag - byte isReused = packet.RawData[10]; - if (isReused > 1) - return null; - - //get remote peer id - int peerId = BitConverter.ToInt32(packet.RawData, 11); - if (peerId < 0) - return null; - - return new NetConnectAcceptPacket(connectionId, connectionNumber, peerId, isReused == 1); - } - - public static NetPacket Make(long connectTime, byte connectNum, int localPeerId) - { - var packet = new NetPacket(PacketProperty.ConnectAccept, 0); - FastBitConverter.GetBytes(packet.RawData, 1, connectTime); - packet.RawData[9] = connectNum; - FastBitConverter.GetBytes(packet.RawData, 11, localPeerId); - return packet; - } - - public static NetPacket MakeNetworkChanged(NetPeer peer) - { - var packet = new NetPacket(PacketProperty.PeerNotFound, Size-1); - FastBitConverter.GetBytes(packet.RawData, 1, peer.ConnectTime); - packet.RawData[9] = peer.ConnectionNum; - packet.RawData[10] = 1; - FastBitConverter.GetBytes(packet.RawData, 11, peer.RemoteId); - return packet; - } - } -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/InternalPackets.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/InternalPackets.cs.meta deleted file mode 100644 index 5415d5d..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/InternalPackets.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b8582459906515843a2f2adb010c3fd7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers.meta deleted file mode 100644 index f2e0b72..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: bcd79f96aed490043aa493beed54d929 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/Crc32cLayer.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/Crc32cLayer.cs deleted file mode 100644 index 3ee97d6..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/Crc32cLayer.cs +++ /dev/null @@ -1,41 +0,0 @@ -using LiteNetLib.Utils; -using System; -using System.Net; - -namespace LiteNetLib.Layers -{ - public sealed class Crc32cLayer : PacketLayerBase - { - public Crc32cLayer() : base(CRC32C.ChecksumSize) - { - - } - - public override void ProcessInboundPacket(ref IPEndPoint endPoint, ref byte[] data, ref int offset, ref int length) - { - if (length < NetConstants.HeaderSize + CRC32C.ChecksumSize) - { - NetDebug.WriteError("[NM] DataReceived size: bad!"); - //Set length to 0 to have netManager drop the packet. - length = 0; - return; - } - - int checksumPoint = length - CRC32C.ChecksumSize; - if (CRC32C.Compute(data, offset, checksumPoint) != BitConverter.ToUInt32(data, checksumPoint)) - { - NetDebug.Write("[NM] DataReceived checksum: bad!"); - //Set length to 0 to have netManager drop the packet. - length = 0; - return; - } - length -= CRC32C.ChecksumSize; - } - - public override void ProcessOutBoundPacket(ref IPEndPoint endPoint, ref byte[] data, ref int offset, ref int length) - { - FastBitConverter.GetBytes(data, length, CRC32C.Compute(data, offset, length)); - length += CRC32C.ChecksumSize; - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/Crc32cLayer.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/Crc32cLayer.cs.meta deleted file mode 100644 index 45504b8..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/Crc32cLayer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7d52aafc1486ec842a8d133ef41dfd39 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/PacketLayerBase.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/PacketLayerBase.cs deleted file mode 100644 index b3d9b3a..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/PacketLayerBase.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Net; - -namespace LiteNetLib.Layers -{ - public abstract class PacketLayerBase - { - public readonly int ExtraPacketSizeForLayer; - - protected PacketLayerBase(int extraPacketSizeForLayer) - { - ExtraPacketSizeForLayer = extraPacketSizeForLayer; - } - - public abstract void ProcessInboundPacket(ref IPEndPoint endPoint, ref byte[] data, ref int offset, ref int length); - public abstract void ProcessOutBoundPacket(ref IPEndPoint endPoint, ref byte[] data, ref int offset, ref int length); - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/PacketLayerBase.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/PacketLayerBase.cs.meta deleted file mode 100644 index 43aaedb..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/PacketLayerBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: bddd0b5590cce7e42918c72429b84bde -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/XorEncryptLayer.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/XorEncryptLayer.cs deleted file mode 100644 index 9b67196..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/XorEncryptLayer.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Net; -using System.Text; - -namespace LiteNetLib.Layers -{ - public class XorEncryptLayer : PacketLayerBase - { - private byte[] _byteKey; - - public XorEncryptLayer() : base(0) - { - - } - - public XorEncryptLayer(byte[] key) : this() - { - SetKey(key); - } - - public XorEncryptLayer(string key) : this() - { - SetKey(key); - } - - public void SetKey(string key) - { - _byteKey = Encoding.UTF8.GetBytes(key); - } - - public void SetKey(byte[] key) - { - if (_byteKey == null || _byteKey.Length != key.Length) - _byteKey = new byte[key.Length]; - Buffer.BlockCopy(key, 0, _byteKey, 0, key.Length); - } - - public override void ProcessInboundPacket(ref IPEndPoint endPoint, ref byte[] data, ref int offset, ref int length) - { - if (_byteKey == null) - return; - var cur = offset; - for (var i = 0; i < length; i++, cur++) - { - data[cur] = (byte)(data[cur] ^ _byteKey[i % _byteKey.Length]); - } - } - - public override void ProcessOutBoundPacket(ref IPEndPoint endPoint, ref byte[] data, ref int offset, ref int length) - { - if (_byteKey == null) - return; - var cur = offset; - for (var i = 0; i < length; i++, cur++) - { - data[cur] = (byte)(data[cur] ^ _byteKey[i % _byteKey.Length]); - } - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/XorEncryptLayer.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/XorEncryptLayer.cs.meta deleted file mode 100644 index 14a4601..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Layers/XorEncryptLayer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fb37499ecdd1ce145b0bcaf4b4f0279e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NatPunchModule.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NatPunchModule.cs deleted file mode 100644 index bab2fca..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NatPunchModule.cs +++ /dev/null @@ -1,259 +0,0 @@ -using System.Collections.Concurrent; -using System.Net; -using LiteNetLib.Utils; - -namespace LiteNetLib -{ - public enum NatAddressType - { - Internal, - External - } - - public interface INatPunchListener - { - void OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, string token); - void OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token); - } - - public class EventBasedNatPunchListener : INatPunchListener - { - public delegate void OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, string token); - public delegate void OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token); - - public event OnNatIntroductionRequest NatIntroductionRequest; - public event OnNatIntroductionSuccess NatIntroductionSuccess; - - void INatPunchListener.OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, string token) - { - if(NatIntroductionRequest != null) - NatIntroductionRequest(localEndPoint, remoteEndPoint, token); - } - - void INatPunchListener.OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token) - { - if (NatIntroductionSuccess != null) - NatIntroductionSuccess(targetEndPoint, type, token); - } - } - - /// - /// Module for UDP NAT Hole punching operations. Can be accessed from NetManager - /// - public sealed class NatPunchModule - { - struct RequestEventData - { - public IPEndPoint LocalEndPoint; - public IPEndPoint RemoteEndPoint; - public string Token; - } - - struct SuccessEventData - { - public IPEndPoint TargetEndPoint; - public NatAddressType Type; - public string Token; - } - - class NatIntroduceRequestPacket - { - public IPEndPoint Internal { get; set; } - public string Token { get; set; } - } - - class NatIntroduceResponsePacket - { - public IPEndPoint Internal { get; set; } - public IPEndPoint External { get; set; } - public string Token { get; set; } - } - - class NatPunchPacket - { - public string Token { get; set; } - public bool IsExternal { get; set; } - } - - private readonly NetManager _socket; - private readonly ConcurrentQueue _requestEvents = new ConcurrentQueue(); - private readonly ConcurrentQueue _successEvents = new ConcurrentQueue(); - private readonly NetDataReader _cacheReader = new NetDataReader(); - private readonly NetDataWriter _cacheWriter = new NetDataWriter(); - private readonly NetPacketProcessor _netPacketProcessor = new NetPacketProcessor(MaxTokenLength); - private INatPunchListener _natPunchListener; - public const int MaxTokenLength = 256; - - /// - /// Events automatically will be called without PollEvents method from another thread - /// - public bool UnsyncedEvents = false; - - internal NatPunchModule(NetManager socket) - { - _socket = socket; - _netPacketProcessor.SubscribeReusable(OnNatIntroductionResponse); - _netPacketProcessor.SubscribeReusable(OnNatIntroductionRequest); - _netPacketProcessor.SubscribeReusable(OnNatPunch); - } - - internal void ProcessMessage(IPEndPoint senderEndPoint, NetPacket packet) - { - lock (_cacheReader) - { - _cacheReader.SetSource(packet.RawData, NetConstants.HeaderSize, packet.Size); - _netPacketProcessor.ReadAllPackets(_cacheReader, senderEndPoint); - } - } - - public void Init(INatPunchListener listener) - { - _natPunchListener = listener; - } - - private void Send(T packet, IPEndPoint target) where T : class, new() - { - _cacheWriter.Reset(); - _cacheWriter.Put((byte)PacketProperty.NatMessage); - _netPacketProcessor.Write(_cacheWriter, packet); - _socket.SendRaw(_cacheWriter.Data, 0, _cacheWriter.Length, target); - } - - public void NatIntroduce( - IPEndPoint hostInternal, - IPEndPoint hostExternal, - IPEndPoint clientInternal, - IPEndPoint clientExternal, - string additionalInfo) - { - var req = new NatIntroduceResponsePacket - { - Token = additionalInfo - }; - - //First packet (server) send to client - req.Internal = hostInternal; - req.External = hostExternal; - Send(req, clientExternal); - - //Second packet (client) send to server - req.Internal = clientInternal; - req.External = clientExternal; - Send(req, hostExternal); - } - - public void PollEvents() - { - if (UnsyncedEvents) - return; - - if (_natPunchListener == null || (_successEvents.IsEmpty && _requestEvents.IsEmpty)) - return; - - while (_successEvents.TryDequeue(out var evt)) - { - _natPunchListener.OnNatIntroductionSuccess( - evt.TargetEndPoint, - evt.Type, - evt.Token); - } - - while (_requestEvents.TryDequeue(out var evt)) - { - _natPunchListener.OnNatIntroductionRequest(evt.LocalEndPoint, evt.RemoteEndPoint, evt.Token); - } - } - - public void SendNatIntroduceRequest(string host, int port, string additionalInfo) - { - SendNatIntroduceRequest(NetUtils.MakeEndPoint(host, port), additionalInfo); - } - - public void SendNatIntroduceRequest(IPEndPoint masterServerEndPoint, string additionalInfo) - { - //prepare outgoing data - string networkIp = NetUtils.GetLocalIp(LocalAddrType.IPv4); - if (string.IsNullOrEmpty(networkIp)) - { - networkIp = NetUtils.GetLocalIp(LocalAddrType.IPv6); - } - - Send( - new NatIntroduceRequestPacket - { - Internal = NetUtils.MakeEndPoint(networkIp, _socket.LocalPort), - Token = additionalInfo - }, - masterServerEndPoint); - } - - //We got request and must introduce - private void OnNatIntroductionRequest(NatIntroduceRequestPacket req, IPEndPoint senderEndPoint) - { - if (UnsyncedEvents) - { - _natPunchListener.OnNatIntroductionRequest( - req.Internal, - senderEndPoint, - req.Token); - } - else - { - _requestEvents.Enqueue(new RequestEventData - { - LocalEndPoint = req.Internal, - RemoteEndPoint = senderEndPoint, - Token = req.Token - }); - } - } - - //We got introduce and must punch - private void OnNatIntroductionResponse(NatIntroduceResponsePacket req) - { - NetDebug.Write(NetLogLevel.Trace, "[NAT] introduction received"); - - // send internal punch - var punchPacket = new NatPunchPacket {Token = req.Token}; - Send(punchPacket, req.Internal); - NetDebug.Write(NetLogLevel.Trace, "[NAT] internal punch sent to " + req.Internal); - - // hack for some routers - _socket.Ttl = 2; - _socket.SendRaw(new[] { (byte)PacketProperty.Empty }, 0, 1, req.External); - - // send external punch - _socket.Ttl = NetConstants.SocketTTL; - punchPacket.IsExternal = true; - Send(punchPacket, req.External); - NetDebug.Write(NetLogLevel.Trace, "[NAT] external punch sent to " + req.External); - } - - //We got punch and can connect - private void OnNatPunch(NatPunchPacket req, IPEndPoint senderEndPoint) - { - //Read info - NetDebug.Write(NetLogLevel.Trace, "[NAT] punch received from {0} - additional info: {1}", - senderEndPoint, req.Token); - - //Release punch success to client; enabling him to Connect() to Sender if token is ok - if(UnsyncedEvents) - { - _natPunchListener.OnNatIntroductionSuccess( - senderEndPoint, - req.IsExternal ? NatAddressType.External : NatAddressType.Internal, - req.Token - ); - } - else - { - _successEvents.Enqueue(new SuccessEventData - { - TargetEndPoint = senderEndPoint, - Type = req.IsExternal ? NatAddressType.External : NatAddressType.Internal, - Token = req.Token - }); - } - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NatPunchModule.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NatPunchModule.cs.meta deleted file mode 100644 index 887acb2..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NatPunchModule.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e608aa88ab820244a90b83eca0f716c5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NativeSocket.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NativeSocket.cs deleted file mode 100644 index fc846c8..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NativeSocket.cs +++ /dev/null @@ -1,301 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Sockets; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace LiteNetLib -{ - internal readonly struct NativeAddr : IEquatable - { - //common parts - private readonly long _part1; //family, port, etc - private readonly long _part2; - //ipv6 parts - private readonly long _part3; - private readonly int _part4; - - private readonly int _hash; - - public NativeAddr(byte[] address, int len) - { - _part1 = BitConverter.ToInt64(address, 0); - _part2 = BitConverter.ToInt64(address, 8); - if (len > 16) - { - _part3 = BitConverter.ToInt64(address, 16); - _part4 = BitConverter.ToInt32(address, 24); - } - else - { - _part3 = 0; - _part4 = 0; - } - _hash = (int)(_part1 >> 32) ^ (int)_part1 ^ - (int)(_part2 >> 32) ^ (int)_part2 ^ - (int)(_part3 >> 32) ^ (int)_part3 ^ - _part4; - } - - public override int GetHashCode() - { - return _hash; - } - - public bool Equals(NativeAddr other) - { - return _part1 == other._part1 && - _part2 == other._part2 && - _part3 == other._part3 && - _part4 == other._part4; - } - - public override bool Equals(object obj) - { - return obj is NativeAddr other && Equals(other); - } - - public static bool operator ==(NativeAddr left, NativeAddr right) - { - return left.Equals(right); - } - - public static bool operator !=(NativeAddr left, NativeAddr right) - { - return !left.Equals(right); - } - } - - internal class NativeEndPoint : IPEndPoint - { - public readonly byte[] NativeAddress; - - public NativeEndPoint(byte[] address) : base(IPAddress.Any, 0) - { - NativeAddress = new byte[address.Length]; - Buffer.BlockCopy(address, 0, NativeAddress, 0, address.Length); - - short family = (short)((address[1] << 8) | address[0]); - Port =(ushort)((address[2] << 8) | address[3]); - - if ((NativeSocket.UnixMode && family == NativeSocket.AF_INET6) || (!NativeSocket.UnixMode && (AddressFamily)family == AddressFamily.InterNetworkV6)) - { - uint scope = unchecked((uint)( - (address[27] << 24) + - (address[26] << 16) + - (address[25] << 8) + - (address[24]))); -#if NETCOREAPP || NETSTANDARD2_1 || NETSTANDARD2_1_OR_GREATER - Address = new IPAddress(new ReadOnlySpan(address, 8, 16), scope); -#else - byte[] addrBuffer = new byte[16]; - Buffer.BlockCopy(address, 8, addrBuffer, 0, 16); - Address = new IPAddress(addrBuffer, scope); -#endif - } - else //IPv4 - { - long ipv4Addr = unchecked((uint)((address[4] & 0x000000FF) | - (address[5] << 8 & 0x0000FF00) | - (address[6] << 16 & 0x00FF0000) | - (address[7] << 24))); - Address = new IPAddress(ipv4Addr); - } - } - } - - internal static class NativeSocket - { - static -#if LITENETLIB_UNSAFE - unsafe -#endif - class WinSock - { - private const string LibName = "ws2_32.dll"; - - [DllImport(LibName, SetLastError = true)] - public static extern int recvfrom( - IntPtr socketHandle, - [In, Out] byte[] pinnedBuffer, - [In] int len, - [In] SocketFlags socketFlags, - [Out] byte[] socketAddress, - [In, Out] ref int socketAddressSize); - - [DllImport(LibName, SetLastError = true)] - internal static extern int sendto( - IntPtr socketHandle, -#if LITENETLIB_UNSAFE - byte* pinnedBuffer, -#else - [In] byte[] pinnedBuffer, -#endif - [In] int len, - [In] SocketFlags socketFlags, - [In] byte[] socketAddress, - [In] int socketAddressSize); - } - - static -#if LITENETLIB_UNSAFE - unsafe -#endif - class UnixSock - { - private const string LibName = "libc"; - - [DllImport(LibName, SetLastError = true)] - public static extern int recvfrom( - IntPtr socketHandle, - [In, Out] byte[] pinnedBuffer, - [In] int len, - [In] SocketFlags socketFlags, - [Out] byte[] socketAddress, - [In, Out] ref int socketAddressSize); - - [DllImport(LibName, SetLastError = true)] - internal static extern int sendto( - IntPtr socketHandle, -#if LITENETLIB_UNSAFE - byte* pinnedBuffer, -#else - [In] byte[] pinnedBuffer, -#endif - [In] int len, - [In] SocketFlags socketFlags, - [In] byte[] socketAddress, - [In] int socketAddressSize); - } - - public static readonly bool IsSupported = false; - public static readonly bool UnixMode = false; - - public const int IPv4AddrSize = 16; - public const int IPv6AddrSize = 28; - public const int AF_INET = 2; - public const int AF_INET6 = 10; - - private static readonly Dictionary NativeErrorToSocketError = new Dictionary - { - { 13, SocketError.AccessDenied }, //EACCES - { 98, SocketError.AddressAlreadyInUse }, //EADDRINUSE - { 99, SocketError.AddressNotAvailable }, //EADDRNOTAVAIL - { 97, SocketError.AddressFamilyNotSupported }, //EAFNOSUPPORT - { 11, SocketError.WouldBlock }, //EAGAIN - { 114, SocketError.AlreadyInProgress }, //EALREADY - { 9, SocketError.OperationAborted }, //EBADF - { 125, SocketError.OperationAborted }, //ECANCELED - { 103, SocketError.ConnectionAborted }, //ECONNABORTED - { 111, SocketError.ConnectionRefused }, //ECONNREFUSED - { 104, SocketError.ConnectionReset }, //ECONNRESET - { 89, SocketError.DestinationAddressRequired }, //EDESTADDRREQ - { 14, SocketError.Fault }, //EFAULT - { 112, SocketError.HostDown }, //EHOSTDOWN - { 6, SocketError.HostNotFound }, //ENXIO - { 113, SocketError.HostUnreachable }, //EHOSTUNREACH - { 115, SocketError.InProgress }, //EINPROGRESS - { 4, SocketError.Interrupted }, //EINTR - { 22, SocketError.InvalidArgument }, //EINVAL - { 106, SocketError.IsConnected }, //EISCONN - { 24, SocketError.TooManyOpenSockets }, //EMFILE - { 90, SocketError.MessageSize }, //EMSGSIZE - { 100, SocketError.NetworkDown }, //ENETDOWN - { 102, SocketError.NetworkReset }, //ENETRESET - { 101, SocketError.NetworkUnreachable }, //ENETUNREACH - { 23, SocketError.TooManyOpenSockets }, //ENFILE - { 105, SocketError.NoBufferSpaceAvailable }, //ENOBUFS - { 61, SocketError.NoData }, //ENODATA - { 2, SocketError.AddressNotAvailable }, //ENOENT - { 92, SocketError.ProtocolOption }, //ENOPROTOOPT - { 107, SocketError.NotConnected }, //ENOTCONN - { 88, SocketError.NotSocket }, //ENOTSOCK - { 3440, SocketError.OperationNotSupported }, //ENOTSUP - { 1, SocketError.AccessDenied }, //EPERM - { 32, SocketError.Shutdown }, //EPIPE - { 96, SocketError.ProtocolFamilyNotSupported }, //EPFNOSUPPORT - { 93, SocketError.ProtocolNotSupported }, //EPROTONOSUPPORT - { 91, SocketError.ProtocolType }, //EPROTOTYPE - { 94, SocketError.SocketNotSupported }, //ESOCKTNOSUPPORT - { 108, SocketError.Disconnecting }, //ESHUTDOWN - { 110, SocketError.TimedOut }, //ETIMEDOUT - { 0, SocketError.Success } - }; - - static NativeSocket() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - IsSupported = true; - UnixMode = true; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - IsSupported = true; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int RecvFrom( - IntPtr socketHandle, - byte[] pinnedBuffer, - int len, - byte[] socketAddress, - ref int socketAddressSize) - { - return UnixMode - ? UnixSock.recvfrom(socketHandle, pinnedBuffer, len, 0, socketAddress, ref socketAddressSize) - : WinSock.recvfrom(socketHandle, pinnedBuffer, len, 0, socketAddress, ref socketAddressSize); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public -#if LITENETLIB_UNSAFE - unsafe -#endif - static int SendTo( - IntPtr socketHandle, -#if LITENETLIB_UNSAFE - byte* pinnedBuffer, -#else - byte[] pinnedBuffer, -#endif - int len, - byte[] socketAddress, - int socketAddressSize) - { - return UnixMode - ? UnixSock.sendto(socketHandle, pinnedBuffer, len, 0, socketAddress, socketAddressSize) - : WinSock.sendto(socketHandle, pinnedBuffer, len, 0, socketAddress, socketAddressSize); - } - - public static SocketError GetSocketError() - { - int error = Marshal.GetLastWin32Error(); - if (UnixMode) - return NativeErrorToSocketError.TryGetValue(error, out var err) - ? err - : SocketError.SocketError; - return (SocketError)error; - } - - public static SocketException GetSocketException() - { - int error = Marshal.GetLastWin32Error(); - if (UnixMode) - return NativeErrorToSocketError.TryGetValue(error, out var err) - ? new SocketException((int)err) - : new SocketException((int)SocketError.SocketError); - return new SocketException(error); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static short GetNativeAddressFamily(IPEndPoint remoteEndPoint) - { - return UnixMode - ? (short)(remoteEndPoint.AddressFamily == AddressFamily.InterNetwork ? AF_INET : AF_INET6) - : (short)remoteEndPoint.AddressFamily; - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NativeSocket.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NativeSocket.cs.meta deleted file mode 100644 index f18fd7c..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NativeSocket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 12cfcf4490f2b8f4db979ee833ecf5af -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetConstants.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetConstants.cs deleted file mode 100644 index ca7dfbc..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetConstants.cs +++ /dev/null @@ -1,75 +0,0 @@ -namespace LiteNetLib -{ - /// - /// Sending method type - /// - public enum DeliveryMethod : byte - { - /// - /// Unreliable. Packets can be dropped, can be duplicated, can arrive without order. - /// - Unreliable = 4, - - /// - /// Reliable. Packets won't be dropped, won't be duplicated, can arrive without order. - /// - ReliableUnordered = 0, - - /// - /// Unreliable. Packets can be dropped, won't be duplicated, will arrive in order. - /// - Sequenced = 1, - - /// - /// Reliable and ordered. Packets won't be dropped, won't be duplicated, will arrive in order. - /// - ReliableOrdered = 2, - - /// - /// Reliable only last packet. Packets can be dropped (except the last one), won't be duplicated, will arrive in order. - /// Cannot be fragmented - /// - ReliableSequenced = 3 - } - - /// - /// Network constants. Can be tuned from sources for your purposes. - /// - public static class NetConstants - { - //can be tuned - public const int DefaultWindowSize = 64; - public const int SocketBufferSize = 1024 * 1024; //1mb - public const int SocketTTL = 255; - - public const int HeaderSize = 1; - public const int ChanneledHeaderSize = 4; - public const int FragmentHeaderSize = 6; - public const int FragmentedHeaderTotalSize = ChanneledHeaderSize + FragmentHeaderSize; - public const ushort MaxSequence = 32768; - public const ushort HalfMaxSequence = MaxSequence / 2; - - //protocol - internal const int ProtocolId = 13; - internal const int MaxUdpHeaderSize = 68; - internal const int ChannelTypeCount = 4; - - internal static readonly int[] PossibleMtu = - { - 576 - MaxUdpHeaderSize, //minimal (RFC 1191) - 1024, //most games standard - 1232 - MaxUdpHeaderSize, - 1460 - MaxUdpHeaderSize, //google cloud - 1472 - MaxUdpHeaderSize, //VPN - 1492 - MaxUdpHeaderSize, //Ethernet with LLC and SNAP, PPPoE (RFC 1042) - 1500 - MaxUdpHeaderSize //Ethernet II (RFC 1191) - }; - - //Max possible single packet size - public static readonly int MaxPacketSize = PossibleMtu[PossibleMtu.Length - 1]; - public static readonly int MaxUnreliableDataSize = MaxPacketSize - HeaderSize; - - //peer specific - public const byte MaxConnectionNumber = 4; - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetConstants.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetConstants.cs.meta deleted file mode 100644 index 653da3e..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetConstants.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b42ee5a523e67ff4c9149f91f7fe4245 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetDebug.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetDebug.cs deleted file mode 100644 index a326c0d..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetDebug.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using System.Diagnostics; - -namespace LiteNetLib -{ - public class InvalidPacketException : ArgumentException - { - public InvalidPacketException(string message) : base(message) - { - } - } - - public class TooBigPacketException : InvalidPacketException - { - public TooBigPacketException(string message) : base(message) - { - } - } - - public enum NetLogLevel - { - Warning, - Error, - Trace, - Info - } - - /// - /// Interface to implement for your own logger - /// - public interface INetLogger - { - void WriteNet(NetLogLevel level, string str, params object[] args); - } - - /// - /// Static class for defining your own LiteNetLib logger instead of Console.WriteLine - /// or Debug.Log if compiled with UNITY flag - /// - public static class NetDebug - { - public static INetLogger Logger = null; - private static readonly object DebugLogLock = new object(); - private static void WriteLogic(NetLogLevel logLevel, string str, params object[] args) - { - lock (DebugLogLock) - { - if (Logger == null) - { -#if UNITY_5_3_OR_NEWER - UnityEngine.Debug.Log(string.Format(str, args)); -#else - Console.WriteLine(str, args); -#endif - } - else - { - Logger.WriteNet(logLevel, str, args); - } - } - } - - [Conditional("DEBUG_MESSAGES")] - internal static void Write(string str, params object[] args) - { - WriteLogic(NetLogLevel.Trace, str, args); - } - - [Conditional("DEBUG_MESSAGES")] - internal static void Write(NetLogLevel level, string str, params object[] args) - { - WriteLogic(level, str, args); - } - - [Conditional("DEBUG_MESSAGES"), Conditional("DEBUG")] - internal static void WriteForce(string str, params object[] args) - { - WriteLogic(NetLogLevel.Trace, str, args); - } - - [Conditional("DEBUG_MESSAGES"), Conditional("DEBUG")] - internal static void WriteForce(NetLogLevel level, string str, params object[] args) - { - WriteLogic(level, str, args); - } - - internal static void WriteError(string str, params object[] args) - { - WriteLogic(NetLogLevel.Error, str, args); - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetDebug.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetDebug.cs.meta deleted file mode 100644 index 73bd709..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetDebug.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9f50ae51c124bf1439e339eee1fcd6f5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.PacketPool.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.PacketPool.cs deleted file mode 100644 index b2ae5e5..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.PacketPool.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Threading; - -namespace LiteNetLib -{ - public partial class NetManager - { - private NetPacket _poolHead; - private int _poolCount; - private readonly object _poolLock = new object(); - - /// - /// Maximum packet pool size (increase if you have tons of packets sending) - /// - public int PacketPoolSize = 1000; - - public int PoolCount => _poolCount; - - private NetPacket PoolGetWithData(PacketProperty property, byte[] data, int start, int length) - { - int headerSize = NetPacket.GetHeaderSize(property); - NetPacket packet = PoolGetPacket(length + headerSize); - packet.Property = property; - Buffer.BlockCopy(data, start, packet.RawData, headerSize, length); - return packet; - } - - //Get packet with size - private NetPacket PoolGetWithProperty(PacketProperty property, int size) - { - NetPacket packet = PoolGetPacket(size + NetPacket.GetHeaderSize(property)); - packet.Property = property; - return packet; - } - - private NetPacket PoolGetWithProperty(PacketProperty property) - { - NetPacket packet = PoolGetPacket(NetPacket.GetHeaderSize(property)); - packet.Property = property; - return packet; - } - - internal NetPacket PoolGetPacket(int size) - { - NetPacket packet; - lock (_poolLock) - { - packet = _poolHead; - if (packet == null) - return new NetPacket(size); - - _poolHead = _poolHead.Next; - _poolCount--; - } - - packet.Size = size; - if (packet.RawData.Length < size) - packet.RawData = new byte[size]; - return packet; - } - - internal void PoolRecycle(NetPacket packet) - { - if (packet.RawData.Length > NetConstants.MaxPacketSize || _poolCount >= PacketPoolSize) - { - //Don't pool big packets. Save memory - return; - } - - //Clean fragmented flag - packet.RawData[0] = 0; - lock (_poolLock) - { - packet.Next = _poolHead; - _poolHead = packet; - _poolCount++; - } - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.PacketPool.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.PacketPool.cs.meta deleted file mode 100644 index 1927ff0..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.PacketPool.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d384bada29340e542945f001cad348ac -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.Socket.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.Socket.cs deleted file mode 100644 index 6862b9c..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.Socket.cs +++ /dev/null @@ -1,701 +0,0 @@ -using System.Runtime.InteropServices; -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using LiteNetLib.Utils; - -namespace LiteNetLib -{ - - public partial class NetManager - { - public bool SocketActive(bool ipv4) - { - if (ipv4) - { - if (_udpSocketv4 != null) - return _udpSocketv4.Connected; - return false; - } - else - { - if (_udpSocketv6 != null) - return _udpSocketv6.Connected; - return false; - } - } - - private const int ReceivePollingTime = 500000; //0.5 second - - private Socket _udpSocketv4; - private Socket _udpSocketv6; - private Thread _threadv4; - private Thread _threadv6; - private IPEndPoint _bufferEndPointv4; - private IPEndPoint _bufferEndPointv6; - private PausedSocketFix _pausedSocketFix; - -#if !LITENETLIB_UNSAFE - [ThreadStatic] private static byte[] _sendToBuffer; -#endif - [ThreadStatic] private static byte[] _endPointBuffer; - - private readonly Dictionary _nativeAddrMap = new Dictionary(); - - private const int SioUdpConnreset = -1744830452; //SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12 - private static readonly IPAddress MulticastAddressV6 = IPAddress.Parse("ff02::1"); - public static readonly bool IPv6Support; - - /// - /// Maximum packets count that will be processed in Manual PollEvents - /// - public int MaxPacketsReceivePerUpdate = 0; - - public short Ttl - { - get - { -#if UNITY_SWITCH - return 0; -#else - return _udpSocketv4.Ttl; -#endif - } - internal set - { -#if !UNITY_SWITCH - _udpSocketv4.Ttl = value; -#endif - } - } - - static NetManager() - { -#if DISABLE_IPV6 - IPv6Support = false; -#elif !UNITY_2019_1_OR_NEWER && !UNITY_2018_4_OR_NEWER && (!UNITY_EDITOR && ENABLE_IL2CPP) - string version = UnityEngine.Application.unityVersion; - IPv6Support = Socket.OSSupportsIPv6 && int.Parse(version.Remove(version.IndexOf('f')).Split('.')[2]) >= 6; -#else - IPv6Support = Socket.OSSupportsIPv6; -#endif - } - - private bool IsActive() - { - return IsRunning; - } - - private void RegisterEndPoint(IPEndPoint ep) - { - if (UseNativeSockets && ep is NativeEndPoint nep) - { - _nativeAddrMap.Add(new NativeAddr(nep.NativeAddress, nep.NativeAddress.Length), nep); - } - } - - private void UnregisterEndPoint(IPEndPoint ep) - { - if (UseNativeSockets && ep is NativeEndPoint nep) - { - var nativeAddr = new NativeAddr(nep.NativeAddress, nep.NativeAddress.Length); - _nativeAddrMap.Remove(nativeAddr); - } - } - - private bool ProcessError(SocketException ex) - { - switch (ex.SocketErrorCode) - { -#if UNITY_IOS && !UNITY_EDITOR - case SocketError.NotConnected: -#endif - case SocketError.Interrupted: - case SocketError.NotSocket: - case SocketError.OperationAborted: - return true; - case SocketError.ConnectionReset: - case SocketError.MessageSize: - case SocketError.TimedOut: - case SocketError.NetworkReset: - //NetDebug.Write($"[R]Ignored error: {(int)ex.SocketErrorCode} - {ex}"); - break; - default: - NetDebug.WriteError($"[R]Error code: {(int)ex.SocketErrorCode} - {ex}"); - CreateEvent(NetEvent.EType.Error, errorCode: ex.SocketErrorCode); - break; - } - return false; - } - - private void ManualReceive(Socket socket, EndPoint bufferEndPoint) - { - //Reading data - try - { - int packetsReceived = 0; - while (socket.Available > 0) - { - var packet = PoolGetPacket(NetConstants.MaxPacketSize); - packet.Size = socket.ReceiveFrom(packet.RawData, 0, NetConstants.MaxPacketSize, SocketFlags.None, - ref bufferEndPoint); - //NetDebug.Write(NetLogLevel.Trace, $"[R]Received data from {bufferEndPoint}, result: {packet.Size}"); - OnMessageReceived(packet, (IPEndPoint)bufferEndPoint); - packetsReceived++; - if (packetsReceived == MaxPacketsReceivePerUpdate) - break; - } - } - catch (SocketException ex) - { - ProcessError(ex); - } - catch (ObjectDisposedException) - { - - } - catch (Exception e) - { - //protects socket receive thread - NetDebug.WriteError("[NM] SocketReceiveThread error: " + e); - } - } - - private void NativeReceiveLogic(object state) - { - Socket socket = (Socket)state; - IntPtr socketHandle = socket.Handle; - byte[] addrBuffer = new byte[socket.AddressFamily == AddressFamily.InterNetwork - ? NativeSocket.IPv4AddrSize - : NativeSocket.IPv6AddrSize]; - - int addrSize = addrBuffer.Length; - NetPacket packet = PoolGetPacket(NetConstants.MaxPacketSize); - - while (IsActive()) - { - //Reading data - packet.Size = NativeSocket.RecvFrom(socketHandle, packet.RawData, NetConstants.MaxPacketSize, addrBuffer, ref addrSize); - if (packet.Size == 0) - return; - if (packet.Size == -1) - { - SocketError errorCode = NativeSocket.GetSocketError(); - if (errorCode == SocketError.WouldBlock || errorCode == SocketError.TimedOut) //Linux timeout EAGAIN - continue; - if (ProcessError(new SocketException((int)errorCode))) - return; - continue; - } - - NativeAddr nativeAddr = new NativeAddr(addrBuffer, addrSize); - if (!_nativeAddrMap.TryGetValue(nativeAddr, out var endPoint)) - endPoint = new NativeEndPoint(addrBuffer); - - //All ok! - //NetDebug.WriteForce($"[R]Received data from {endPoint}, result: {packet.Size}"); - OnMessageReceived(packet, endPoint); - packet = PoolGetPacket(NetConstants.MaxPacketSize); - } - } - - private void ReceiveLogic(object state) - { - Socket socket = (Socket)state; - EndPoint bufferEndPoint = new IPEndPoint(socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0); - - while (IsActive()) - { - //Reading data - try - { - if (socket.Available == 0 && !socket.Poll(ReceivePollingTime, SelectMode.SelectRead)) - continue; - NetPacket packet = PoolGetPacket(NetConstants.MaxPacketSize); - packet.Size = socket.ReceiveFrom(packet.RawData, 0, NetConstants.MaxPacketSize, SocketFlags.None, - ref bufferEndPoint); - - //NetDebug.Write(NetLogLevel.Trace, $"[R]Received data from {bufferEndPoint}, result: {packet.Size}"); - OnMessageReceived(packet, (IPEndPoint)bufferEndPoint); - } - catch (SocketException ex) - { - if (ProcessError(ex)) - return; - } - catch (ObjectDisposedException) - { - //socket closed - return; - } - catch (ThreadAbortException) - { - //thread closed - return; - } - catch (Exception e) - { - //protects socket receive thread - NetDebug.WriteError("[NM] SocketReceiveThread error: " + e); - } - } - } - - /// - /// Start logic thread and listening on selected port - /// - /// bind to specific ipv4 address - /// bind to specific ipv6 address - /// port to listen - /// mode of library - public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool manualMode) - { - if (IsRunning && !IsActive()) - return false; - _manualMode = manualMode; - UseNativeSockets = UseNativeSockets && NativeSocket.IsSupported; - - //osx doesn't support dual mode - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && IPv6Mode == IPv6Mode.DualMode) - IPv6Mode = IPv6Mode.SeparateSocket; - - bool dualMode = IPv6Mode == IPv6Mode.DualMode && IPv6Support; - - _udpSocketv4 = new Socket( - dualMode ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, - SocketType.Dgram, - ProtocolType.Udp); - - if (!BindSocket(_udpSocketv4, new IPEndPoint(dualMode ? addressIPv6 : addressIPv4, port))) - return false; - - LocalPort = ((IPEndPoint)_udpSocketv4.LocalEndPoint).Port; - - if (_pausedSocketFix == null) - _pausedSocketFix = new PausedSocketFix(this, addressIPv4, addressIPv6, port, manualMode); - - if (dualMode) - _udpSocketv6 = _udpSocketv4; - - IsRunning = true; - if (!_manualMode) - { - ParameterizedThreadStart ts = ReceiveLogic; - if (UseNativeSockets) - ts = NativeReceiveLogic; - - _threadv4 = new Thread(ts) - { - Name = $"SocketThreadv4({LocalPort})", - IsBackground = true - }; - _threadv4.Start(_udpSocketv4); - - _logicThread = new Thread(UpdateLogic) { Name = "LogicThread", IsBackground = true }; - _logicThread.Start(); - } - else - { - _bufferEndPointv4 = new IPEndPoint(IPAddress.Any, 0); - } - - //Check IPv6 support - if (IPv6Support && IPv6Mode == IPv6Mode.SeparateSocket) - { - _udpSocketv6 = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); - //Use one port for two sockets - if (BindSocket(_udpSocketv6, new IPEndPoint(addressIPv6, LocalPort))) - { - if (_manualMode) - { - _bufferEndPointv6 = new IPEndPoint(IPAddress.IPv6Any, 0); - } - else - { - ParameterizedThreadStart ts = ReceiveLogic; - if (UseNativeSockets) - ts = NativeReceiveLogic; - _threadv6 = new Thread(ts) - { - Name = $"SocketThreadv6({LocalPort})", - IsBackground = true - }; - _threadv6.Start(_udpSocketv6); - } - } - } - - return true; - } - - private bool BindSocket(Socket socket, IPEndPoint ep) - { - //Setup socket - socket.ReceiveTimeout = 500; - socket.SendTimeout = 500; - socket.ReceiveBufferSize = NetConstants.SocketBufferSize; - socket.SendBufferSize = NetConstants.SocketBufferSize; - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - try - { - socket.IOControl(SioUdpConnreset, new byte[] { 0 }, null); - } - catch - { - //ignored - } - } - - try - { - socket.ExclusiveAddressUse = !ReuseAddress; - socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, ReuseAddress); - } - catch - { - //Unity with IL2CPP throws an exception here, it doesn't matter in most cases so just ignore it - } - if (ep.AddressFamily == AddressFamily.InterNetwork || IPv6Mode == IPv6Mode.DualMode) - { - Ttl = NetConstants.SocketTTL; - - try { socket.EnableBroadcast = true; } - catch (SocketException e) - { - NetDebug.WriteError($"[B]Broadcast error: {e.SocketErrorCode}"); - } - - if (IPv6Mode == IPv6Mode.DualMode) - { - try { socket.DualMode = true; } - catch (Exception e) - { - NetDebug.WriteError($"[B]Bind exception (dualmode setting): {e}"); - } - } - else if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - try { socket.DontFragment = true; } - catch (SocketException e) - { - NetDebug.WriteError($"[B]DontFragment error: {e.SocketErrorCode}"); - } - } - } - //Bind - try - { - socket.Bind(ep); - NetDebug.Write(NetLogLevel.Trace, $"[B]Successfully binded to port: {((IPEndPoint)socket.LocalEndPoint).Port}, AF: {socket.AddressFamily}"); - - //join multicast - if (ep.AddressFamily == AddressFamily.InterNetworkV6) - { - try - { -#if !UNITY_2018_3_OR_NEWER - socket.SetSocketOption( - SocketOptionLevel.IPv6, - SocketOptionName.AddMembership, - new IPv6MulticastOption(MulticastAddressV6)); -#endif - } - catch (Exception) - { - // Unity3d throws exception - ignored - } - } - } - catch (SocketException bindException) - { - switch (bindException.SocketErrorCode) - { - //IPv6 bind fix - case SocketError.AddressAlreadyInUse: - if (socket.AddressFamily == AddressFamily.InterNetworkV6 && IPv6Mode != IPv6Mode.DualMode) - { - try - { - //Set IPv6Only - socket.DualMode = false; - socket.Bind(ep); - } - catch (SocketException ex) - { - //because its fixed in 2018_3 - NetDebug.WriteError($"[B]Bind exception: {ex}, errorCode: {ex.SocketErrorCode}"); - return false; - } - return true; - } - break; - //hack for iOS (Unity3D) - case SocketError.AddressFamilyNotSupported: - return true; - } - NetDebug.WriteError($"[B]Bind exception: {bindException}, errorCode: {bindException.SocketErrorCode}"); - return false; - } - return true; - } - - internal int SendRawAndRecycle(NetPacket packet, IPEndPoint remoteEndPoint) - { - int result = SendRaw(packet.RawData, 0, packet.Size, remoteEndPoint); - PoolRecycle(packet); - return result; - } - - internal int SendRaw(NetPacket packet, IPEndPoint remoteEndPoint) - { - return SendRaw(packet.RawData, 0, packet.Size, remoteEndPoint); - } - - internal int SendRaw(byte[] message, int start, int length, IPEndPoint remoteEndPoint) - { - if (!IsRunning) - return 0; - - NetPacket expandedPacket = null; - if (_extraPacketLayer != null) - { - expandedPacket = PoolGetPacket(length + _extraPacketLayer.ExtraPacketSizeForLayer); - Buffer.BlockCopy(message, start, expandedPacket.RawData, 0, length); - start = 0; - _extraPacketLayer.ProcessOutBoundPacket(ref remoteEndPoint, ref expandedPacket.RawData, ref start, ref length); - message = expandedPacket.RawData; - } - - var socket = _udpSocketv4; - if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6 && IPv6Support) - { - socket = _udpSocketv6; - if (socket == null) - return 0; - } - - int result; - try - { - if (UseNativeSockets) - { - byte[] socketAddress; - - if (remoteEndPoint is NativeEndPoint nep) - { - socketAddress = nep.NativeAddress; - } - else //Convert endpoint to raw - { - if (_endPointBuffer == null) - _endPointBuffer = new byte[NativeSocket.IPv6AddrSize]; - socketAddress = _endPointBuffer; - - bool ipv4 = remoteEndPoint.AddressFamily == AddressFamily.InterNetwork; - short addressFamily = NativeSocket.GetNativeAddressFamily(remoteEndPoint); - - socketAddress[0] = (byte)(addressFamily); - socketAddress[1] = (byte)(addressFamily >> 8); - socketAddress[2] = (byte)(remoteEndPoint.Port >> 8); - socketAddress[3] = (byte)(remoteEndPoint.Port); - - if (ipv4) - { -#pragma warning disable 618 - long addr = remoteEndPoint.Address.Address; -#pragma warning restore 618 - socketAddress[4] = (byte)(addr); - socketAddress[5] = (byte)(addr >> 8); - socketAddress[6] = (byte)(addr >> 16); - socketAddress[7] = (byte)(addr >> 24); - } - else - { -#if NETCOREAPP || NETSTANDARD2_1 || NETSTANDARD2_1_OR_GREATER - remoteEndPoint.Address.TryWriteBytes(new Span(socketAddress, 8, 16), out _); -#else - byte[] addrBytes = remoteEndPoint.Address.GetAddressBytes(); - Buffer.BlockCopy(addrBytes, 0, socketAddress, 8, 16); -#endif - } - } - -#if LITENETLIB_UNSAFE - unsafe - { - fixed (byte* dataWithOffset = &message[start]) - { - result = - NativeSocket.SendTo(socket.Handle, dataWithOffset, length, socketAddress, socketAddress.Length); - } - } -#else - if (start > 0) - { - if (_sendToBuffer == null) - _sendToBuffer = new byte[NetConstants.MaxPacketSize]; - Buffer.BlockCopy(message, start, _sendToBuffer, 0, length); - message = _sendToBuffer; - } - - result = NativeSocket.SendTo(socket.Handle, message, length, socketAddress, socketAddress.Length); -#endif - if (result == -1) - throw NativeSocket.GetSocketException(); - } - else - { - result = socket.SendTo(message, start, length, SocketFlags.None, remoteEndPoint); - } - //NetDebug.WriteForce("[S]Send packet to {0}, result: {1}", remoteEndPoint, result); - } - catch (SocketException ex) - { - switch (ex.SocketErrorCode) - { - case SocketError.NoBufferSpaceAvailable: - case SocketError.Interrupted: - return 0; - case SocketError.MessageSize: - NetDebug.Write(NetLogLevel.Trace, "[SRD] 10040, datalen: {0}", length); - return 0; - - case SocketError.HostUnreachable: - case SocketError.NetworkUnreachable: - if (DisconnectOnUnreachable && TryGetPeer(remoteEndPoint, out var fromPeer)) - { - DisconnectPeerForce( - fromPeer, - ex.SocketErrorCode == SocketError.HostUnreachable - ? DisconnectReason.HostUnreachable - : DisconnectReason.NetworkUnreachable, - ex.SocketErrorCode, - null); - } - - CreateEvent(NetEvent.EType.Error, remoteEndPoint: remoteEndPoint, errorCode: ex.SocketErrorCode); - return -1; - - default: - NetDebug.WriteError($"[S] {ex}"); - return -1; - } - } - catch (Exception ex) - { - NetDebug.WriteError($"[S] {ex}"); - return 0; - } - finally - { - if (expandedPacket != null) - { - PoolRecycle(expandedPacket); - } - } - - if (result <= 0) - return 0; - - if (EnableStatistics) - { - Statistics.IncrementPacketsSent(); - Statistics.AddBytesSent(length); - } - - return result; - } - - public bool SendBroadcast(NetDataWriter writer, int port) - { - return SendBroadcast(writer.Data, 0, writer.Length, port); - } - - public bool SendBroadcast(byte[] data, int port) - { - return SendBroadcast(data, 0, data.Length, port); - } - - public bool SendBroadcast(byte[] data, int start, int length, int port) - { - if (!IsActive()) - return false; - - NetPacket packet; - if (_extraPacketLayer != null) - { - var headerSize = NetPacket.GetHeaderSize(PacketProperty.Broadcast); - packet = PoolGetPacket(headerSize + length + _extraPacketLayer.ExtraPacketSizeForLayer); - packet.Property = PacketProperty.Broadcast; - Buffer.BlockCopy(data, start, packet.RawData, headerSize, length); - var checksumComputeStart = 0; - int preCrcLength = length + headerSize; - IPEndPoint emptyEp = null; - _extraPacketLayer.ProcessOutBoundPacket(ref emptyEp, ref packet.RawData, ref checksumComputeStart, ref preCrcLength); - } - else - { - packet = PoolGetWithData(PacketProperty.Broadcast, data, start, length); - } - - bool broadcastSuccess = false; - bool multicastSuccess = false; - try - { - broadcastSuccess = _udpSocketv4.SendTo( - packet.RawData, - 0, - packet.Size, - SocketFlags.None, - new IPEndPoint(IPAddress.Broadcast, port)) > 0; - - if (_udpSocketv6 != null) - { - multicastSuccess = _udpSocketv6.SendTo( - packet.RawData, - 0, - packet.Size, - SocketFlags.None, - new IPEndPoint(MulticastAddressV6, port)) > 0; - } - } - catch (Exception ex) - { - NetDebug.WriteError($"[S][MCAST] {ex}"); - return broadcastSuccess; - } - finally - { - PoolRecycle(packet); - } - - return broadcastSuccess || multicastSuccess; - } - - internal void CloseSocket(bool suspend) - { - if (!suspend) - IsRunning = false; - - //cleanup dual mode - if (_udpSocketv4 == _udpSocketv6) - _udpSocketv6 = null; - - _udpSocketv4?.Close(); - _udpSocketv6?.Close(); - _udpSocketv4 = null; - _udpSocketv6 = null; - - if (_threadv4 != null && _threadv4 != Thread.CurrentThread) - _threadv4.Join(); - if (_threadv6 != null && _threadv6 != Thread.CurrentThread) - _threadv6.Join(); - _threadv4 = null; - _threadv6 = null; - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.Socket.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.Socket.cs.meta deleted file mode 100644 index a418311..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.Socket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9cc0423407df3e74a8e5a15dbbad2598 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.cs deleted file mode 100644 index 23ee56b..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.cs +++ /dev/null @@ -1,1789 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using LiteNetLib.Layers; -using LiteNetLib.Utils; - -namespace LiteNetLib -{ - public enum IPv6Mode - { - Disabled, - SeparateSocket, - DualMode - } - - public sealed class NetPacketReader : NetDataReader - { - private NetPacket _packet; - private readonly NetManager _manager; - private readonly NetEvent _evt; - - internal NetPacketReader(NetManager manager, NetEvent evt) - { - _manager = manager; - _evt = evt; - } - - internal void SetSource(NetPacket packet, int headerSize) - { - if (packet == null) - return; - _packet = packet; - SetSource(packet.RawData, headerSize, packet.Size); - } - - internal void Recycle_Internal() - { - Clear(); - if (_packet != null) - _manager.PoolRecycle(_packet); - _packet = null; - _manager.RecycleEvent(_evt); - } - - public void Recycle() - { - if (_manager.AutoRecycle) - return; - Recycle_Internal(); - } - } - - internal sealed class NetEvent - { - public NetEvent Next; - - public enum EType - { - Connect, - Disconnect, - Receive, - ReceiveUnconnected, - Error, - ConnectionLatencyUpdated, - Broadcast, - ConnectionRequest, - MessageDelivered, - PeerAddressChanged - } - public EType Type; - - public NetPeer Peer; - public IPEndPoint RemoteEndPoint; - public object UserData; - public int Latency; - public SocketError ErrorCode; - public DisconnectReason DisconnectReason; - public ConnectionRequest ConnectionRequest; - public DeliveryMethod DeliveryMethod; - public byte ChannelNumber; - public readonly NetPacketReader DataReader; - - public NetEvent(NetManager manager) - { - DataReader = new NetPacketReader(manager, this); - } - } - - /// - /// Main class for all network operations. Can be used as client and/or server. - /// - public partial class NetManager : IEnumerable - { - private class IPEndPointComparer : IEqualityComparer - { - public bool Equals(IPEndPoint x, IPEndPoint y) - { - return x.Address.Equals(y.Address) && x.Port == y.Port; - } - - public int GetHashCode(IPEndPoint obj) - { - return obj.GetHashCode(); - } - } - - public struct NetPeerEnumerator : IEnumerator - { - private readonly NetPeer _initialPeer; - private NetPeer _p; - - public NetPeerEnumerator(NetPeer p) - { - _initialPeer = p; - _p = null; - } - - public void Dispose() - { - - } - - public bool MoveNext() - { - _p = _p == null ? _initialPeer : _p.NextPeer; - return _p != null; - } - - public void Reset() - { - throw new NotSupportedException(); - } - - public NetPeer Current => _p; - object IEnumerator.Current => _p; - } - -#if DEBUG - private struct IncomingData - { - public NetPacket Data; - public IPEndPoint EndPoint; - public DateTime TimeWhenGet; - } - private readonly List _pingSimulationList = new List(); - private readonly Random _randomGenerator = new Random(); - private const int MinLatencyThreshold = 5; -#endif - - private Thread _logicThread; - private bool _manualMode; - private readonly AutoResetEvent _updateTriggerEvent = new AutoResetEvent(true); - - private Queue _netEventsProduceQueue = new Queue(); - private Queue _netEventsConsumeQueue = new Queue(); - - private NetEvent _netEventPoolHead; - private readonly INetEventListener _netEventListener; - private readonly IDeliveryEventListener _deliveryEventListener; - private readonly INtpEventListener _ntpEventListener; - private readonly IPeerAddressChangedListener _peerAddressChangedListener; - - private readonly Dictionary _peersDict = new Dictionary(new IPEndPointComparer()); - private readonly Dictionary _requestsDict = new Dictionary(new IPEndPointComparer()); - private readonly Dictionary _ntpRequests = new Dictionary(new IPEndPointComparer()); - private readonly ReaderWriterLockSlim _peersLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); - private volatile NetPeer _headPeer; - private int _connectedPeersCount; - private readonly List _connectedPeerListCache = new List(); - private NetPeer[] _peersArray = new NetPeer[32]; - private readonly PacketLayerBase _extraPacketLayer; - private int _lastPeerId; - private ConcurrentQueue _peerIds = new ConcurrentQueue(); - private byte _channelsCount = 1; - private readonly object _eventLock = new object(); - - //config section - /// - /// Enable messages receiving without connection. (with SendUnconnectedMessage method) - /// - public bool UnconnectedMessagesEnabled = false; - - /// - /// Enable nat punch messages - /// - public bool NatPunchEnabled = false; - - /// - /// Library logic update and send period in milliseconds - /// Lowest values in Windows doesn't change much because of Thread.Sleep precision - /// To more frequent sends (or sends tied to your game logic) use - /// - public int UpdateTime = 15; - - /// - /// Interval for latency detection and checking connection (in milliseconds) - /// - public int PingInterval = 1000; - - /// - /// If NetManager doesn't receive any packet from remote peer during this time (in milliseconds) then connection will be closed - /// (including library internal keepalive packets) - /// - public int DisconnectTimeout = 5000; - - /// - /// Simulate packet loss by dropping random amount of packets. (Works only in DEBUG mode) - /// - public bool SimulatePacketLoss = false; - - /// - /// Simulate latency by holding packets for random time. (Works only in DEBUG mode) - /// - public bool SimulateLatency = false; - - /// - /// Chance of packet loss when simulation enabled. value in percents (1 - 100). - /// - public int SimulationPacketLossChance = 10; - - /// - /// Minimum simulated latency (in milliseconds) - /// - public int SimulationMinLatency = 30; - - /// - /// Maximum simulated latency (in milliseconds) - /// - public int SimulationMaxLatency = 100; - - /// - /// Events automatically will be called without PollEvents method from another thread - /// - public bool UnsyncedEvents = false; - - /// - /// If true - receive event will be called from "receive" thread immediately otherwise on PollEvents call - /// - public bool UnsyncedReceiveEvent = false; - - /// - /// If true - delivery event will be called from "receive" thread immediately otherwise on PollEvents call - /// - public bool UnsyncedDeliveryEvent = false; - - /// - /// Allows receive broadcast packets - /// - public bool BroadcastReceiveEnabled = false; - - /// - /// Delay between initial connection attempts (in milliseconds) - /// - public int ReconnectDelay = 500; - - /// - /// Maximum connection attempts before client stops and call disconnect event. - /// - public int MaxConnectAttempts = 10; - - /// - /// Enables socket option "ReuseAddress" for specific purposes - /// - public bool ReuseAddress = false; - - /// - /// Statistics of all connections - /// - public readonly NetStatistics Statistics = new NetStatistics(); - - /// - /// Toggles the collection of network statistics for the instance and all known peers - /// - public bool EnableStatistics = false; - - /// - /// NatPunchModule for NAT hole punching operations - /// - public readonly NatPunchModule NatPunchModule; - - /// - /// Returns true if socket listening and update thread is running - /// - public bool IsRunning { get; private set; } - - /// - /// Local EndPoint (host and port) - /// - public int LocalPort { get; private set; } - - /// - /// Automatically recycle NetPacketReader after OnReceive event - /// - public bool AutoRecycle; - - /// - /// IPv6 support - /// - public IPv6Mode IPv6Mode = IPv6Mode.SeparateSocket; - - /// - /// Override MTU for all new peers registered in this NetManager, will ignores MTU Discovery! - /// - public int MtuOverride = 0; - - /// - /// Sets initial MTU to lowest possible value according to RFC1191 (576 bytes) - /// - public bool UseSafeMtu = false; - - /// - /// First peer. Useful for Client mode - /// - public NetPeer FirstPeer => _headPeer; - - /// - /// Experimental feature mostly for servers. Only for Windows/Linux - /// use direct socket calls for send/receive to drastically increase speed and reduce GC pressure - /// - public bool UseNativeSockets = false; - - /// - /// Disconnect peers if HostUnreachable or NetworkUnreachable spawned (old behaviour 0.9.x was true) - /// - public bool DisconnectOnUnreachable = false; - - /// - /// Allows peer change it's ip (lte to wifi, wifi to lte, etc). Use only on server - /// - public bool AllowPeerAddressChange = false; - - /// - /// QoS channel count per message type (value must be between 1 and 64 channels) - /// - public byte ChannelsCount - { - get => _channelsCount; - set - { - if (value < 1 || value > 64) - throw new ArgumentException("Channels count must be between 1 and 64"); - _channelsCount = value; - } - } - - /// - /// Returns connected peers list (with internal cached list) - /// - public List ConnectedPeerList - { - get - { - GetPeersNonAlloc(_connectedPeerListCache, ConnectionState.Connected); - return _connectedPeerListCache; - } - } - - /// - /// Gets peer by peer id - /// - /// id of peer - /// Peer if peer with id exist, otherwise null - public NetPeer GetPeerById(int id) - { - if (id >= 0 && id < _peersArray.Length) - { - return _peersArray[id]; - } - - return null; - } - - /// - /// Gets peer by peer id - /// - /// id of peer - /// resulting peer - /// True if peer with id exist, otherwise false - public bool TryGetPeerById(int id, out NetPeer peer) - { - peer = GetPeerById(id); - - return peer != null; - } - - /// - /// Returns connected peers count - /// - public int ConnectedPeersCount => Interlocked.CompareExchange(ref _connectedPeersCount,0,0); - - public int ExtraPacketSizeForLayer => _extraPacketLayer?.ExtraPacketSizeForLayer ?? 0; - - private bool TryGetPeer(IPEndPoint endPoint, out NetPeer peer) - { - _peersLock.EnterReadLock(); - bool result = _peersDict.TryGetValue(endPoint, out peer); - _peersLock.ExitReadLock(); - return result; - } - - private void AddPeer(NetPeer peer) - { - _peersLock.EnterWriteLock(); - if (_headPeer != null) - { - peer.NextPeer = _headPeer; - _headPeer.PrevPeer = peer; - } - _headPeer = peer; - _peersDict.Add(peer.EndPoint, peer); - if (peer.Id >= _peersArray.Length) - { - int newSize = _peersArray.Length * 2; - while (peer.Id >= newSize) - newSize *= 2; - Array.Resize(ref _peersArray, newSize); - } - _peersArray[peer.Id] = peer; - RegisterEndPoint(peer.EndPoint); - _peersLock.ExitWriteLock(); - } - - private void RemovePeer(NetPeer peer) - { - _peersLock.EnterWriteLock(); - RemovePeer_Internal(peer); - _peersLock.ExitWriteLock(); - } - - private void RemovePeer_Internal(NetPeer peer) - { - if (!_peersDict.Remove(peer.EndPoint)) - return; - if (peer == _headPeer) - _headPeer = peer.NextPeer; - - if (peer.PrevPeer != null) - peer.PrevPeer.NextPeer = peer.NextPeer; - if (peer.NextPeer != null) - peer.NextPeer.PrevPeer = peer.PrevPeer; - peer.PrevPeer = null; - - _peersArray[peer.Id] = null; - _peerIds.Enqueue(peer.Id); - UnregisterEndPoint(peer.EndPoint); - } - - /// - /// NetManager constructor - /// - /// Network events listener (also can implement IDeliveryEventListener) - /// Extra processing of packages, like CRC checksum or encryption. All connected NetManagers must have same layer. - public NetManager(INetEventListener listener, PacketLayerBase extraPacketLayer = null) - { - _netEventListener = listener; - _deliveryEventListener = listener as IDeliveryEventListener; - _ntpEventListener = listener as INtpEventListener; - _peerAddressChangedListener = listener as IPeerAddressChangedListener; - NatPunchModule = new NatPunchModule(this); - _extraPacketLayer = extraPacketLayer; - } - - internal void ConnectionLatencyUpdated(NetPeer fromPeer, int latency) - { - CreateEvent(NetEvent.EType.ConnectionLatencyUpdated, fromPeer, latency: latency); - } - - internal void MessageDelivered(NetPeer fromPeer, object userData) - { - if(_deliveryEventListener != null) - CreateEvent(NetEvent.EType.MessageDelivered, fromPeer, userData: userData); - } - - internal void DisconnectPeerForce(NetPeer peer, - DisconnectReason reason, - SocketError socketErrorCode, - NetPacket eventData) - { - DisconnectPeer(peer, reason, socketErrorCode, true, null, 0, 0, eventData); - } - - private void DisconnectPeer( - NetPeer peer, - DisconnectReason reason, - SocketError socketErrorCode, - bool force, - byte[] data, - int start, - int count, - NetPacket eventData) - { - var shutdownResult = peer.Shutdown(data, start, count, force); - if (shutdownResult == ShutdownResult.None) - return; - if(shutdownResult == ShutdownResult.WasConnected) - Interlocked.Decrement(ref _connectedPeersCount); - CreateEvent( - NetEvent.EType.Disconnect, - peer, - errorCode: socketErrorCode, - disconnectReason: reason, - readerSource: eventData); - } - - private void CreateEvent( - NetEvent.EType type, - NetPeer peer = null, - IPEndPoint remoteEndPoint = null, - SocketError errorCode = 0, - int latency = 0, - DisconnectReason disconnectReason = DisconnectReason.ConnectionFailed, - ConnectionRequest connectionRequest = null, - DeliveryMethod deliveryMethod = DeliveryMethod.Unreliable, - byte channelNumber = 0, - NetPacket readerSource = null, - object userData = null) - { - NetEvent evt; - bool unsyncEvent = UnsyncedEvents; - - if (type == NetEvent.EType.Connect) - Interlocked.Increment(ref _connectedPeersCount); - else if (type == NetEvent.EType.MessageDelivered) - unsyncEvent = UnsyncedDeliveryEvent; - - lock(_eventLock) - { - evt = _netEventPoolHead; - if (evt == null) - evt = new NetEvent(this); - else - _netEventPoolHead = evt.Next; - } - - evt.Type = type; - evt.DataReader.SetSource(readerSource, readerSource?.GetHeaderSize() ?? 0); - evt.Peer = peer; - evt.RemoteEndPoint = remoteEndPoint; - evt.Latency = latency; - evt.ErrorCode = errorCode; - evt.DisconnectReason = disconnectReason; - evt.ConnectionRequest = connectionRequest; - evt.DeliveryMethod = deliveryMethod; - evt.ChannelNumber = channelNumber; - evt.UserData = userData; - - if (unsyncEvent || _manualMode) - { - ProcessEvent(evt); - } - else - { - lock(_netEventsProduceQueue) - _netEventsProduceQueue.Enqueue(evt); - } - } - - private void ProcessEvent(NetEvent evt) - { - NetDebug.Write("[NM] Processing event: " + evt.Type); - bool emptyData = evt.DataReader.IsNull; - switch (evt.Type) - { - case NetEvent.EType.Connect: - _netEventListener.OnPeerConnected(evt.Peer); - break; - case NetEvent.EType.Disconnect: - var info = new DisconnectInfo - { - Reason = evt.DisconnectReason, - AdditionalData = evt.DataReader, - SocketErrorCode = evt.ErrorCode - }; - _netEventListener.OnPeerDisconnected(evt.Peer, info); - break; - case NetEvent.EType.Receive: - _netEventListener.OnNetworkReceive(evt.Peer, evt.DataReader, evt.ChannelNumber, evt.DeliveryMethod); - break; - case NetEvent.EType.ReceiveUnconnected: - _netEventListener.OnNetworkReceiveUnconnected(evt.RemoteEndPoint, evt.DataReader, UnconnectedMessageType.BasicMessage); - break; - case NetEvent.EType.Broadcast: - _netEventListener.OnNetworkReceiveUnconnected(evt.RemoteEndPoint, evt.DataReader, UnconnectedMessageType.Broadcast); - break; - case NetEvent.EType.Error: - _netEventListener.OnNetworkError(evt.RemoteEndPoint, evt.ErrorCode); - break; - case NetEvent.EType.ConnectionLatencyUpdated: - _netEventListener.OnNetworkLatencyUpdate(evt.Peer, evt.Latency); - break; - case NetEvent.EType.ConnectionRequest: - _netEventListener.OnConnectionRequest(evt.ConnectionRequest); - break; - case NetEvent.EType.MessageDelivered: - _deliveryEventListener.OnMessageDelivered(evt.Peer, evt.UserData); - break; - case NetEvent.EType.PeerAddressChanged: - _peersLock.EnterUpgradeableReadLock(); - IPEndPoint previousAddress = null; - if (_peersDict.ContainsKey(evt.Peer.EndPoint)) - { - _peersLock.EnterWriteLock(); - _peersDict.Remove(evt.Peer.EndPoint); - previousAddress = evt.Peer.EndPoint; - evt.Peer.FinishEndPointChange(evt.RemoteEndPoint); - _peersDict.Add(evt.Peer.EndPoint, evt.Peer); - _peersLock.ExitWriteLock(); - } - _peersLock.ExitUpgradeableReadLock(); - if(previousAddress != null) - _peerAddressChangedListener.OnPeerAddressChanged(evt.Peer, previousAddress); - break; - } - //Recycle if not message - if (emptyData) - RecycleEvent(evt); - else if (AutoRecycle) - evt.DataReader.Recycle_Internal(); - } - - internal void RecycleEvent(NetEvent evt) - { - evt.Peer = null; - evt.ErrorCode = 0; - evt.RemoteEndPoint = null; - evt.ConnectionRequest = null; - lock(_eventLock) - { - evt.Next = _netEventPoolHead; - _netEventPoolHead = evt; - } - } - - //Update function - private void UpdateLogic() - { - var peersToRemove = new List(); - var stopwatch = new Stopwatch(); - stopwatch.Start(); - - while (IsRunning) - { - try - { - ProcessDelayedPackets(); - int elapsed = (int)stopwatch.ElapsedMilliseconds; - elapsed = elapsed <= 0 ? 1 : elapsed; - stopwatch.Restart(); - - for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer) - { - if (netPeer.ConnectionState == ConnectionState.Disconnected && - netPeer.TimeSinceLastPacket > DisconnectTimeout) - { - peersToRemove.Add(netPeer); - } - else - { - netPeer.Update(elapsed); - } - } - - if (peersToRemove.Count > 0) - { - _peersLock.EnterWriteLock(); - for (int i = 0; i < peersToRemove.Count; i++) - RemovePeer_Internal(peersToRemove[i]); - _peersLock.ExitWriteLock(); - peersToRemove.Clear(); - } - - ProcessNtpRequests(elapsed); - - int sleepTime = UpdateTime - (int)stopwatch.ElapsedMilliseconds; - if (sleepTime > 0) - _updateTriggerEvent.WaitOne(sleepTime); - } - catch (ThreadAbortException) - { - return; - } - catch (Exception e) - { - NetDebug.WriteError("[NM] LogicThread error: " + e); - } - } - stopwatch.Stop(); - } - - [Conditional("DEBUG")] - private void ProcessDelayedPackets() - { -#if DEBUG - if (!SimulateLatency) - return; - - var time = DateTime.UtcNow; - lock (_pingSimulationList) - { - for (int i = 0; i < _pingSimulationList.Count; i++) - { - var incomingData = _pingSimulationList[i]; - if (incomingData.TimeWhenGet <= time) - { - DebugMessageReceived(incomingData.Data, incomingData.EndPoint); - _pingSimulationList.RemoveAt(i); - i--; - } - } - } -#endif - } - - private void ProcessNtpRequests(int elapsedMilliseconds) - { - List requestsToRemove = null; - foreach (var ntpRequest in _ntpRequests) - { - ntpRequest.Value.Send(_udpSocketv4, elapsedMilliseconds); - if(ntpRequest.Value.NeedToKill) - { - if (requestsToRemove == null) - requestsToRemove = new List(); - requestsToRemove.Add(ntpRequest.Key); - } - } - - if (requestsToRemove != null) - { - foreach (var ipEndPoint in requestsToRemove) - { - _ntpRequests.Remove(ipEndPoint); - } - } - } - - /// - /// Update and send logic. Use this only when NetManager started in manual mode - /// - /// elapsed milliseconds since last update call - public void ManualUpdate(int elapsedMilliseconds) - { - if (!_manualMode) - return; - - for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer) - { - if (netPeer.ConnectionState == ConnectionState.Disconnected && netPeer.TimeSinceLastPacket > DisconnectTimeout) - { - RemovePeer_Internal(netPeer); - } - else - { - netPeer.Update(elapsedMilliseconds); - } - } - ProcessNtpRequests(elapsedMilliseconds); - } - - internal NetPeer OnConnectionSolved(ConnectionRequest request, byte[] rejectData, int start, int length) - { - NetPeer netPeer = null; - - if (request.Result == ConnectionRequestResult.RejectForce) - { - NetDebug.Write(NetLogLevel.Trace, "[NM] Peer connect reject force."); - if (rejectData != null && length > 0) - { - var shutdownPacket = PoolGetWithProperty(PacketProperty.Disconnect, length); - shutdownPacket.ConnectionNumber = request.InternalPacket.ConnectionNumber; - FastBitConverter.GetBytes(shutdownPacket.RawData, 1, request.InternalPacket.ConnectionTime); - if (shutdownPacket.Size >= NetConstants.PossibleMtu[0]) - NetDebug.WriteError("[Peer] Disconnect additional data size more than MTU!"); - else - Buffer.BlockCopy(rejectData, start, shutdownPacket.RawData, 9, length); - SendRawAndRecycle(shutdownPacket, request.RemoteEndPoint); - } - } - else - { - _peersLock.EnterUpgradeableReadLock(); - if (_peersDict.TryGetValue(request.RemoteEndPoint, out netPeer)) - { - //already have peer - _peersLock.ExitUpgradeableReadLock(); - } - else if (request.Result == ConnectionRequestResult.Reject) - { - netPeer = new NetPeer(this, request.RemoteEndPoint, GetNextPeerId()); - netPeer.Reject(request.InternalPacket, rejectData, start, length); - AddPeer(netPeer); - _peersLock.ExitUpgradeableReadLock(); - NetDebug.Write(NetLogLevel.Trace, "[NM] Peer connect reject."); - } - else //Accept - { - netPeer = new NetPeer(this, request, GetNextPeerId()); - AddPeer(netPeer); - _peersLock.ExitUpgradeableReadLock(); - CreateEvent(NetEvent.EType.Connect, netPeer); - NetDebug.Write(NetLogLevel.Trace, "[NM] Received peer connection Id: {0}, EP: {1}", - netPeer.ConnectTime, netPeer.EndPoint); - } - } - - lock(_requestsDict) - _requestsDict.Remove(request.RemoteEndPoint); - - return netPeer; - } - - private int GetNextPeerId() - { - return _peerIds.TryDequeue(out int id) ? id : _lastPeerId++; - } - - private void ProcessConnectRequest( - IPEndPoint remoteEndPoint, - NetPeer netPeer, - NetConnectRequestPacket connRequest) - { - //if we have peer - if (netPeer != null) - { - var processResult = netPeer.ProcessConnectRequest(connRequest); - NetDebug.Write("ConnectRequest LastId: {0}, NewId: {1}, EP: {2}, Result: {3}", - netPeer.ConnectTime, - connRequest.ConnectionTime, - remoteEndPoint, - processResult); - - switch (processResult) - { - case ConnectRequestResult.Reconnection: - DisconnectPeerForce(netPeer, DisconnectReason.Reconnect, 0, null); - RemovePeer(netPeer); - //go to new connection - break; - case ConnectRequestResult.NewConnection: - RemovePeer(netPeer); - //go to new connection - break; - case ConnectRequestResult.P2PLose: - DisconnectPeerForce(netPeer, DisconnectReason.PeerToPeerConnection, 0, null); - RemovePeer(netPeer); - //go to new connection - break; - default: - //no operations needed - return; - } - //ConnectRequestResult.NewConnection - //Set next connection number - if(processResult != ConnectRequestResult.P2PLose) - connRequest.ConnectionNumber = (byte)((netPeer.ConnectionNum + 1) % NetConstants.MaxConnectionNumber); - //To reconnect peer - } - else - { - NetDebug.Write("ConnectRequest Id: {0}, EP: {1}", connRequest.ConnectionTime, remoteEndPoint); - } - - ConnectionRequest req; - lock (_requestsDict) - { - if (_requestsDict.TryGetValue(remoteEndPoint, out req)) - { - req.UpdateRequest(connRequest); - return; - } - req = new ConnectionRequest(remoteEndPoint, connRequest, this); - _requestsDict.Add(remoteEndPoint, req); - } - NetDebug.Write("[NM] Creating request event: " + connRequest.ConnectionTime); - CreateEvent(NetEvent.EType.ConnectionRequest, connectionRequest: req); - } - - private void OnMessageReceived(NetPacket packet, IPEndPoint remoteEndPoint) - { -#if DEBUG - if (SimulatePacketLoss && _randomGenerator.NextDouble() * 100 < SimulationPacketLossChance) - { - //drop packet - return; - } - if (SimulateLatency) - { - int latency = _randomGenerator.Next(SimulationMinLatency, SimulationMaxLatency); - if (latency > MinLatencyThreshold) - { - lock (_pingSimulationList) - { - _pingSimulationList.Add(new IncomingData - { - Data = packet, - EndPoint = remoteEndPoint, - TimeWhenGet = DateTime.UtcNow.AddMilliseconds(latency) - }); - } - //hold packet - return; - } - } - - //ProcessEvents - DebugMessageReceived(packet, remoteEndPoint); - } - - private void DebugMessageReceived(NetPacket packet, IPEndPoint remoteEndPoint) - { -#endif - if (EnableStatistics) - { - Statistics.IncrementPacketsReceived(); - Statistics.AddBytesReceived(packet.Size); - } - - if (_ntpRequests.Count > 0) - { - if (_ntpRequests.TryGetValue(remoteEndPoint, out var request)) - { - if (packet.Size < 48) - { - NetDebug.Write(NetLogLevel.Trace, "NTP response too short: {}", packet.Size); - return; - } - - byte[] copiedData = new byte[packet.Size]; - Buffer.BlockCopy(packet.RawData, 0, copiedData, 0, packet.Size); - NtpPacket ntpPacket = NtpPacket.FromServerResponse(copiedData, DateTime.UtcNow); - try - { - ntpPacket.ValidateReply(); - } - catch (InvalidOperationException ex) - { - NetDebug.Write(NetLogLevel.Trace, "NTP response error: {}", ex.Message); - ntpPacket = null; - } - - if (ntpPacket != null) - { - _ntpRequests.Remove(remoteEndPoint); - _ntpEventListener?.OnNtpResponse(ntpPacket); - } - return; - } - } - - if (_extraPacketLayer != null) - { - int start = 0; - _extraPacketLayer.ProcessInboundPacket(ref remoteEndPoint, ref packet.RawData, ref start, ref packet.Size); - if (packet.Size == 0) - return; - } - - if (!packet.Verify()) - { - NetDebug.WriteError("[NM] DataReceived: bad!"); - PoolRecycle(packet); - return; - } - - switch (packet.Property) - { - //special case connect request - case PacketProperty.ConnectRequest: - if (NetConnectRequestPacket.GetProtocolId(packet) != NetConstants.ProtocolId) - { - SendRawAndRecycle(PoolGetWithProperty(PacketProperty.InvalidProtocol), remoteEndPoint); - return; - } - break; - //unconnected messages - case PacketProperty.Broadcast: - if (!BroadcastReceiveEnabled) - return; - CreateEvent(NetEvent.EType.Broadcast, remoteEndPoint: remoteEndPoint, readerSource: packet); - return; - case PacketProperty.UnconnectedMessage: - if (!UnconnectedMessagesEnabled) - return; - CreateEvent(NetEvent.EType.ReceiveUnconnected, remoteEndPoint: remoteEndPoint, readerSource: packet); - return; - case PacketProperty.NatMessage: - if (NatPunchEnabled) - NatPunchModule.ProcessMessage(remoteEndPoint, packet); - return; - } - - //Check normal packets - _peersLock.EnterReadLock(); - bool peerFound = _peersDict.TryGetValue(remoteEndPoint, out var netPeer); - _peersLock.ExitReadLock(); - - switch (packet.Property) - { - case PacketProperty.ConnectRequest: - var connRequest = NetConnectRequestPacket.FromData(packet); - if (connRequest != null) - ProcessConnectRequest(remoteEndPoint, netPeer, connRequest); - break; - case PacketProperty.PeerNotFound: - if (peerFound) //local - { - if (netPeer.ConnectionState != ConnectionState.Connected) - return; - if (packet.Size == 1) - { - //first reply - //send NetworkChanged packet - netPeer.ResetMtu(); - SendRaw(NetConnectAcceptPacket.MakeNetworkChanged(netPeer), remoteEndPoint); - NetDebug.Write($"PeerNotFound sending connection info: {remoteEndPoint}"); - } - else if (packet.Size == 2 && packet.RawData[1] == 1) - { - //second reply - DisconnectPeerForce(netPeer, DisconnectReason.PeerNotFound, 0, null); - } - } - else if (packet.Size > 1) //remote - { - //check if this is old peer - bool isOldPeer = false; - - if (AllowPeerAddressChange) - { - NetDebug.Write($"[NM] Looks like address change: {packet.Size}"); - var remoteData = NetConnectAcceptPacket.FromData(packet); - if (remoteData != null && - remoteData.PeerNetworkChanged && - remoteData.PeerId < _peersArray.Length) - { - _peersLock.EnterUpgradeableReadLock(); - var peer = _peersArray[remoteData.PeerId]; - if (peer != null && - peer.ConnectTime == remoteData.ConnectionTime && - peer.ConnectionNum == remoteData.ConnectionNumber) - { - if (peer.ConnectionState == ConnectionState.Connected) - { - peer.InitiateEndPointChange(); - if (_peerAddressChangedListener != null) - { - CreateEvent(NetEvent.EType.PeerAddressChanged, peer, remoteEndPoint); - } - NetDebug.Write("[NM] PeerNotFound change address of remote peer"); - } - isOldPeer = true; - } - _peersLock.ExitUpgradeableReadLock(); - } - } - - PoolRecycle(packet); - - //else peer really not found - if (!isOldPeer) - { - var secondResponse = PoolGetWithProperty(PacketProperty.PeerNotFound, 1); - secondResponse.RawData[1] = 1; - SendRawAndRecycle(secondResponse, remoteEndPoint); - } - } - break; - case PacketProperty.InvalidProtocol: - if (peerFound && netPeer.ConnectionState == ConnectionState.Outgoing) - DisconnectPeerForce(netPeer, DisconnectReason.InvalidProtocol, 0, null); - break; - case PacketProperty.Disconnect: - if (peerFound) - { - var disconnectResult = netPeer.ProcessDisconnect(packet); - if (disconnectResult == DisconnectResult.None) - { - PoolRecycle(packet); - return; - } - DisconnectPeerForce( - netPeer, - disconnectResult == DisconnectResult.Disconnect - ? DisconnectReason.RemoteConnectionClose - : DisconnectReason.ConnectionRejected, - 0, packet); - } - else - { - PoolRecycle(packet); - } - //Send shutdown - SendRawAndRecycle(PoolGetWithProperty(PacketProperty.ShutdownOk), remoteEndPoint); - break; - case PacketProperty.ConnectAccept: - if (!peerFound) - return; - var connAccept = NetConnectAcceptPacket.FromData(packet); - if (connAccept != null && netPeer.ProcessConnectAccept(connAccept)) - CreateEvent(NetEvent.EType.Connect, netPeer); - break; - default: - if(peerFound) - netPeer.ProcessPacket(packet); - else - SendRawAndRecycle(PoolGetWithProperty(PacketProperty.PeerNotFound), remoteEndPoint); - break; - } - } - - internal void CreateReceiveEvent(NetPacket packet, DeliveryMethod method, byte channelNumber, int headerSize, NetPeer fromPeer) - { - NetEvent evt; - lock (_eventLock) - { - evt = _netEventPoolHead; - if (evt == null) - evt = new NetEvent(this); - else - _netEventPoolHead = evt.Next; - } - evt.Type = NetEvent.EType.Receive; - evt.DataReader.SetSource(packet, headerSize); - evt.Peer = fromPeer; - evt.DeliveryMethod = method; - evt.ChannelNumber = channelNumber; - if (UnsyncedEvents || UnsyncedReceiveEvent || _manualMode) - { - ProcessEvent(evt); - } - else - { - lock(_netEventsProduceQueue) - _netEventsProduceQueue.Enqueue(evt); - } - } - - /// - /// Send data to all connected peers (channel - 0) - /// - /// DataWriter with data - /// Send options (reliable, unreliable, etc.) - public void SendToAll(NetDataWriter writer, DeliveryMethod options) - { - SendToAll(writer.Data, 0, writer.Length, options); - } - - /// - /// Send data to all connected peers (channel - 0) - /// - /// Data - /// Send options (reliable, unreliable, etc.) - public void SendToAll(byte[] data, DeliveryMethod options) - { - SendToAll(data, 0, data.Length, options); - } - - /// - /// Send data to all connected peers (channel - 0) - /// - /// Data - /// Start of data - /// Length of data - /// Send options (reliable, unreliable, etc.) - public void SendToAll(byte[] data, int start, int length, DeliveryMethod options) - { - SendToAll(data, start, length, 0, options); - } - - /// - /// Send data to all connected peers - /// - /// DataWriter with data - /// Number of channel (from 0 to channelsCount - 1) - /// Send options (reliable, unreliable, etc.) - public void SendToAll(NetDataWriter writer, byte channelNumber, DeliveryMethod options) - { - SendToAll(writer.Data, 0, writer.Length, channelNumber, options); - } - - /// - /// Send data to all connected peers - /// - /// Data - /// Number of channel (from 0 to channelsCount - 1) - /// Send options (reliable, unreliable, etc.) - public void SendToAll(byte[] data, byte channelNumber, DeliveryMethod options) - { - SendToAll(data, 0, data.Length, channelNumber, options); - } - - /// - /// Send data to all connected peers - /// - /// Data - /// Start of data - /// Length of data - /// Number of channel (from 0 to channelsCount - 1) - /// Send options (reliable, unreliable, etc.) - public void SendToAll(byte[] data, int start, int length, byte channelNumber, DeliveryMethod options) - { - try - { - _peersLock.EnterReadLock(); - for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer) - netPeer.Send(data, start, length, channelNumber, options); - } - finally - { - _peersLock.ExitReadLock(); - } - } - - /// - /// Send data to all connected peers (channel - 0) - /// - /// DataWriter with data - /// Send options (reliable, unreliable, etc.) - /// Excluded peer - public void SendToAll(NetDataWriter writer, DeliveryMethod options, NetPeer excludePeer) - { - SendToAll(writer.Data, 0, writer.Length, 0, options, excludePeer); - } - - /// - /// Send data to all connected peers (channel - 0) - /// - /// Data - /// Send options (reliable, unreliable, etc.) - /// Excluded peer - public void SendToAll(byte[] data, DeliveryMethod options, NetPeer excludePeer) - { - SendToAll(data, 0, data.Length, 0, options, excludePeer); - } - - /// - /// Send data to all connected peers (channel - 0) - /// - /// Data - /// Start of data - /// Length of data - /// Send options (reliable, unreliable, etc.) - /// Excluded peer - public void SendToAll(byte[] data, int start, int length, DeliveryMethod options, NetPeer excludePeer) - { - SendToAll(data, start, length, 0, options, excludePeer); - } - - /// - /// Send data to all connected peers - /// - /// DataWriter with data - /// Number of channel (from 0 to channelsCount - 1) - /// Send options (reliable, unreliable, etc.) - /// Excluded peer - public void SendToAll(NetDataWriter writer, byte channelNumber, DeliveryMethod options, NetPeer excludePeer) - { - SendToAll(writer.Data, 0, writer.Length, channelNumber, options, excludePeer); - } - - /// - /// Send data to all connected peers - /// - /// Data - /// Number of channel (from 0 to channelsCount - 1) - /// Send options (reliable, unreliable, etc.) - /// Excluded peer - public void SendToAll(byte[] data, byte channelNumber, DeliveryMethod options, NetPeer excludePeer) - { - SendToAll(data, 0, data.Length, channelNumber, options, excludePeer); - } - - - /// - /// Send data to all connected peers - /// - /// Data - /// Start of data - /// Length of data - /// Number of channel (from 0 to channelsCount - 1) - /// Send options (reliable, unreliable, etc.) - /// Excluded peer - public void SendToAll(byte[] data, int start, int length, byte channelNumber, DeliveryMethod options, NetPeer excludePeer) - { - try - { - _peersLock.EnterReadLock(); - for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer) - { - if (netPeer != excludePeer) - netPeer.Send(data, start, length, channelNumber, options); - } - } - finally - { - _peersLock.ExitReadLock(); - } - } - - /// - /// Start logic thread and listening on available port - /// - public bool Start() - { - return Start(0); - } - - /// - /// Start logic thread and listening on selected port - /// - /// bind to specific ipv4 address - /// bind to specific ipv6 address - /// port to listen - public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port) - { - return Start(addressIPv4, addressIPv6, port, false); - } - - /// - /// Start logic thread and listening on selected port - /// - /// bind to specific ipv4 address - /// bind to specific ipv6 address - /// port to listen - public bool Start(string addressIPv4, string addressIPv6, int port) - { - IPAddress ipv4 = NetUtils.ResolveAddress(addressIPv4); - IPAddress ipv6 = NetUtils.ResolveAddress(addressIPv6); - return Start(ipv4, ipv6, port); - } - - /// - /// Start logic thread and listening on selected port - /// - /// port to listen - public bool Start(int port) - { - return Start(IPAddress.Any, IPAddress.IPv6Any, port); - } - - /// - /// Start in manual mode and listening on selected port - /// In this mode you should use ManualReceive (without PollEvents) for receive packets - /// and ManualUpdate(...) for update and send packets - /// This mode useful mostly for single-threaded servers - /// - /// bind to specific ipv4 address - /// bind to specific ipv6 address - /// port to listen - public bool StartInManualMode(IPAddress addressIPv4, IPAddress addressIPv6, int port) - { - return Start(addressIPv4, addressIPv6, port, true); - } - - /// - /// Start in manual mode and listening on selected port - /// In this mode you should use ManualReceive (without PollEvents) for receive packets - /// and ManualUpdate(...) for update and send packets - /// This mode useful mostly for single-threaded servers - /// - /// bind to specific ipv4 address - /// bind to specific ipv6 address - /// port to listen - public bool StartInManualMode(string addressIPv4, string addressIPv6, int port) - { - IPAddress ipv4 = NetUtils.ResolveAddress(addressIPv4); - IPAddress ipv6 = NetUtils.ResolveAddress(addressIPv6); - return StartInManualMode(ipv4, ipv6, port); - } - - /// - /// Start in manual mode and listening on selected port - /// In this mode you should use ManualReceive (without PollEvents) for receive packets - /// and ManualUpdate(...) for update and send packets - /// This mode useful mostly for single-threaded servers - /// - /// port to listen - public bool StartInManualMode(int port) - { - return StartInManualMode(IPAddress.Any, IPAddress.IPv6Any, port); - } - - /// - /// Send message without connection - /// - /// Raw data - /// Packet destination - /// Operation result - public bool SendUnconnectedMessage(byte[] message, IPEndPoint remoteEndPoint) - { - return SendUnconnectedMessage(message, 0, message.Length, remoteEndPoint); - } - - /// - /// Send message without connection. WARNING This method allocates a new IPEndPoint object and - /// synchronously makes a DNS request. If you're calling this method every frame it will be - /// much faster to just cache the IPEndPoint. - /// - /// Data serializer - /// Packet destination IP or hostname - /// Packet destination port - /// Operation result - public bool SendUnconnectedMessage(NetDataWriter writer, string address, int port) - { - IPEndPoint remoteEndPoint = NetUtils.MakeEndPoint(address, port); - - return SendUnconnectedMessage(writer.Data, 0, writer.Length, remoteEndPoint); - } - - /// - /// Send message without connection - /// - /// Data serializer - /// Packet destination - /// Operation result - public bool SendUnconnectedMessage(NetDataWriter writer, IPEndPoint remoteEndPoint) - { - return SendUnconnectedMessage(writer.Data, 0, writer.Length, remoteEndPoint); - } - - /// - /// Send message without connection - /// - /// Raw data - /// data start - /// data length - /// Packet destination - /// Operation result - public bool SendUnconnectedMessage(byte[] message, int start, int length, IPEndPoint remoteEndPoint) - { - //No need for CRC here, SendRaw does that - NetPacket packet = PoolGetWithData(PacketProperty.UnconnectedMessage, message, start, length); - return SendRawAndRecycle(packet, remoteEndPoint) > 0; - } - - /// - /// Triggers update and send logic immediately (works asynchronously) - /// - public void TriggerUpdate() - { - _updateTriggerEvent.Set(); - } - - /// - /// Receive all pending events. Call this in game update code - /// In Manual mode it will call also socket Receive (which can be slow) - /// - public void PollEvents() - { - if (_manualMode) - { - if (_udpSocketv4 != null) - ManualReceive(_udpSocketv4, _bufferEndPointv4); - if (_udpSocketv6 != null && _udpSocketv6 != _udpSocketv4) - ManualReceive(_udpSocketv6, _bufferEndPointv6); - ProcessDelayedPackets(); - return; - } - if (UnsyncedEvents) - return; - lock (_netEventsProduceQueue) - { - (_netEventsConsumeQueue, _netEventsProduceQueue) = (_netEventsProduceQueue, _netEventsConsumeQueue); - } - - while(_netEventsConsumeQueue.Count > 0) - ProcessEvent(_netEventsConsumeQueue.Dequeue()); - } - - /// - /// Connect to remote host - /// - /// Server IP or hostname - /// Server Port - /// Connection key - /// New NetPeer if new connection, Old NetPeer if already connected, null peer if there is ConnectionRequest awaiting - /// Manager is not running. Call - public NetPeer Connect(string address, int port, string key) - { - return Connect(address, port, NetDataWriter.FromString(key)); - } - - /// - /// Connect to remote host - /// - /// Server IP or hostname - /// Server Port - /// Additional data for remote peer - /// New NetPeer if new connection, Old NetPeer if already connected, null peer if there is ConnectionRequest awaiting - /// Manager is not running. Call - public NetPeer Connect(string address, int port, NetDataWriter connectionData) - { - IPEndPoint ep; - try - { - ep = NetUtils.MakeEndPoint(address, port); - } - catch - { - CreateEvent(NetEvent.EType.Disconnect, disconnectReason: DisconnectReason.UnknownHost); - return null; - } - return Connect(ep, connectionData); - } - - /// - /// Connect to remote host - /// - /// Server end point (ip and port) - /// Connection key - /// New NetPeer if new connection, Old NetPeer if already connected, null peer if there is ConnectionRequest awaiting - /// Manager is not running. Call - public NetPeer Connect(IPEndPoint target, string key) - { - return Connect(target, NetDataWriter.FromString(key)); - } - - public bool IsClient { get; private set; } - /// - /// Connect to remote host - /// - /// Server end point (ip and port) - /// Additional data for remote peer - /// New NetPeer if new connection, Old NetPeer if already connected, null peer if there is ConnectionRequest awaiting - /// Manager is not running. Call - public NetPeer Connect(IPEndPoint target, NetDataWriter connectionData) - { - if (!IsRunning) - throw new InvalidOperationException("Client is not running"); - - lock(_requestsDict) - { - if (_requestsDict.ContainsKey(target)) - return null; - } - - byte connectionNumber = 0; - _peersLock.EnterUpgradeableReadLock(); - if (_peersDict.TryGetValue(target, out var peer)) - { - switch (peer.ConnectionState) - { - //just return already connected peer - case ConnectionState.Connected: - case ConnectionState.Outgoing: - _peersLock.ExitUpgradeableReadLock(); - return peer; - } - //else reconnect - connectionNumber = (byte)((peer.ConnectionNum + 1) % NetConstants.MaxConnectionNumber); - RemovePeer(peer); - } - - //Create reliable connection - //And send connection request - peer = new NetPeer(this, target, GetNextPeerId(), connectionNumber, connectionData); - AddPeer(peer); - _peersLock.ExitUpgradeableReadLock(); - IsClient = true; - - return peer; - } - - /// - /// Force closes connection and stop all threads. - /// - public void Stop() - { - Stop(true); - } - - /// - /// Force closes connection and stop all threads. - /// - /// Send disconnect messages - public void Stop(bool sendDisconnectMessages) - { - if (!IsRunning) - return; - NetDebug.Write("[NM] Stop"); - - IsClient = false; - //Send last disconnect - for(var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer) - netPeer.Shutdown(null, 0, 0, !sendDisconnectMessages); - - //Stop - CloseSocket(false); - _updateTriggerEvent.Set(); - if (!_manualMode) - { - _logicThread.Join(); - _logicThread = null; - } - - //clear peers - _peersLock.EnterWriteLock(); - _headPeer = null; - _peersDict.Clear(); - _peersArray = new NetPeer[32]; - _peersLock.ExitWriteLock(); - _peerIds = new ConcurrentQueue(); - _lastPeerId = 0; -#if DEBUG - lock (_pingSimulationList) - _pingSimulationList.Clear(); -#endif - _connectedPeersCount = 0; - _netEventsProduceQueue.Clear(); - _netEventsConsumeQueue.Clear(); - } - - /// - /// Return peers count with connection state - /// - /// peer connection state (you can use as bit flags) - /// peers count - public int GetPeersCount(ConnectionState peerState) - { - int count = 0; - _peersLock.EnterReadLock(); - for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer) - { - if ((netPeer.ConnectionState & peerState) != 0) - count++; - } - _peersLock.ExitReadLock(); - return count; - } - - /// - /// Get copy of peers (without allocations) - /// - /// List that will contain result - /// State of peers - public void GetPeersNonAlloc(List peers, ConnectionState peerState) - { - peers.Clear(); - _peersLock.EnterReadLock(); - for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer) - { - if ((netPeer.ConnectionState & peerState) != 0) - peers.Add(netPeer); - } - _peersLock.ExitReadLock(); - } - - /// - /// Disconnect all peers without any additional data - /// - public void DisconnectAll() - { - DisconnectAll(null, 0, 0); - } - - /// - /// Disconnect all peers with shutdown message - /// - /// Data to send (must be less or equal MTU) - /// Data start - /// Data count - public void DisconnectAll(byte[] data, int start, int count) - { - //Send disconnect packets - _peersLock.EnterReadLock(); - for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer) - { - DisconnectPeer( - netPeer, - DisconnectReason.DisconnectPeerCalled, - 0, - false, - data, - start, - count, - null); - } - _peersLock.ExitReadLock(); - } - - /// - /// Immediately disconnect peer from server without additional data - /// - /// peer to disconnect - public void DisconnectPeerForce(NetPeer peer) - { - DisconnectPeerForce(peer, DisconnectReason.DisconnectPeerCalled, 0, null); - } - - /// - /// Disconnect peer from server - /// - /// peer to disconnect - public void DisconnectPeer(NetPeer peer) - { - DisconnectPeer(peer, null, 0, 0); - } - - /// - /// Disconnect peer from server and send additional data (Size must be less or equal MTU - 8) - /// - /// peer to disconnect - /// additional data - public void DisconnectPeer(NetPeer peer, byte[] data) - { - DisconnectPeer(peer, data, 0, data.Length); - } - - /// - /// Disconnect peer from server and send additional data (Size must be less or equal MTU - 8) - /// - /// peer to disconnect - /// additional data - public void DisconnectPeer(NetPeer peer, NetDataWriter writer) - { - DisconnectPeer(peer, writer.Data, 0, writer.Length); - } - - /// - /// Disconnect peer from server and send additional data (Size must be less or equal MTU - 8) - /// - /// peer to disconnect - /// additional data - /// data start - /// data length - public void DisconnectPeer(NetPeer peer, byte[] data, int start, int count) - { - DisconnectPeer( - peer, - DisconnectReason.DisconnectPeerCalled, - 0, - false, - data, - start, - count, - null); - } - - /// - /// Create the requests for NTP server - /// - /// NTP Server address. - public void CreateNtpRequest(IPEndPoint endPoint) - { - _ntpRequests.Add(endPoint, new NtpRequest(endPoint)); - } - - /// - /// Create the requests for NTP server - /// - /// NTP Server address. - /// port - public void CreateNtpRequest(string ntpServerAddress, int port) - { - IPEndPoint endPoint = NetUtils.MakeEndPoint(ntpServerAddress, port); - _ntpRequests.Add(endPoint, new NtpRequest(endPoint)); - } - - /// - /// Create the requests for NTP server (default port) - /// - /// NTP Server address. - public void CreateNtpRequest(string ntpServerAddress) - { - IPEndPoint endPoint = NetUtils.MakeEndPoint(ntpServerAddress, NtpRequest.DefaultPort); - _ntpRequests.Add(endPoint, new NtpRequest(endPoint)); - } - - public NetPeerEnumerator GetEnumerator() - { - return new NetPeerEnumerator(_headPeer); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return new NetPeerEnumerator(_headPeer); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return new NetPeerEnumerator(_headPeer); - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.cs.meta deleted file mode 100644 index 673e75f..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 37d95580df7122c44b9333cd3ab77732 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPacket.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPacket.cs deleted file mode 100644 index 7e29fe9..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPacket.cs +++ /dev/null @@ -1,161 +0,0 @@ -using System; -using System.Net; -using LiteNetLib.Utils; - -namespace LiteNetLib -{ - internal enum PacketProperty : byte - { - Unreliable, - Channeled, - Ack, - Ping, - Pong, - ConnectRequest, - ConnectAccept, - Disconnect, - UnconnectedMessage, - MtuCheck, - MtuOk, - Broadcast, - Merged, - ShutdownOk, - PeerNotFound, - InvalidProtocol, - NatMessage, - Empty - } - - internal sealed class NetPacket - { - private static readonly int PropertiesCount = Enum.GetValues(typeof(PacketProperty)).Length; - private static readonly int[] HeaderSizes; - - static NetPacket() - { - HeaderSizes = NetUtils.AllocatePinnedUninitializedArray(PropertiesCount); - for (int i = 0; i < HeaderSizes.Length; i++) - { - switch ((PacketProperty)i) - { - case PacketProperty.Channeled: - case PacketProperty.Ack: - HeaderSizes[i] = NetConstants.ChanneledHeaderSize; - break; - case PacketProperty.Ping: - HeaderSizes[i] = NetConstants.HeaderSize + 2; - break; - case PacketProperty.ConnectRequest: - HeaderSizes[i] = NetConnectRequestPacket.HeaderSize; - break; - case PacketProperty.ConnectAccept: - HeaderSizes[i] = NetConnectAcceptPacket.Size; - break; - case PacketProperty.Disconnect: - HeaderSizes[i] = NetConstants.HeaderSize + 8; - break; - case PacketProperty.Pong: - HeaderSizes[i] = NetConstants.HeaderSize + 10; - break; - default: - HeaderSizes[i] = NetConstants.HeaderSize; - break; - } - } - } - - //Header - public PacketProperty Property - { - get => (PacketProperty)(RawData[0] & 0x1F); - set => RawData[0] = (byte)((RawData[0] & 0xE0) | (byte)value); - } - - public byte ConnectionNumber - { - get => (byte)((RawData[0] & 0x60) >> 5); - set => RawData[0] = (byte) ((RawData[0] & 0x9F) | (value << 5)); - } - - public ushort Sequence - { - get => BitConverter.ToUInt16(RawData, 1); - set => FastBitConverter.GetBytes(RawData, 1, value); - } - - public bool IsFragmented => (RawData[0] & 0x80) != 0; - - public void MarkFragmented() - { - RawData[0] |= 0x80; //set first bit - } - - public byte ChannelId - { - get => RawData[3]; - set => RawData[3] = value; - } - - public ushort FragmentId - { - get => BitConverter.ToUInt16(RawData, 4); - set => FastBitConverter.GetBytes(RawData, 4, value); - } - - public ushort FragmentPart - { - get => BitConverter.ToUInt16(RawData, 6); - set => FastBitConverter.GetBytes(RawData, 6, value); - } - - public ushort FragmentsTotal - { - get => BitConverter.ToUInt16(RawData, 8); - set => FastBitConverter.GetBytes(RawData, 8, value); - } - - //Data - public byte[] RawData; - public int Size; - - //Delivery - public object UserData; - - //Pool node - public NetPacket Next; - - public NetPacket(int size) - { - RawData = new byte[size]; - Size = size; - } - - public NetPacket(PacketProperty property, int size) - { - size += GetHeaderSize(property); - RawData = new byte[size]; - Property = property; - Size = size; - } - - public static int GetHeaderSize(PacketProperty property) - { - return HeaderSizes[(int)property]; - } - - public int GetHeaderSize() - { - return HeaderSizes[RawData[0] & 0x1F]; - } - - public bool Verify() - { - byte property = (byte)(RawData[0] & 0x1F); - if (property >= PropertiesCount) - return false; - int headerSize = HeaderSizes[property]; - bool fragmented = (RawData[0] & 0x80) != 0; - return Size >= headerSize && (!fragmented || Size >= headerSize + NetConstants.FragmentHeaderSize); - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPacket.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPacket.cs.meta deleted file mode 100644 index 02838af..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPacket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e7ddd322169be074f870f73db1a55255 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPeer.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPeer.cs deleted file mode 100644 index 0ebf508..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPeer.cs +++ /dev/null @@ -1,1405 +0,0 @@ -#if DEBUG -#define STATS_ENABLED -#endif -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Net; -using System.Threading; -using LiteNetLib.Utils; - -namespace LiteNetLib -{ - /// - /// Peer connection state - /// - [Flags] - public enum ConnectionState : byte - { - Outgoing = 1 << 1, - Connected = 1 << 2, - ShutdownRequested = 1 << 3, - Disconnected = 1 << 4, - EndPointChange = 1 << 5, - Any = Outgoing | Connected | ShutdownRequested | EndPointChange - } - - internal enum ConnectRequestResult - { - None, - P2PLose, //when peer connecting - Reconnection, //when peer was connected - NewConnection //when peer was disconnected - } - - internal enum DisconnectResult - { - None, - Reject, - Disconnect - } - - internal enum ShutdownResult - { - None, - Success, - WasConnected - } - - /// - /// Network peer. Main purpose is sending messages to specific peer. - /// - public class NetPeer - { - //Ping and RTT - private int _rtt; - private int _avgRtt; - private int _rttCount; - private double _resendDelay = 27.0; - private int _pingSendTimer; - private int _rttResetTimer; - private readonly Stopwatch _pingTimer = new Stopwatch(); - private int _timeSinceLastPacket; - private long _remoteDelta; - - //Common - private readonly object _shutdownLock = new object(); - - internal volatile NetPeer NextPeer; - internal NetPeer PrevPeer; - - internal byte ConnectionNum - { - get => _connectNum; - private set - { - _connectNum = value; - _mergeData.ConnectionNumber = value; - _pingPacket.ConnectionNumber = value; - _pongPacket.ConnectionNumber = value; - } - } - - //Channels - private readonly Queue _unreliableChannel; - private readonly ConcurrentQueue _channelSendQueue; - private readonly BaseChannel[] _channels; - - //MTU - private int _mtu; - private int _mtuIdx; - private bool _finishMtu; - private int _mtuCheckTimer; - private int _mtuCheckAttempts; - private const int MtuCheckDelay = 1000; - private const int MaxMtuCheckAttempts = 4; - private readonly object _mtuMutex = new object(); - - //Fragment - private class IncomingFragments - { - public NetPacket[] Fragments; - public int ReceivedCount; - public int TotalSize; - public byte ChannelId; - } - private int _fragmentId; - private readonly Dictionary _holdedFragments; - private readonly Dictionary _deliveredFragments; - - //Merging - private readonly NetPacket _mergeData; - private int _mergePos; - private int _mergeCount; - - //Connection - private IPEndPoint _remoteEndPoint; - private int _connectAttempts; - private int _connectTimer; - private long _connectTime; - private byte _connectNum; - private ConnectionState _connectionState; - private NetPacket _shutdownPacket; - private const int ShutdownDelay = 300; - private int _shutdownTimer; - private readonly NetPacket _pingPacket; - private readonly NetPacket _pongPacket; - private readonly NetPacket _connectRequestPacket; - private readonly NetPacket _connectAcceptPacket; - - /// - /// Peer ip address and port - /// - public IPEndPoint EndPoint => _remoteEndPoint; - - /// - /// Peer parent NetManager - /// - public readonly NetManager NetManager; - - /// - /// Current connection state - /// - public ConnectionState ConnectionState => _connectionState; - - /// - /// Connection time for internal purposes - /// - internal long ConnectTime => _connectTime; - - /// - /// Peer id can be used as key in your dictionary of peers - /// - public readonly int Id; - - /// - /// Id assigned from server - /// - public int RemoteId { get; private set; } - - /// - /// Current one-way ping (RTT/2) in milliseconds - /// - public int Ping => _avgRtt/2; - - /// - /// Round trip time in milliseconds - /// - public int RoundTripTime => _avgRtt; - - /// - /// Current MTU - Maximum Transfer Unit ( maximum udp packet size without fragmentation ) - /// - public int Mtu => _mtu; - - /// - /// Delta with remote time in ticks (not accurate) - /// positive - remote time > our time - /// - public long RemoteTimeDelta => _remoteDelta; - - /// - /// Remote UTC time (not accurate) - /// - public DateTime RemoteUtcTime => new DateTime(DateTime.UtcNow.Ticks + _remoteDelta); - - /// - /// Time since last packet received (including internal library packets) - /// - public int TimeSinceLastPacket => _timeSinceLastPacket; - - internal double ResendDelay => _resendDelay; - - /// - /// Application defined object containing data about the connection - /// - public object Tag; - - /// - /// Statistics of peer connection - /// - public readonly NetStatistics Statistics; - - //incoming connection constructor - internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id) - { - Id = id; - Statistics = new NetStatistics(); - NetManager = netManager; - ResetMtu(); - _remoteEndPoint = remoteEndPoint; - _connectionState = ConnectionState.Connected; - _mergeData = new NetPacket(PacketProperty.Merged, NetConstants.MaxPacketSize); - _pongPacket = new NetPacket(PacketProperty.Pong, 0); - _pingPacket = new NetPacket(PacketProperty.Ping, 0) {Sequence = 1}; - - _unreliableChannel = new Queue(); - _holdedFragments = new Dictionary(); - _deliveredFragments = new Dictionary(); - - _channels = new BaseChannel[netManager.ChannelsCount * NetConstants.ChannelTypeCount]; - _channelSendQueue = new ConcurrentQueue(); - } - - internal void InitiateEndPointChange() - { - ResetMtu(); - _connectionState = ConnectionState.EndPointChange; - } - - internal void FinishEndPointChange(IPEndPoint newEndPoint) - { - if (_connectionState != ConnectionState.EndPointChange) - return; - _connectionState = ConnectionState.Connected; - _remoteEndPoint = newEndPoint; - } - - internal void ResetMtu() - { - _finishMtu = false; - if (NetManager.MtuOverride > 0) - OverrideMtu(NetManager.MtuOverride); - else if (NetManager.UseSafeMtu) - SetMtu(0); - else - SetMtu(1); - } - - private void SetMtu(int mtuIdx) - { - _mtuIdx = mtuIdx; - _mtu = NetConstants.PossibleMtu[mtuIdx] - NetManager.ExtraPacketSizeForLayer; - } - - private void OverrideMtu(int mtuValue) - { - _mtu = mtuValue; - _finishMtu = true; - } - - /// - /// Returns packets count in queue for reliable channel - /// - /// number of channel 0-63 - /// type of channel ReliableOrdered or ReliableUnordered - /// packets count in channel queue - public int GetPacketsCountInReliableQueue(byte channelNumber, bool ordered) - { - int idx = channelNumber * NetConstants.ChannelTypeCount + - (byte) (ordered ? DeliveryMethod.ReliableOrdered : DeliveryMethod.ReliableUnordered); - var channel = _channels[idx]; - return channel != null ? ((ReliableChannel)channel).PacketsInQueue : 0; - } - - /// - /// Create temporary packet (maximum size MTU - headerSize) to send later without additional copies - /// - /// Delivery method (reliable, unreliable, etc.) - /// Number of channel (from 0 to channelsCount - 1) - /// PooledPacket that you can use to write data starting from UserDataOffset - public PooledPacket CreatePacketFromPool(DeliveryMethod deliveryMethod, byte channelNumber) - { - //multithreaded variable - int mtu = _mtu; - var packet = NetManager.PoolGetPacket(mtu); - if (deliveryMethod == DeliveryMethod.Unreliable) - { - packet.Property = PacketProperty.Unreliable; - return new PooledPacket(packet, mtu, 0); - } - else - { - packet.Property = PacketProperty.Channeled; - return new PooledPacket(packet, mtu, (byte)(channelNumber * NetConstants.ChannelTypeCount + (byte)deliveryMethod)); - } - } - - /// - /// Sends pooled packet without data copy - /// - /// packet to send - /// size of user data you want to send - public void SendPooledPacket(PooledPacket packet, int userDataSize) - { - if (_connectionState != ConnectionState.Connected) - return; - packet._packet.Size = packet.UserDataOffset + userDataSize; - if (packet._packet.Property == PacketProperty.Channeled) - { - CreateChannel(packet._channelNumber).AddToQueue(packet._packet); - } - else - { - lock(_unreliableChannel) - _unreliableChannel.Enqueue(packet._packet); - } - } - - private BaseChannel CreateChannel(byte idx) - { - BaseChannel newChannel = _channels[idx]; - if (newChannel != null) - return newChannel; - switch ((DeliveryMethod)(idx % NetConstants.ChannelTypeCount)) - { - case DeliveryMethod.ReliableUnordered: - newChannel = new ReliableChannel(this, false, idx); - break; - case DeliveryMethod.Sequenced: - newChannel = new SequencedChannel(this, false, idx); - break; - case DeliveryMethod.ReliableOrdered: - newChannel = new ReliableChannel(this, true, idx); - break; - case DeliveryMethod.ReliableSequenced: - newChannel = new SequencedChannel(this, true, idx); - break; - } - BaseChannel prevChannel = Interlocked.CompareExchange(ref _channels[idx], newChannel, null); - if (prevChannel != null) - return prevChannel; - - return newChannel; - } - - //"Connect to" constructor - internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id, byte connectNum, NetDataWriter connectData) - : this(netManager, remoteEndPoint, id) - { - _connectTime = DateTime.UtcNow.Ticks; - _connectionState = ConnectionState.Outgoing; - ConnectionNum = connectNum; - - //Make initial packet - _connectRequestPacket = NetConnectRequestPacket.Make(connectData, remoteEndPoint.Serialize(), _connectTime, id); - _connectRequestPacket.ConnectionNumber = connectNum; - - //Send request - NetManager.SendRaw(_connectRequestPacket, _remoteEndPoint); - - NetDebug.Write(NetLogLevel.Trace, $"[CC] ConnectId: {_connectTime}, ConnectNum: {connectNum}"); - } - - //"Accept" incoming constructor - internal NetPeer(NetManager netManager, ConnectionRequest request, int id) - : this(netManager, request.RemoteEndPoint, id) - { - _connectTime = request.InternalPacket.ConnectionTime; - ConnectionNum = request.InternalPacket.ConnectionNumber; - RemoteId = request.InternalPacket.PeerId; - - //Make initial packet - _connectAcceptPacket = NetConnectAcceptPacket.Make(_connectTime, ConnectionNum, id); - - //Make Connected - _connectionState = ConnectionState.Connected; - - //Send - NetManager.SendRaw(_connectAcceptPacket, _remoteEndPoint); - - NetDebug.Write(NetLogLevel.Trace, $"[CC] ConnectId: {_connectTime}"); - } - - //Reject - internal void Reject(NetConnectRequestPacket requestData, byte[] data, int start, int length) - { - _connectTime = requestData.ConnectionTime; - _connectNum = requestData.ConnectionNumber; - Shutdown(data, start, length, false); - } - - internal bool ProcessConnectAccept(NetConnectAcceptPacket packet) - { - if (_connectionState != ConnectionState.Outgoing) - return false; - - //check connection id - if (packet.ConnectionTime != _connectTime) - { - NetDebug.Write(NetLogLevel.Trace, $"[NC] Invalid connectId: {packet.ConnectionTime} != our({_connectTime})"); - return false; - } - //check connect num - ConnectionNum = packet.ConnectionNumber; - RemoteId = packet.PeerId; - - NetDebug.Write(NetLogLevel.Trace, "[NC] Received connection accept"); - Interlocked.Exchange(ref _timeSinceLastPacket, 0); - _connectionState = ConnectionState.Connected; - return true; - } - - /// - /// Gets maximum size of packet that will be not fragmented. - /// - /// Type of packet that you want send - /// size in bytes - public int GetMaxSinglePacketSize(DeliveryMethod options) - { - return _mtu - NetPacket.GetHeaderSize(options == DeliveryMethod.Unreliable ? PacketProperty.Unreliable : PacketProperty.Channeled); - } - - /// - /// Send data to peer with delivery event called - /// - /// Data - /// Number of channel (from 0 to channelsCount - 1) - /// Delivery method (reliable, unreliable, etc.) - /// User data that will be received in DeliveryEvent - /// - /// If you trying to send unreliable packet type - /// - public void SendWithDeliveryEvent(byte[] data, byte channelNumber, DeliveryMethod deliveryMethod, object userData) - { - if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != DeliveryMethod.ReliableUnordered) - throw new ArgumentException("Delivery event will work only for ReliableOrdered/Unordered packets"); - Send_Internal(data, 0, data.Length, channelNumber, deliveryMethod, userData); - } - - /// - /// Send data to peer with delivery event called - /// - /// Data - /// Start of data - /// Length of data - /// Number of channel (from 0 to channelsCount - 1) - /// Delivery method (reliable, unreliable, etc.) - /// User data that will be received in DeliveryEvent - /// - /// If you trying to send unreliable packet type - /// - public void SendWithDeliveryEvent(byte[] data, int start, int length, byte channelNumber, DeliveryMethod deliveryMethod, object userData) - { - if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != DeliveryMethod.ReliableUnordered) - throw new ArgumentException("Delivery event will work only for ReliableOrdered/Unordered packets"); - Send_Internal(data, start, length, channelNumber, deliveryMethod, userData); - } - - /// - /// Send data to peer with delivery event called - /// - /// Data - /// Number of channel (from 0 to channelsCount - 1) - /// Delivery method (reliable, unreliable, etc.) - /// User data that will be received in DeliveryEvent - /// - /// If you trying to send unreliable packet type - /// - public void SendWithDeliveryEvent(NetDataWriter dataWriter, byte channelNumber, DeliveryMethod deliveryMethod, object userData) - { - if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != DeliveryMethod.ReliableUnordered) - throw new ArgumentException("Delivery event will work only for ReliableOrdered/Unordered packets"); - Send_Internal(dataWriter.Data, 0, dataWriter.Length, channelNumber, deliveryMethod, userData); - } - - /// - /// Send data to peer (channel - 0) - /// - /// Data - /// Send options (reliable, unreliable, etc.) - /// - /// If size exceeds maximum limit: - /// MTU - headerSize bytes for Unreliable - /// Fragment count exceeded ushort.MaxValue - /// - public void Send(byte[] data, DeliveryMethod deliveryMethod) - { - Send_Internal(data, 0, data.Length, 0, deliveryMethod, null); - } - - /// - /// Send data to peer (channel - 0) - /// - /// DataWriter with data - /// Send options (reliable, unreliable, etc.) - /// - /// If size exceeds maximum limit: - /// MTU - headerSize bytes for Unreliable - /// Fragment count exceeded ushort.MaxValue - /// - public void Send(NetDataWriter dataWriter, DeliveryMethod deliveryMethod) - { - Send_Internal(dataWriter.Data, 0, dataWriter.Length, 0, deliveryMethod, null); - } - - /// - /// Send data to peer (channel - 0) - /// - /// Data - /// Start of data - /// Length of data - /// Send options (reliable, unreliable, etc.) - /// - /// If size exceeds maximum limit: - /// MTU - headerSize bytes for Unreliable - /// Fragment count exceeded ushort.MaxValue - /// - public void Send(byte[] data, int start, int length, DeliveryMethod options) - { - Send_Internal(data, start, length, 0, options, null); - } - - /// - /// Send data to peer - /// - /// Data - /// Number of channel (from 0 to channelsCount - 1) - /// Send options (reliable, unreliable, etc.) - /// - /// If size exceeds maximum limit: - /// MTU - headerSize bytes for Unreliable - /// Fragment count exceeded ushort.MaxValue - /// - public void Send(byte[] data, byte channelNumber, DeliveryMethod deliveryMethod) - { - Send_Internal(data, 0, data.Length, channelNumber, deliveryMethod, null); - } - - /// - /// Send data to peer - /// - /// DataWriter with data - /// Number of channel (from 0 to channelsCount - 1) - /// Send options (reliable, unreliable, etc.) - /// - /// If size exceeds maximum limit: - /// MTU - headerSize bytes for Unreliable - /// Fragment count exceeded ushort.MaxValue - /// - public void Send(NetDataWriter dataWriter, byte channelNumber, DeliveryMethod deliveryMethod) - { - Send_Internal(dataWriter.Data, 0, dataWriter.Length, channelNumber, deliveryMethod, null); - } - - /// - /// Send data to peer - /// - /// Data - /// Start of data - /// Length of data - /// Number of channel (from 0 to channelsCount - 1) - /// Delivery method (reliable, unreliable, etc.) - /// - /// If size exceeds maximum limit: - /// MTU - headerSize bytes for Unreliable - /// Fragment count exceeded ushort.MaxValue - /// - public void Send(byte[] data, int start, int length, byte channelNumber, DeliveryMethod deliveryMethod) - { - Send_Internal(data, start, length, channelNumber, deliveryMethod, null); - } - - private void Send_Internal( - byte[] data, - int start, - int length, - byte channelNumber, - DeliveryMethod deliveryMethod, - object userData) - { - if (_connectionState != ConnectionState.Connected || channelNumber >= _channels.Length) - return; - - //Select channel - PacketProperty property; - BaseChannel channel = null; - - if (deliveryMethod == DeliveryMethod.Unreliable) - { - property = PacketProperty.Unreliable; - } - else - { - property = PacketProperty.Channeled; - channel = CreateChannel((byte)(channelNumber * NetConstants.ChannelTypeCount + (byte)deliveryMethod)); - } - - //Prepare - NetDebug.Write("[RS]Packet: " + property); - - //Check fragmentation - int headerSize = NetPacket.GetHeaderSize(property); - //Save mtu for multithread - int mtu = _mtu; - if (length + headerSize > mtu) - { - //if cannot be fragmented - if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != DeliveryMethod.ReliableUnordered) - throw new TooBigPacketException("Unreliable or ReliableSequenced packet size exceeded maximum of " + (mtu - headerSize) + " bytes, Check allowed size by GetMaxSinglePacketSize()"); - - int packetFullSize = mtu - headerSize; - int packetDataSize = packetFullSize - NetConstants.FragmentHeaderSize; - int totalPackets = length / packetDataSize + (length % packetDataSize == 0 ? 0 : 1); - - NetDebug.Write("FragmentSend:\n" + - " MTU: {0}\n" + - " headerSize: {1}\n" + - " packetFullSize: {2}\n" + - " packetDataSize: {3}\n" + - " totalPackets: {4}", - mtu, headerSize, packetFullSize, packetDataSize, totalPackets); - - if (totalPackets > ushort.MaxValue) - throw new TooBigPacketException("Data was split in " + totalPackets + " fragments, which exceeds " + ushort.MaxValue); - - ushort currentFragmentId = (ushort)Interlocked.Increment(ref _fragmentId); - - for(ushort partIdx = 0; partIdx < totalPackets; partIdx++) - { - int sendLength = length > packetDataSize ? packetDataSize : length; - - NetPacket p = NetManager.PoolGetPacket(headerSize + sendLength + NetConstants.FragmentHeaderSize); - p.Property = property; - p.UserData = userData; - p.FragmentId = currentFragmentId; - p.FragmentPart = partIdx; - p.FragmentsTotal = (ushort)totalPackets; - p.MarkFragmented(); - - Buffer.BlockCopy(data, start + partIdx * packetDataSize, p.RawData, NetConstants.FragmentedHeaderTotalSize, sendLength); - channel.AddToQueue(p); - - length -= sendLength; - } - return; - } - - //Else just send - NetPacket packet = NetManager.PoolGetPacket(headerSize + length); - packet.Property = property; - Buffer.BlockCopy(data, start, packet.RawData, headerSize, length); - packet.UserData = userData; - - if (channel == null) //unreliable - { - lock(_unreliableChannel) - _unreliableChannel.Enqueue(packet); - } - else - { - channel.AddToQueue(packet); - } - } - -#if LITENETLIB_SPANS || NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1 || NETCOREAPP3_1 || NET5_0 || NETSTANDARD2_1 - /// - /// Send data to peer with delivery event called - /// - /// Data - /// Number of channel (from 0 to channelsCount - 1) - /// Delivery method (reliable, unreliable, etc.) - /// User data that will be received in DeliveryEvent - /// - /// If you trying to send unreliable packet type - /// - public void SendWithDeliveryEvent(ReadOnlySpan data, byte channelNumber, DeliveryMethod deliveryMethod, object userData) - { - if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != DeliveryMethod.ReliableUnordered) - throw new ArgumentException("Delivery event will work only for ReliableOrdered/Unordered packets"); - Send_Internal(data, channelNumber, deliveryMethod, userData); - } - - /// - /// Send data to peer (channel - 0) - /// - /// Data - /// Send options (reliable, unreliable, etc.) - /// - /// If size exceeds maximum limit: - /// MTU - headerSize bytes for Unreliable - /// Fragment count exceeded ushort.MaxValue - /// - public void Send(ReadOnlySpan data, DeliveryMethod deliveryMethod) - { - Send_Internal(data, 0, deliveryMethod, null); - } - - /// - /// Send data to peer - /// - /// Data - /// Number of channel (from 0 to channelsCount - 1) - /// Send options (reliable, unreliable, etc.) - /// - /// If size exceeds maximum limit: - /// MTU - headerSize bytes for Unreliable - /// Fragment count exceeded ushort.MaxValue - /// - public void Send(ReadOnlySpan data, byte channelNumber, DeliveryMethod deliveryMethod) - { - Send_Internal(data, channelNumber, deliveryMethod, null); - } - - private void Send_Internal( - ReadOnlySpan data, - byte channelNumber, - DeliveryMethod deliveryMethod, - object userData) - { - if (_connectionState != ConnectionState.Connected || channelNumber >= _channels.Length) - return; - - //Select channel - PacketProperty property; - BaseChannel channel = null; - - if (deliveryMethod == DeliveryMethod.Unreliable) - { - property = PacketProperty.Unreliable; - } - else - { - property = PacketProperty.Channeled; - channel = CreateChannel((byte)(channelNumber * NetConstants.ChannelTypeCount + (byte)deliveryMethod)); - } - - //Prepare - NetDebug.Write("[RS]Packet: " + property); - - //Check fragmentation - int headerSize = NetPacket.GetHeaderSize(property); - //Save mtu for multithread - int mtu = _mtu; - int length = data.Length; - if (length + headerSize > mtu) - { - //if cannot be fragmented - if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != DeliveryMethod.ReliableUnordered) - throw new TooBigPacketException("Unreliable or ReliableSequenced packet size exceeded maximum of " + (mtu - headerSize) + " bytes, Check allowed size by GetMaxSinglePacketSize()"); - - int packetFullSize = mtu - headerSize; - int packetDataSize = packetFullSize - NetConstants.FragmentHeaderSize; - int totalPackets = length / packetDataSize + (length % packetDataSize == 0 ? 0 : 1); - - if (totalPackets > ushort.MaxValue) - throw new TooBigPacketException("Data was split in " + totalPackets + " fragments, which exceeds " + ushort.MaxValue); - - ushort currentFragmentId = (ushort)Interlocked.Increment(ref _fragmentId); - - for (ushort partIdx = 0; partIdx < totalPackets; partIdx++) - { - int sendLength = length > packetDataSize ? packetDataSize : length; - - NetPacket p = NetManager.PoolGetPacket(headerSize + sendLength + NetConstants.FragmentHeaderSize); - p.Property = property; - p.UserData = userData; - p.FragmentId = currentFragmentId; - p.FragmentPart = partIdx; - p.FragmentsTotal = (ushort)totalPackets; - p.MarkFragmented(); - - data.Slice(partIdx * packetDataSize, sendLength).CopyTo(new Span(p.RawData, NetConstants.FragmentedHeaderTotalSize, sendLength)); - channel.AddToQueue(p); - - length -= sendLength; - } - return; - } - - //Else just send - NetPacket packet = NetManager.PoolGetPacket(headerSize + length); - packet.Property = property; - data.CopyTo(new Span(packet.RawData, headerSize, length)); - packet.UserData = userData; - - if (channel == null) //unreliable - { - lock(_unreliableChannel) - _unreliableChannel.Enqueue(packet); - } - else - { - channel.AddToQueue(packet); - } - } -#endif - - public void Disconnect(byte[] data) - { - NetManager.DisconnectPeer(this, data); - } - - public void Disconnect(NetDataWriter writer) - { - NetManager.DisconnectPeer(this, writer); - } - - public void Disconnect(byte[] data, int start, int count) - { - NetManager.DisconnectPeer(this, data, start, count); - } - - public void Disconnect() - { - NetManager.DisconnectPeer(this); - } - - internal DisconnectResult ProcessDisconnect(NetPacket packet) - { - if ((_connectionState == ConnectionState.Connected || _connectionState == ConnectionState.Outgoing) && - packet.Size >= 9 && - BitConverter.ToInt64(packet.RawData, 1) == _connectTime && - packet.ConnectionNumber == _connectNum) - { - return _connectionState == ConnectionState.Connected - ? DisconnectResult.Disconnect - : DisconnectResult.Reject; - } - return DisconnectResult.None; - } - - internal void AddToReliableChannelSendQueue(BaseChannel channel) - { - _channelSendQueue.Enqueue(channel); - } - - internal ShutdownResult Shutdown(byte[] data, int start, int length, bool force) - { - lock (_shutdownLock) - { - //trying to shutdown already disconnected - if (_connectionState == ConnectionState.Disconnected || - _connectionState == ConnectionState.ShutdownRequested) - { - return ShutdownResult.None; - } - - var result = _connectionState == ConnectionState.Connected - ? ShutdownResult.WasConnected - : ShutdownResult.Success; - - //don't send anything - if (force) - { - _connectionState = ConnectionState.Disconnected; - return result; - } - - //reset time for reconnect protection - Interlocked.Exchange(ref _timeSinceLastPacket, 0); - - //send shutdown packet - _shutdownPacket = new NetPacket(PacketProperty.Disconnect, length) {ConnectionNumber = _connectNum}; - FastBitConverter.GetBytes(_shutdownPacket.RawData, 1, _connectTime); - if (_shutdownPacket.Size >= _mtu) - { - //Drop additional data - NetDebug.WriteError("[Peer] Disconnect additional data size more than MTU - 8!"); - } - else if (data != null && length > 0) - { - Buffer.BlockCopy(data, start, _shutdownPacket.RawData, 9, length); - } - _connectionState = ConnectionState.ShutdownRequested; - NetDebug.Write("[Peer] Send disconnect"); - NetManager.SendRaw(_shutdownPacket, _remoteEndPoint); - return result; - } - } - - private void UpdateRoundTripTime(int roundTripTime) - { - _rtt += roundTripTime; - _rttCount++; - _avgRtt = _rtt/_rttCount; - _resendDelay = 25.0 + _avgRtt * 2.1; // 25 ms + double rtt - } - - internal void AddReliablePacket(DeliveryMethod method, NetPacket p) - { - if (p.IsFragmented) - { - NetDebug.Write("Fragment. Id: {0}, Part: {1}, Total: {2}", p.FragmentId, p.FragmentPart, p.FragmentsTotal); - //Get needed array from dictionary - ushort packetFragId = p.FragmentId; - byte packetChannelId = p.ChannelId; - if (!_holdedFragments.TryGetValue(packetFragId, out var incomingFragments)) - { - incomingFragments = new IncomingFragments - { - Fragments = new NetPacket[p.FragmentsTotal], - ChannelId = p.ChannelId - }; - _holdedFragments.Add(packetFragId, incomingFragments); - } - - //Cache - var fragments = incomingFragments.Fragments; - - //Error check - if (p.FragmentPart >= fragments.Length || - fragments[p.FragmentPart] != null || - p.ChannelId != incomingFragments.ChannelId) - { - NetManager.PoolRecycle(p); - NetDebug.WriteError("Invalid fragment packet"); - return; - } - //Fill array - fragments[p.FragmentPart] = p; - - //Increase received fragments count - incomingFragments.ReceivedCount++; - - //Increase total size - incomingFragments.TotalSize += p.Size - NetConstants.FragmentedHeaderTotalSize; - - //Check for finish - if (incomingFragments.ReceivedCount != fragments.Length) - return; - - //just simple packet - NetPacket resultingPacket = NetManager.PoolGetPacket(incomingFragments.TotalSize); - - int pos = 0; - for (int i = 0; i < incomingFragments.ReceivedCount; i++) - { - var fragment = fragments[i]; - int writtenSize = fragment.Size - NetConstants.FragmentedHeaderTotalSize; - - if (pos+writtenSize > resultingPacket.RawData.Length) - { - _holdedFragments.Remove(packetFragId); - NetDebug.WriteError("Fragment error pos: {0} >= resultPacketSize: {1} , totalSize: {2}", - pos + writtenSize, - resultingPacket.RawData.Length, - incomingFragments.TotalSize); - return; - } - if (fragment.Size > fragment.RawData.Length) - { - _holdedFragments.Remove(packetFragId); - NetDebug.WriteError("Fragment error size: {0} > fragment.RawData.Length: {1}", fragment.Size, fragment.RawData.Length); - return; - } - - //Create resulting big packet - Buffer.BlockCopy( - fragment.RawData, - NetConstants.FragmentedHeaderTotalSize, - resultingPacket.RawData, - pos, - writtenSize); - pos += writtenSize; - - //Free memory - NetManager.PoolRecycle(fragment); - fragments[i] = null; - } - - //Clear memory - _holdedFragments.Remove(packetFragId); - - //Send to process - NetManager.CreateReceiveEvent(resultingPacket, method, (byte)(packetChannelId / NetConstants.ChannelTypeCount), 0, this); - } - else //Just simple packet - { - NetManager.CreateReceiveEvent(p, method, (byte)(p.ChannelId / NetConstants.ChannelTypeCount), NetConstants.ChanneledHeaderSize, this); - } - } - - private void ProcessMtuPacket(NetPacket packet) - { - //header + int - if (packet.Size < NetConstants.PossibleMtu[0]) - return; - - //first stage check (mtu check and mtu ok) - int receivedMtu = BitConverter.ToInt32(packet.RawData, 1); - int endMtuCheck = BitConverter.ToInt32(packet.RawData, packet.Size - 4); - if (receivedMtu != packet.Size || receivedMtu != endMtuCheck || receivedMtu > NetConstants.MaxPacketSize) - { - NetDebug.WriteError("[MTU] Broken packet. RMTU {0}, EMTU {1}, PSIZE {2}", receivedMtu, endMtuCheck, packet.Size); - return; - } - - if (packet.Property == PacketProperty.MtuCheck) - { - _mtuCheckAttempts = 0; - NetDebug.Write("[MTU] check. send back: " + receivedMtu); - packet.Property = PacketProperty.MtuOk; - NetManager.SendRawAndRecycle(packet, _remoteEndPoint); - } - else if(receivedMtu > _mtu && !_finishMtu) //MtuOk - { - //invalid packet - if (receivedMtu != NetConstants.PossibleMtu[_mtuIdx + 1] - NetManager.ExtraPacketSizeForLayer) - return; - - lock (_mtuMutex) - { - SetMtu(_mtuIdx+1); - } - //if maxed - finish. - if (_mtuIdx == NetConstants.PossibleMtu.Length - 1) - _finishMtu = true; - NetManager.PoolRecycle(packet); - NetDebug.Write("[MTU] ok. Increase to: " + _mtu); - } - } - - private void UpdateMtuLogic(int deltaTime) - { - if (_finishMtu) - return; - - _mtuCheckTimer += deltaTime; - if (_mtuCheckTimer < MtuCheckDelay) - return; - - _mtuCheckTimer = 0; - _mtuCheckAttempts++; - if (_mtuCheckAttempts >= MaxMtuCheckAttempts) - { - _finishMtu = true; - return; - } - - lock (_mtuMutex) - { - if (_mtuIdx >= NetConstants.PossibleMtu.Length - 1) - return; - - //Send increased packet - int newMtu = NetConstants.PossibleMtu[_mtuIdx + 1] - NetManager.ExtraPacketSizeForLayer; - var p = NetManager.PoolGetPacket(newMtu); - p.Property = PacketProperty.MtuCheck; - FastBitConverter.GetBytes(p.RawData, 1, newMtu); //place into start - FastBitConverter.GetBytes(p.RawData, p.Size - 4, newMtu);//and end of packet - - //Must check result for MTU fix - if (NetManager.SendRawAndRecycle(p, _remoteEndPoint) <= 0) - _finishMtu = true; - } - } - - internal ConnectRequestResult ProcessConnectRequest(NetConnectRequestPacket connRequest) - { - //current or new request - switch (_connectionState) - { - //P2P case - case ConnectionState.Outgoing: - //fast check - if (connRequest.ConnectionTime < _connectTime) - { - return ConnectRequestResult.P2PLose; - } - //slow rare case check - if (connRequest.ConnectionTime == _connectTime) - { - var remoteBytes = _remoteEndPoint.Serialize(); - var localBytes = connRequest.TargetAddress; - for (int i = remoteBytes.Size-1; i >= 0; i--) - { - byte rb = remoteBytes[i]; - if (rb == localBytes[i]) - continue; - if (rb < localBytes[i]) - return ConnectRequestResult.P2PLose; - } - } - break; - - case ConnectionState.Connected: - //Old connect request - if (connRequest.ConnectionTime == _connectTime) - { - //just reply accept - NetManager.SendRaw(_connectAcceptPacket, _remoteEndPoint); - } - //New connect request - else if (connRequest.ConnectionTime > _connectTime) - { - return ConnectRequestResult.Reconnection; - } - break; - - case ConnectionState.Disconnected: - case ConnectionState.ShutdownRequested: - if (connRequest.ConnectionTime >= _connectTime) - return ConnectRequestResult.NewConnection; - break; - } - return ConnectRequestResult.None; - } - - //Process incoming packet - internal void ProcessPacket(NetPacket packet) - { - //not initialized - if (_connectionState == ConnectionState.Outgoing || _connectionState == ConnectionState.Disconnected) - { - NetManager.PoolRecycle(packet); - return; - } - if (packet.Property == PacketProperty.ShutdownOk) - { - if (_connectionState == ConnectionState.ShutdownRequested) - _connectionState = ConnectionState.Disconnected; - NetManager.PoolRecycle(packet); - return; - } - if (packet.ConnectionNumber != _connectNum) - { - NetDebug.Write(NetLogLevel.Trace, "[RR]Old packet"); - NetManager.PoolRecycle(packet); - return; - } - Interlocked.Exchange(ref _timeSinceLastPacket, 0); - - NetDebug.Write("[RR]PacketProperty: {0}", packet.Property); - switch (packet.Property) - { - case PacketProperty.Merged: - int pos = NetConstants.HeaderSize; - while (pos < packet.Size) - { - ushort size = BitConverter.ToUInt16(packet.RawData, pos); - pos += 2; - if (packet.RawData.Length - pos < size) - break; - - NetPacket mergedPacket = NetManager.PoolGetPacket(size); - Buffer.BlockCopy(packet.RawData, pos, mergedPacket.RawData, 0, size); - mergedPacket.Size = size; - - if (!mergedPacket.Verify()) - break; - - pos += size; - ProcessPacket(mergedPacket); - } - NetManager.PoolRecycle(packet); - break; - //If we get ping, send pong - case PacketProperty.Ping: - if (NetUtils.RelativeSequenceNumber(packet.Sequence, _pongPacket.Sequence) > 0) - { - NetDebug.Write("[PP]Ping receive, send pong"); - FastBitConverter.GetBytes(_pongPacket.RawData, 3, DateTime.UtcNow.Ticks); - _pongPacket.Sequence = packet.Sequence; - NetManager.SendRaw(_pongPacket, _remoteEndPoint); - } - NetManager.PoolRecycle(packet); - break; - - //If we get pong, calculate ping time and rtt - case PacketProperty.Pong: - if (packet.Sequence == _pingPacket.Sequence) - { - _pingTimer.Stop(); - int elapsedMs = (int)_pingTimer.ElapsedMilliseconds; - _remoteDelta = BitConverter.ToInt64(packet.RawData, 3) + (elapsedMs * TimeSpan.TicksPerMillisecond ) / 2 - DateTime.UtcNow.Ticks; - UpdateRoundTripTime(elapsedMs); - NetManager.ConnectionLatencyUpdated(this, elapsedMs / 2); - NetDebug.Write("[PP]Ping: {0} - {1} - {2}", packet.Sequence, elapsedMs, _remoteDelta); - } - NetManager.PoolRecycle(packet); - break; - - case PacketProperty.Ack: - case PacketProperty.Channeled: - if (packet.ChannelId > _channels.Length) - { - NetManager.PoolRecycle(packet); - break; - } - var channel = _channels[packet.ChannelId] ?? (packet.Property == PacketProperty.Ack ? null : CreateChannel(packet.ChannelId)); - if (channel != null) - { - if (!channel.ProcessPacket(packet)) - NetManager.PoolRecycle(packet); - } - break; - - //Simple packet without acks - case PacketProperty.Unreliable: - NetManager.CreateReceiveEvent(packet, DeliveryMethod.Unreliable, 0, NetConstants.HeaderSize, this); - return; - - case PacketProperty.MtuCheck: - case PacketProperty.MtuOk: - ProcessMtuPacket(packet); - break; - - default: - NetDebug.WriteError("Error! Unexpected packet type: " + packet.Property); - break; - } - } - - private void SendMerged() - { - if (_mergeCount == 0) - return; - int bytesSent; - if (_mergeCount > 1) - { - NetDebug.Write("[P]Send merged: " + _mergePos + ", count: " + _mergeCount); - bytesSent = NetManager.SendRaw(_mergeData.RawData, 0, NetConstants.HeaderSize + _mergePos, _remoteEndPoint); - } - else - { - //Send without length information and merging - bytesSent = NetManager.SendRaw(_mergeData.RawData, NetConstants.HeaderSize + 2, _mergePos - 2, _remoteEndPoint); - } - - if (NetManager.EnableStatistics) - { - Statistics.IncrementPacketsSent(); - Statistics.AddBytesSent(bytesSent); - } - - _mergePos = 0; - _mergeCount = 0; - } - - internal void SendUserData(NetPacket packet) - { - packet.ConnectionNumber = _connectNum; - int mergedPacketSize = NetConstants.HeaderSize + packet.Size + 2; - const int sizeTreshold = 20; - if (mergedPacketSize + sizeTreshold >= _mtu) - { - NetDebug.Write(NetLogLevel.Trace, "[P]SendingPacket: " + packet.Property); - int bytesSent = NetManager.SendRaw(packet, _remoteEndPoint); - - if (NetManager.EnableStatistics) - { - Statistics.IncrementPacketsSent(); - Statistics.AddBytesSent(bytesSent); - } - - return; - } - if (_mergePos + mergedPacketSize > _mtu) - SendMerged(); - - FastBitConverter.GetBytes(_mergeData.RawData, _mergePos + NetConstants.HeaderSize, (ushort)packet.Size); - Buffer.BlockCopy(packet.RawData, 0, _mergeData.RawData, _mergePos + NetConstants.HeaderSize + 2, packet.Size); - _mergePos += packet.Size + 2; - _mergeCount++; - //DebugWriteForce("Merged: " + _mergePos + "/" + (_mtu - 2) + ", count: " + _mergeCount); - } - - internal void Update(int deltaTime) - { - Interlocked.Add(ref _timeSinceLastPacket, deltaTime); - switch (_connectionState) - { - case ConnectionState.Connected: - if (_timeSinceLastPacket > NetManager.DisconnectTimeout) - { - NetDebug.Write( - "[UPDATE] Disconnect by timeout: {0} > {1}", - _timeSinceLastPacket, - NetManager.DisconnectTimeout); - NetManager.DisconnectPeerForce(this, DisconnectReason.Timeout, 0, null); - return; - } - break; - - case ConnectionState.ShutdownRequested: - if (_timeSinceLastPacket > NetManager.DisconnectTimeout) - { - _connectionState = ConnectionState.Disconnected; - } - else - { - _shutdownTimer += deltaTime; - if (_shutdownTimer >= ShutdownDelay) - { - _shutdownTimer = 0; - NetManager.SendRaw(_shutdownPacket, _remoteEndPoint); - } - } - return; - - case ConnectionState.Outgoing: - _connectTimer += deltaTime; - if (_connectTimer > NetManager.ReconnectDelay) - { - _connectTimer = 0; - _connectAttempts++; - if (_connectAttempts > NetManager.MaxConnectAttempts) - { - NetManager.DisconnectPeerForce(this, DisconnectReason.ConnectionFailed, 0, null); - return; - } - - //else send connect again - NetManager.SendRaw(_connectRequestPacket, _remoteEndPoint); - } - return; - - case ConnectionState.Disconnected: - return; - } - - //Send ping - _pingSendTimer += deltaTime; - if (_pingSendTimer >= NetManager.PingInterval) - { - NetDebug.Write("[PP] Send ping..."); - //reset timer - _pingSendTimer = 0; - //send ping - _pingPacket.Sequence++; - //ping timeout - if (_pingTimer.IsRunning) - UpdateRoundTripTime((int)_pingTimer.ElapsedMilliseconds); - _pingTimer.Restart(); - NetManager.SendRaw(_pingPacket, _remoteEndPoint); - } - - //RTT - round trip time - _rttResetTimer += deltaTime; - if (_rttResetTimer >= NetManager.PingInterval * 3) - { - _rttResetTimer = 0; - _rtt = _avgRtt; - _rttCount = 1; - } - - UpdateMtuLogic(deltaTime); - - //Pending send - int count = _channelSendQueue.Count; - while (count-- > 0) - { - if (!_channelSendQueue.TryDequeue(out var channel)) - break; - if (channel.SendAndCheckQueue()) - { - // still has something to send, re-add it to the send queue - _channelSendQueue.Enqueue(channel); - } - } - - lock (_unreliableChannel) - { - int unreliableCount = _unreliableChannel.Count; - for (int i = 0; i < unreliableCount; i++) - { - var packet = _unreliableChannel.Dequeue(); - SendUserData(packet); - NetManager.PoolRecycle(packet); - } - } - - SendMerged(); - } - - //For reliable channel - internal void RecycleAndDeliver(NetPacket packet) - { - if (packet.UserData != null) - { - if (packet.IsFragmented) - { - _deliveredFragments.TryGetValue(packet.FragmentId, out ushort fragCount); - fragCount++; - if (fragCount == packet.FragmentsTotal) - { - NetManager.MessageDelivered(this, packet.UserData); - _deliveredFragments.Remove(packet.FragmentId); - } - else - { - _deliveredFragments[packet.FragmentId] = fragCount; - } - } - else - { - NetManager.MessageDelivered(this, packet.UserData); - } - packet.UserData = null; - } - NetManager.PoolRecycle(packet); - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPeer.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPeer.cs.meta deleted file mode 100644 index 7d06b87..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetPeer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3e1a9277334c51545b92369c8e4c6d74 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetStatistics.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetStatistics.cs deleted file mode 100644 index 032e275..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetStatistics.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System.Threading; - -namespace LiteNetLib -{ - public sealed class NetStatistics - { - private long _packetsSent; - private long _packetsReceived; - private long _bytesSent; - private long _bytesReceived; - private long _packetLoss; - - public long PacketsSent => Interlocked.Read(ref _packetsSent); - public long PacketsReceived => Interlocked.Read(ref _packetsReceived); - public long BytesSent => Interlocked.Read(ref _bytesSent); - public long BytesReceived => Interlocked.Read(ref _bytesReceived); - public long PacketLoss => Interlocked.Read(ref _packetLoss); - - public long PacketLossPercent - { - get - { - long sent = PacketsSent, loss = PacketLoss; - - return sent == 0 ? 0 : loss * 100 / sent; - } - } - - public void Reset() - { - Interlocked.Exchange(ref _packetsSent, 0); - Interlocked.Exchange(ref _packetsReceived, 0); - Interlocked.Exchange(ref _bytesSent, 0); - Interlocked.Exchange(ref _bytesReceived, 0); - Interlocked.Exchange(ref _packetLoss, 0); - } - - public void IncrementPacketsSent() - { - Interlocked.Increment(ref _packetsSent); - } - - public void IncrementPacketsReceived() - { - Interlocked.Increment(ref _packetsReceived); - } - - public void AddBytesSent(long bytesSent) - { - Interlocked.Add(ref _bytesSent, bytesSent); - } - - public void AddBytesReceived(long bytesReceived) - { - Interlocked.Add(ref _bytesReceived, bytesReceived); - } - - public void IncrementPacketLoss() - { - Interlocked.Increment(ref _packetLoss); - } - - public void AddPacketLoss(long packetLoss) - { - Interlocked.Add(ref _packetLoss, packetLoss); - } - - public override string ToString() - { - return - string.Format( - "BytesReceived: {0}\nPacketsReceived: {1}\nBytesSent: {2}\nPacketsSent: {3}\nPacketLoss: {4}\nPacketLossPercent: {5}\n", - BytesReceived, - PacketsReceived, - BytesSent, - PacketsSent, - PacketLoss, - PacketLossPercent); - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetStatistics.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetStatistics.cs.meta deleted file mode 100644 index 8d54a07..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetStatistics.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 15d4b62077bda58428b77d57fa4a9288 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetUtils.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetUtils.cs deleted file mode 100644 index d162b2d..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetUtils.cs +++ /dev/null @@ -1,194 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Sockets; -using System.Net.NetworkInformation; - -namespace LiteNetLib -{ - /// - /// Address type that you want to receive from NetUtils.GetLocalIp method - /// - [Flags] - public enum LocalAddrType - { - IPv4 = 1, - IPv6 = 2, - All = IPv4 | IPv6 - } - - /// - /// Some specific network utilities - /// - public static class NetUtils - { - public static IPEndPoint MakeEndPoint(string hostStr, int port) - { - return new IPEndPoint(ResolveAddress(hostStr), port); - } - - public static IPAddress ResolveAddress(string hostStr) - { - if(hostStr == "localhost") - return IPAddress.Loopback; - - if (!IPAddress.TryParse(hostStr, out var ipAddress)) - { - if (NetManager.IPv6Support) - ipAddress = ResolveAddress(hostStr, AddressFamily.InterNetworkV6); - if (ipAddress == null) - ipAddress = ResolveAddress(hostStr, AddressFamily.InterNetwork); - } - if (ipAddress == null) - throw new ArgumentException("Invalid address: " + hostStr); - - return ipAddress; - } - - public static IPAddress ResolveAddress(string hostStr, AddressFamily addressFamily) - { - IPAddress[] addresses = Dns.GetHostEntry(hostStr).AddressList; - foreach (IPAddress ip in addresses) - { - if (ip.AddressFamily == addressFamily) - { - return ip; - } - } - return null; - } - - /// - /// Get all local ip addresses - /// - /// type of address (IPv4, IPv6 or both) - /// List with all local ip addresses - public static List GetLocalIpList(LocalAddrType addrType) - { - List targetList = new List(); - GetLocalIpList(targetList, addrType); - return targetList; - } - - /// - /// Get all local ip addresses (non alloc version) - /// - /// result list - /// type of address (IPv4, IPv6 or both) - public static void GetLocalIpList(IList targetList, LocalAddrType addrType) - { - bool ipv4 = (addrType & LocalAddrType.IPv4) == LocalAddrType.IPv4; - bool ipv6 = (addrType & LocalAddrType.IPv6) == LocalAddrType.IPv6; - try - { - foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) - { - //Skip loopback and disabled network interfaces - if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback || - ni.OperationalStatus != OperationalStatus.Up) - continue; - - var ipProps = ni.GetIPProperties(); - - //Skip address without gateway - if (ipProps.GatewayAddresses.Count == 0) - continue; - - foreach (UnicastIPAddressInformation ip in ipProps.UnicastAddresses) - { - var address = ip.Address; - if ((ipv4 && address.AddressFamily == AddressFamily.InterNetwork) || - (ipv6 && address.AddressFamily == AddressFamily.InterNetworkV6)) - targetList.Add(address.ToString()); - } - } - - //Fallback mode (unity android) - if (targetList.Count == 0) - { - IPAddress[] addresses = Dns.GetHostEntry(Dns.GetHostName()).AddressList; - foreach (IPAddress ip in addresses) - { - if((ipv4 && ip.AddressFamily == AddressFamily.InterNetwork) || - (ipv6 && ip.AddressFamily == AddressFamily.InterNetworkV6)) - targetList.Add(ip.ToString()); - } - } - } - catch - { - //ignored - } - - if (targetList.Count == 0) - { - if(ipv4) - targetList.Add("127.0.0.1"); - if(ipv6) - targetList.Add("::1"); - } - } - - private static readonly List IpList = new List(); - /// - /// Get first detected local ip address - /// - /// type of address (IPv4, IPv6 or both) - /// IP address if available. Else - string.Empty - public static string GetLocalIp(LocalAddrType addrType) - { - lock (IpList) - { - IpList.Clear(); - GetLocalIpList(IpList, addrType); - return IpList.Count == 0 ? string.Empty : IpList[0]; - } - } - - // =========================================== - // Internal and debug log related stuff - // =========================================== - internal static void PrintInterfaceInfos() - { - NetDebug.WriteForce(NetLogLevel.Info, "IPv6Support: {0}", NetManager.IPv6Support); - try - { - foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) - { - foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses) - { - if (ip.Address.AddressFamily == AddressFamily.InterNetwork || - ip.Address.AddressFamily == AddressFamily.InterNetworkV6) - { - NetDebug.WriteForce( - NetLogLevel.Info, - "Interface: {0}, Type: {1}, Ip: {2}, OpStatus: {3}", - ni.Name, - ni.NetworkInterfaceType.ToString(), - ip.Address.ToString(), - ni.OperationalStatus.ToString()); - } - } - } - } - catch (Exception e) - { - NetDebug.WriteForce(NetLogLevel.Info, "Error while getting interface infos: {0}", e.ToString()); - } - } - - internal static int RelativeSequenceNumber(int number, int expected) - { - return (number - expected + NetConstants.MaxSequence + NetConstants.HalfMaxSequence) % NetConstants.MaxSequence - NetConstants.HalfMaxSequence; - } - - internal static T[] AllocatePinnedUninitializedArray(int count) where T : unmanaged - { -#if NET5_0_OR_GREATER || NET5_0 - return GC.AllocateUninitializedArray(count, true); -#else - return new T[count]; -#endif - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetUtils.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetUtils.cs.meta deleted file mode 100644 index 0d039e7..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/NetUtils.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ab6438405a73f8c46ac22cd2f259a0e2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PausedSocketFix.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PausedSocketFix.cs deleted file mode 100644 index 2ecbfb8..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PausedSocketFix.cs +++ /dev/null @@ -1,75 +0,0 @@ - -using System.Net; - -namespace LiteNetLib -{ - - public class PausedSocketFix - { - public bool ApplicationFocused { get; private set; } - - private NetManager _netManager; - private IPAddress _ipv4; - private IPAddress _ipv6; - private int _port; - private bool _manualMode; - - - public PausedSocketFix() - { - UnityEngine.Application.focusChanged += Application_focusChanged; - } - public PausedSocketFix(NetManager netManager, IPAddress ipv4, IPAddress ipv6, int port, bool manualMode) : this() - { - Initialize(netManager, ipv4, ipv6, port, manualMode); - } - - ~PausedSocketFix() - { - UnityEngine.Application.focusChanged -= Application_focusChanged; - } - - public void Initialize(NetManager netManager, IPAddress ipv4, IPAddress ipv6, int port, bool manualMode) - { - _netManager = netManager; - _ipv4 = ipv4; - _ipv6 = ipv6; - _port = port; - _manualMode = manualMode; - } - - - private void Application_focusChanged(bool focused) - { - ApplicationFocused = focused; - //If coming back into focus see if a reconnect is needed. - if (focused) - TryReconnect(); - } - - - private void TryReconnect() - { - if (_netManager == null) - return; - //Was intentionally disconnected at some point. - if (!_netManager.IsRunning) - return; - if (!_netManager.IsClient) - return; - //Socket is still running. - if (_netManager.SocketActive(false) || _netManager.SocketActive(true)) - return; - - //Socket isn't running but should be. Try to start again. - if (!_netManager.Start(_ipv4, _ipv6, _port, _manualMode)) - { - NetDebug.WriteError($"[S] Cannot restore connection. Ipv4 {_ipv4}, Ipv6 {_ipv6}, Port {_port}, ManualMode {_manualMode}"); - _netManager.CloseSocket(false); - } - } - - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PausedSocketFix.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PausedSocketFix.cs.meta deleted file mode 100644 index 18fc877..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PausedSocketFix.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7d69976ae1e5f344daec35f343bbe189 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PooledPacket.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PooledPacket.cs deleted file mode 100644 index 26ef7bd..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PooledPacket.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace LiteNetLib -{ - public readonly ref struct PooledPacket - { - internal readonly NetPacket _packet; - internal readonly byte _channelNumber; - - /// - /// Maximum data size that you can put into such packet - /// - public readonly int MaxUserDataSize; - - /// - /// Offset for user data when writing to Data array - /// - public readonly int UserDataOffset; - - /// - /// Raw packet data. Do not modify header! Use UserDataOffset as start point for your data - /// - public byte[] Data => _packet.RawData; - - internal PooledPacket(NetPacket packet, int maxDataSize, byte channelNumber) - { - _packet = packet; - UserDataOffset = _packet.GetHeaderSize(); - _packet.Size = UserDataOffset; - MaxUserDataSize = maxDataSize - UserDataOffset; - _channelNumber = channelNumber; - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PooledPacket.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PooledPacket.cs.meta deleted file mode 100644 index 8c3b978..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/PooledPacket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 76e47a542bb12e043b874c7180d98319 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ReliableChannel.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ReliableChannel.cs deleted file mode 100644 index f825e37..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ReliableChannel.cs +++ /dev/null @@ -1,336 +0,0 @@ -using System; - -namespace LiteNetLib -{ - internal sealed class ReliableChannel : BaseChannel - { - private struct PendingPacket - { - private NetPacket _packet; - private long _timeStamp; - private bool _isSent; - - public override string ToString() - { - return _packet == null ? "Empty" : _packet.Sequence.ToString(); - } - - public void Init(NetPacket packet) - { - _packet = packet; - _isSent = false; - } - - //Returns true if there is a pending packet inside - public bool TrySend(long currentTime, NetPeer peer) - { - if (_packet == null) - return false; - - if (_isSent) //check send time - { - double resendDelay = peer.ResendDelay * TimeSpan.TicksPerMillisecond; - double packetHoldTime = currentTime - _timeStamp; - if (packetHoldTime < resendDelay) - return true; - NetDebug.Write("[RC]Resend: {0} > {1}", (int)packetHoldTime, resendDelay); - } - _timeStamp = currentTime; - _isSent = true; - peer.SendUserData(_packet); - return true; - } - - public bool Clear(NetPeer peer) - { - if (_packet != null) - { - peer.RecycleAndDeliver(_packet); - _packet = null; - return true; - } - return false; - } - } - - private readonly NetPacket _outgoingAcks; //for send acks - private readonly PendingPacket[] _pendingPackets; //for unacked packets and duplicates - private readonly NetPacket[] _receivedPackets; //for order - private readonly bool[] _earlyReceived; //for unordered - - private int _localSeqence; - private int _remoteSequence; - private int _localWindowStart; - private int _remoteWindowStart; - - private bool _mustSendAcks; - - private readonly DeliveryMethod _deliveryMethod; - private readonly bool _ordered; - private readonly int _windowSize; - private const int BitsInByte = 8; - private readonly byte _id; - - public ReliableChannel(NetPeer peer, bool ordered, byte id) : base(peer) - { - _id = id; - _windowSize = NetConstants.DefaultWindowSize; - _ordered = ordered; - _pendingPackets = new PendingPacket[_windowSize]; - for (int i = 0; i < _pendingPackets.Length; i++) - _pendingPackets[i] = new PendingPacket(); - - if (_ordered) - { - _deliveryMethod = DeliveryMethod.ReliableOrdered; - _receivedPackets = new NetPacket[_windowSize]; - } - else - { - _deliveryMethod = DeliveryMethod.ReliableUnordered; - _earlyReceived = new bool[_windowSize]; - } - - _localWindowStart = 0; - _localSeqence = 0; - _remoteSequence = 0; - _remoteWindowStart = 0; - _outgoingAcks = new NetPacket(PacketProperty.Ack, (_windowSize - 1) / BitsInByte + 2) {ChannelId = id}; - } - - //ProcessAck in packet - private void ProcessAck(NetPacket packet) - { - if (packet.Size != _outgoingAcks.Size) - { - NetDebug.Write("[PA]Invalid acks packet size"); - return; - } - - ushort ackWindowStart = packet.Sequence; - int windowRel = NetUtils.RelativeSequenceNumber(_localWindowStart, ackWindowStart); - if (ackWindowStart >= NetConstants.MaxSequence || windowRel < 0) - { - NetDebug.Write("[PA]Bad window start"); - return; - } - - //check relevance - if (windowRel >= _windowSize) - { - NetDebug.Write("[PA]Old acks"); - return; - } - - byte[] acksData = packet.RawData; - lock (_pendingPackets) - { - for (int pendingSeq = _localWindowStart; - pendingSeq != _localSeqence; - pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence) - { - int rel = NetUtils.RelativeSequenceNumber(pendingSeq, ackWindowStart); - if (rel >= _windowSize) - { - NetDebug.Write("[PA]REL: " + rel); - break; - } - - int pendingIdx = pendingSeq % _windowSize; - int currentByte = NetConstants.ChanneledHeaderSize + pendingIdx / BitsInByte; - int currentBit = pendingIdx % BitsInByte; - if ((acksData[currentByte] & (1 << currentBit)) == 0) - { - if (Peer.NetManager.EnableStatistics) - { - Peer.Statistics.IncrementPacketLoss(); - Peer.NetManager.Statistics.IncrementPacketLoss(); - } - - //Skip false ack - NetDebug.Write("[PA]False ack: {0}", pendingSeq); - continue; - } - - if (pendingSeq == _localWindowStart) - { - //Move window - _localWindowStart = (_localWindowStart + 1) % NetConstants.MaxSequence; - } - - //clear packet - if (_pendingPackets[pendingIdx].Clear(Peer)) - NetDebug.Write("[PA]Removing reliableInOrder ack: {0} - true", pendingSeq); - } - } - } - - protected override bool SendNextPackets() - { - if (_mustSendAcks) - { - _mustSendAcks = false; - NetDebug.Write("[RR]SendAcks"); - lock(_outgoingAcks) - Peer.SendUserData(_outgoingAcks); - } - - long currentTime = DateTime.UtcNow.Ticks; - bool hasPendingPackets = false; - - lock (_pendingPackets) - { - //get packets from queue - while (!OutgoingQueue.IsEmpty) - { - int relate = NetUtils.RelativeSequenceNumber(_localSeqence, _localWindowStart); - if (relate >= _windowSize) - break; - - if (!OutgoingQueue.TryDequeue(out var netPacket)) - break; - - netPacket.Sequence = (ushort) _localSeqence; - netPacket.ChannelId = _id; - _pendingPackets[_localSeqence % _windowSize].Init(netPacket); - _localSeqence = (_localSeqence + 1) % NetConstants.MaxSequence; - } - - //send - for (int pendingSeq = _localWindowStart; pendingSeq != _localSeqence; pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence) - { - // Please note: TrySend is invoked on a mutable struct, it's important to not extract it into a variable here - if (_pendingPackets[pendingSeq % _windowSize].TrySend(currentTime, Peer)) - hasPendingPackets = true; - } - } - - return hasPendingPackets || _mustSendAcks || !OutgoingQueue.IsEmpty; - } - - //Process incoming packet - public override bool ProcessPacket(NetPacket packet) - { - if (packet.Property == PacketProperty.Ack) - { - ProcessAck(packet); - return false; - } - int seq = packet.Sequence; - if (seq >= NetConstants.MaxSequence) - { - NetDebug.Write("[RR]Bad sequence"); - return false; - } - - int relate = NetUtils.RelativeSequenceNumber(seq, _remoteWindowStart); - int relateSeq = NetUtils.RelativeSequenceNumber(seq, _remoteSequence); - - if (relateSeq > _windowSize) - { - NetDebug.Write("[RR]Bad sequence"); - return false; - } - - //Drop bad packets - if (relate < 0) - { - //Too old packet doesn't ack - NetDebug.Write("[RR]ReliableInOrder too old"); - return false; - } - if (relate >= _windowSize * 2) - { - //Some very new packet - NetDebug.Write("[RR]ReliableInOrder too new"); - return false; - } - - //If very new - move window - int ackIdx; - int ackByte; - int ackBit; - lock (_outgoingAcks) - { - if (relate >= _windowSize) - { - //New window position - int newWindowStart = (_remoteWindowStart + relate - _windowSize + 1) % NetConstants.MaxSequence; - _outgoingAcks.Sequence = (ushort) newWindowStart; - - //Clean old data - while (_remoteWindowStart != newWindowStart) - { - ackIdx = _remoteWindowStart % _windowSize; - ackByte = NetConstants.ChanneledHeaderSize + ackIdx / BitsInByte; - ackBit = ackIdx % BitsInByte; - _outgoingAcks.RawData[ackByte] &= (byte) ~(1 << ackBit); - _remoteWindowStart = (_remoteWindowStart + 1) % NetConstants.MaxSequence; - } - } - - //Final stage - process valid packet - //trigger acks send - _mustSendAcks = true; - - ackIdx = seq % _windowSize; - ackByte = NetConstants.ChanneledHeaderSize + ackIdx / BitsInByte; - ackBit = ackIdx % BitsInByte; - if ((_outgoingAcks.RawData[ackByte] & (1 << ackBit)) != 0) - { - NetDebug.Write("[RR]ReliableInOrder duplicate"); - //because _mustSendAcks == true - AddToPeerChannelSendQueue(); - return false; - } - - //save ack - _outgoingAcks.RawData[ackByte] |= (byte) (1 << ackBit); - } - - AddToPeerChannelSendQueue(); - - //detailed check - if (seq == _remoteSequence) - { - NetDebug.Write("[RR]ReliableInOrder packet succes"); - Peer.AddReliablePacket(_deliveryMethod, packet); - _remoteSequence = (_remoteSequence + 1) % NetConstants.MaxSequence; - - if (_ordered) - { - NetPacket p; - while ((p = _receivedPackets[_remoteSequence % _windowSize]) != null) - { - //process holden packet - _receivedPackets[_remoteSequence % _windowSize] = null; - Peer.AddReliablePacket(_deliveryMethod, p); - _remoteSequence = (_remoteSequence + 1) % NetConstants.MaxSequence; - } - } - else - { - while (_earlyReceived[_remoteSequence % _windowSize]) - { - //process early packet - _earlyReceived[_remoteSequence % _windowSize] = false; - _remoteSequence = (_remoteSequence + 1) % NetConstants.MaxSequence; - } - } - return true; - } - - //holden packet - if (_ordered) - { - _receivedPackets[ackIdx] = packet; - } - else - { - _earlyReceived[ackIdx] = true; - Peer.AddReliablePacket(_deliveryMethod, packet); - } - return true; - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ReliableChannel.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ReliableChannel.cs.meta deleted file mode 100644 index 55f9b0b..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/ReliableChannel.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f7e20c169333af54fa233b0d70b19a61 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/SequencedChannel.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/SequencedChannel.cs deleted file mode 100644 index a3763ee..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/SequencedChannel.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; - -namespace LiteNetLib -{ - internal sealed class SequencedChannel : BaseChannel - { - private int _localSequence; - private ushort _remoteSequence; - private readonly bool _reliable; - private NetPacket _lastPacket; - private readonly NetPacket _ackPacket; - private bool _mustSendAck; - private readonly byte _id; - private long _lastPacketSendTime; - - public SequencedChannel(NetPeer peer, bool reliable, byte id) : base(peer) - { - _id = id; - _reliable = reliable; - if (_reliable) - _ackPacket = new NetPacket(PacketProperty.Ack, 0) {ChannelId = id}; - } - - protected override bool SendNextPackets() - { - if (_reliable && OutgoingQueue.Count == 0) - { - long currentTime = DateTime.UtcNow.Ticks; - long packetHoldTime = currentTime - _lastPacketSendTime; - if (packetHoldTime >= Peer.ResendDelay * TimeSpan.TicksPerMillisecond) - { - var packet = _lastPacket; - if (packet != null) - { - _lastPacketSendTime = currentTime; - Peer.SendUserData(packet); - } - } - } - else - { - while (OutgoingQueue.TryDequeue(out var packet)) - { - _localSequence = (_localSequence + 1) % NetConstants.MaxSequence; - packet.Sequence = (ushort)_localSequence; - packet.ChannelId = _id; - Peer.SendUserData(packet); - - if (_reliable && OutgoingQueue.Count == 0) - { - _lastPacketSendTime = DateTime.UtcNow.Ticks; - _lastPacket = packet; - } - else - { - Peer.NetManager.PoolRecycle(packet); - } - } - } - - if (_reliable && _mustSendAck) - { - _mustSendAck = false; - _ackPacket.Sequence = _remoteSequence; - Peer.SendUserData(_ackPacket); - } - - return _lastPacket != null; - } - - public override bool ProcessPacket(NetPacket packet) - { - if (packet.IsFragmented) - return false; - if (packet.Property == PacketProperty.Ack) - { - if (_reliable && _lastPacket != null && packet.Sequence == _lastPacket.Sequence) - _lastPacket = null; - return false; - } - int relative = NetUtils.RelativeSequenceNumber(packet.Sequence, _remoteSequence); - bool packetProcessed = false; - if (packet.Sequence < NetConstants.MaxSequence && relative > 0) - { - if (Peer.NetManager.EnableStatistics) - { - Peer.Statistics.AddPacketLoss(relative - 1); - Peer.NetManager.Statistics.AddPacketLoss(relative - 1); - } - - _remoteSequence = packet.Sequence; - Peer.NetManager.CreateReceiveEvent( - packet, - _reliable ? DeliveryMethod.ReliableSequenced : DeliveryMethod.Sequenced, - (byte)(packet.ChannelId / NetConstants.ChannelTypeCount), - NetConstants.ChanneledHeaderSize, - Peer); - packetProcessed = true; - } - - if (_reliable) - { - _mustSendAck = true; - AddToPeerChannelSendQueue(); - } - - return packetProcessed; - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/SequencedChannel.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/SequencedChannel.cs.meta deleted file mode 100644 index a6b7dba..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/SequencedChannel.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c4e1f97908b70e642baea0fc22724282 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils.meta deleted file mode 100644 index 5c1f750..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 0c6e0e6809efaf74c8c6864f8129b89f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/CRC32C.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/CRC32C.cs deleted file mode 100644 index 7e85680..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/CRC32C.cs +++ /dev/null @@ -1,150 +0,0 @@ -#if NETCOREAPP3_0_OR_GREATER || NETCOREAPP3_1 || NET5_0 -using System; -using System.Runtime.InteropServices; -using System.Runtime.Intrinsics.X86; -#endif -#if NET5_0_OR_GREATER || NET5_0 -using System.Runtime.Intrinsics.Arm; -#endif - -namespace LiteNetLib.Utils -{ - //Implementation from Crc32.NET - public static class CRC32C - { - public const int ChecksumSize = 4; - private const uint Poly = 0x82F63B78u; - private static readonly uint[] Table; - - static CRC32C() - { -#if NETCOREAPP3_0_OR_GREATER || NETCOREAPP3_1 || NET5_0 - if (Sse42.IsSupported) - return; -#endif -#if NET5_0_OR_GREATER || NET5_0 - if (Crc32.IsSupported) - return; -#endif - Table = NetUtils.AllocatePinnedUninitializedArray(16 * 256); - for (uint i = 0; i < 256; i++) - { - uint res = i; - for (int t = 0; t < 16; t++) - { - for (int k = 0; k < 8; k++) - res = (res & 1) == 1 ? Poly ^ (res >> 1) : (res >> 1); - Table[t * 256 + i] = res; - } - } - } - - /// - /// Compute CRC32C for data - /// - /// input data - /// offset - /// length - /// CRC32C checksum - public static uint Compute(byte[] input, int offset, int length) - { - uint crcLocal = uint.MaxValue; -#if NETCOREAPP3_0_OR_GREATER || NETCOREAPP3_1 || NET5_0 - if (Sse42.IsSupported) - { - var data = new ReadOnlySpan(input, offset, length); - int processed = 0; - if (Sse42.X64.IsSupported && data.Length > sizeof(ulong)) - { - processed = data.Length / sizeof(ulong) * sizeof(ulong); - var ulongs = MemoryMarshal.Cast(data.Slice(0, processed)); - ulong crclong = crcLocal; - for (int i = 0; i < ulongs.Length; i++) - { - crclong = Sse42.X64.Crc32(crclong, ulongs[i]); - } - - crcLocal = (uint)crclong; - } - else if (data.Length > sizeof(uint)) - { - processed = data.Length / sizeof(uint) * sizeof(uint); - var uints = MemoryMarshal.Cast(data.Slice(0, processed)); - for (int i = 0; i < uints.Length; i++) - { - crcLocal = Sse42.Crc32(crcLocal, uints[i]); - } - } - - for (int i = processed; i < data.Length; i++) - { - crcLocal = Sse42.Crc32(crcLocal, data[i]); - } - - return crcLocal ^ uint.MaxValue; - } -#endif -#if NET5_0_OR_GREATER || NET5_0 - if (Crc32.IsSupported) - { - var data = new ReadOnlySpan(input, offset, length); - int processed = 0; - if (Crc32.Arm64.IsSupported && data.Length > sizeof(ulong)) - { - processed = data.Length / sizeof(ulong) * sizeof(ulong); - var ulongs = MemoryMarshal.Cast(data.Slice(0, processed)); - for (int i = 0; i < ulongs.Length; i++) - { - crcLocal = Crc32.Arm64.ComputeCrc32C(crcLocal, ulongs[i]); - } - } - else if (data.Length > sizeof(uint)) - { - processed = data.Length / sizeof(uint) * sizeof(uint); - var uints = MemoryMarshal.Cast(data.Slice(0, processed)); - for (int i = 0; i < uints.Length; i++) - { - crcLocal = Crc32.ComputeCrc32C(crcLocal, uints[i]); - } - } - - for (int i = processed; i < data.Length; i++) - { - crcLocal = Crc32.ComputeCrc32C(crcLocal, data[i]); - } - - return crcLocal ^ uint.MaxValue; - } -#endif - while (length >= 16) - { - var a = Table[(3 * 256) + input[offset + 12]] - ^ Table[(2 * 256) + input[offset + 13]] - ^ Table[(1 * 256) + input[offset + 14]] - ^ Table[(0 * 256) + input[offset + 15]]; - - var b = Table[(7 * 256) + input[offset + 8]] - ^ Table[(6 * 256) + input[offset + 9]] - ^ Table[(5 * 256) + input[offset + 10]] - ^ Table[(4 * 256) + input[offset + 11]]; - - var c = Table[(11 * 256) + input[offset + 4]] - ^ Table[(10 * 256) + input[offset + 5]] - ^ Table[(9 * 256) + input[offset + 6]] - ^ Table[(8 * 256) + input[offset + 7]]; - - var d = Table[(15 * 256) + ((byte)crcLocal ^ input[offset])] - ^ Table[(14 * 256) + ((byte)(crcLocal >> 8) ^ input[offset + 1])] - ^ Table[(13 * 256) + ((byte)(crcLocal >> 16) ^ input[offset + 2])] - ^ Table[(12 * 256) + ((crcLocal >> 24) ^ input[offset + 3])]; - - crcLocal = d ^ c ^ b ^ a; - offset += 16; - length -= 16; - } - while (--length >= 0) - crcLocal = Table[(byte)(crcLocal ^ input[offset++])] ^ crcLocal >> 8; - return crcLocal ^ uint.MaxValue; - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/CRC32C.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/CRC32C.cs.meta deleted file mode 100644 index d42bd93..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/CRC32C.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 912ba506b0945b743be5c4129177024c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/FastBitConverter.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/FastBitConverter.cs deleted file mode 100644 index 3ecd10c..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/FastBitConverter.cs +++ /dev/null @@ -1,175 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace LiteNetLib.Utils -{ - public static class FastBitConverter - { -#if (LITENETLIB_UNSAFE || LITENETLIB_UNSAFELIB || NETCOREAPP3_1 || NET5_0 || NETCOREAPP3_0_OR_GREATER) && !BIGENDIAN -#if LITENETLIB_UNSAFE - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe void GetBytes(byte[] bytes, int startIndex, T value) where T : unmanaged - { - int size = sizeof(T); - if (bytes.Length < startIndex + size) - ThrowIndexOutOfRangeException(); -#if LITENETLIB_UNSAFELIB || NETCOREAPP3_1 || NET5_0 || NETCOREAPP3_0_OR_GREATER - Unsafe.As(ref bytes[startIndex]) = value; -#else - fixed (byte* ptr = &bytes[startIndex]) - { -#if UNITY_ANDROID - // On some android systems, assigning *(T*)ptr throws a NRE if - // the ptr isn't aligned (i.e. if Position is 1,2,3,5, etc.). - // Here we have to use memcpy. - // - // => we can't get a pointer of a struct in C# without - // marshalling allocations - // => instead, we stack allocate an array of type T and use that - // => stackalloc avoids GC and is very fast. it only works for - // value types, but all blittable types are anyway. - T* valueBuffer = stackalloc T[1] { value }; - UnsafeUtility.MemCpy(ptr, valueBuffer, size); -#else - *(T*)ptr = value; -#endif - } -#endif - } -#else - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, T value) where T : unmanaged - { - if (bytes.Length < startIndex + Unsafe.SizeOf()) - ThrowIndexOutOfRangeException(); - Unsafe.As(ref bytes[startIndex]) = value; - } -#endif - - private static void ThrowIndexOutOfRangeException() => throw new IndexOutOfRangeException(); -#else - [StructLayout(LayoutKind.Explicit)] - private struct ConverterHelperDouble - { - [FieldOffset(0)] - public ulong Along; - - [FieldOffset(0)] - public double Adouble; - } - - [StructLayout(LayoutKind.Explicit)] - private struct ConverterHelperFloat - { - [FieldOffset(0)] - public int Aint; - - [FieldOffset(0)] - public float Afloat; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void WriteLittleEndian(byte[] buffer, int offset, ulong data) - { -#if BIGENDIAN - buffer[offset + 7] = (byte)(data); - buffer[offset + 6] = (byte)(data >> 8); - buffer[offset + 5] = (byte)(data >> 16); - buffer[offset + 4] = (byte)(data >> 24); - buffer[offset + 3] = (byte)(data >> 32); - buffer[offset + 2] = (byte)(data >> 40); - buffer[offset + 1] = (byte)(data >> 48); - buffer[offset ] = (byte)(data >> 56); -#else - buffer[offset] = (byte)(data); - buffer[offset + 1] = (byte)(data >> 8); - buffer[offset + 2] = (byte)(data >> 16); - buffer[offset + 3] = (byte)(data >> 24); - buffer[offset + 4] = (byte)(data >> 32); - buffer[offset + 5] = (byte)(data >> 40); - buffer[offset + 6] = (byte)(data >> 48); - buffer[offset + 7] = (byte)(data >> 56); -#endif - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void WriteLittleEndian(byte[] buffer, int offset, int data) - { -#if BIGENDIAN - buffer[offset + 3] = (byte)(data); - buffer[offset + 2] = (byte)(data >> 8); - buffer[offset + 1] = (byte)(data >> 16); - buffer[offset ] = (byte)(data >> 24); -#else - buffer[offset] = (byte)(data); - buffer[offset + 1] = (byte)(data >> 8); - buffer[offset + 2] = (byte)(data >> 16); - buffer[offset + 3] = (byte)(data >> 24); -#endif - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void WriteLittleEndian(byte[] buffer, int offset, short data) - { -#if BIGENDIAN - buffer[offset + 1] = (byte)(data); - buffer[offset ] = (byte)(data >> 8); -#else - buffer[offset] = (byte)(data); - buffer[offset + 1] = (byte)(data >> 8); -#endif - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, double value) - { - ConverterHelperDouble ch = new ConverterHelperDouble { Adouble = value }; - WriteLittleEndian(bytes, startIndex, ch.Along); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, float value) - { - ConverterHelperFloat ch = new ConverterHelperFloat { Afloat = value }; - WriteLittleEndian(bytes, startIndex, ch.Aint); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, short value) - { - WriteLittleEndian(bytes, startIndex, value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, ushort value) - { - WriteLittleEndian(bytes, startIndex, (short)value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, int value) - { - WriteLittleEndian(bytes, startIndex, value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, uint value) - { - WriteLittleEndian(bytes, startIndex, (int)value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, long value) - { - WriteLittleEndian(bytes, startIndex, (ulong)value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, ulong value) - { - WriteLittleEndian(bytes, startIndex, value); - } -#endif - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/FastBitConverter.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/FastBitConverter.cs.meta deleted file mode 100644 index 784434c..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/FastBitConverter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 21018f84ccfb8244e99b5ec22ceb91c9 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/INetSerializable.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/INetSerializable.cs deleted file mode 100644 index 92f14be..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/INetSerializable.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace LiteNetLib.Utils -{ - public interface INetSerializable - { - void Serialize(NetDataWriter writer); - void Deserialize(NetDataReader reader); - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/INetSerializable.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/INetSerializable.cs.meta deleted file mode 100644 index f055292..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/INetSerializable.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c26b17a74d3fb8b498fc89d253f1742a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataReader.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataReader.cs deleted file mode 100644 index 7022265..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataReader.cs +++ /dev/null @@ -1,680 +0,0 @@ -using System; -using System.Net; -using System.Text; - -namespace LiteNetLib.Utils -{ - public class NetDataReader - { - protected byte[] _data; - protected int _position; - protected int _dataSize; - private int _offset; - - public byte[] RawData => _data; - public int RawDataSize => _dataSize; - public int UserDataOffset => _offset; - public int UserDataSize => _dataSize - _offset; - public bool IsNull => _data == null; - public int Position => _position; - public bool EndOfData => _position == _dataSize; - public int AvailableBytes => _dataSize - _position; - - // Cache encoding instead of creating it with BinaryWriter each time - // 1000 readers before: 1MB GC, 30ms - // 1000 readers after: .8MB GC, 18ms - private static readonly UTF8Encoding _uTF8Encoding = new UTF8Encoding(false, true); - - public void SkipBytes(int count) - { - _position += count; - } - - public void SetPosition(int position) - { - _position = position; - } - - public void SetSource(NetDataWriter dataWriter) - { - _data = dataWriter.Data; - _position = 0; - _offset = 0; - _dataSize = dataWriter.Length; - } - - public void SetSource(byte[] source) - { - _data = source; - _position = 0; - _offset = 0; - _dataSize = source.Length; - } - - public void SetSource(byte[] source, int offset, int maxSize) - { - _data = source; - _position = offset; - _offset = offset; - _dataSize = maxSize; - } - - public NetDataReader() - { - - } - - public NetDataReader(NetDataWriter writer) - { - SetSource(writer); - } - - public NetDataReader(byte[] source) - { - SetSource(source); - } - - public NetDataReader(byte[] source, int offset, int maxSize) - { - SetSource(source, offset, maxSize); - } - - #region GetMethods - public IPEndPoint GetNetEndPoint() - { - string host = GetString(1000); - int port = GetInt(); - return NetUtils.MakeEndPoint(host, port); - } - - public byte GetByte() - { - byte res = _data[_position]; - _position += 1; - return res; - } - - public sbyte GetSByte() - { - var b = (sbyte)_data[_position]; - _position++; - return b; - } - - public bool[] GetBoolArray() - { - ushort size = BitConverter.ToUInt16(_data, _position); - _position += 2; - var arr = new bool[size]; - Buffer.BlockCopy(_data, _position, arr, 0, size); - _position += size; - return arr; - } - - public ushort[] GetUShortArray() - { - ushort size = BitConverter.ToUInt16(_data, _position); - _position += 2; - var arr = new ushort[size]; - Buffer.BlockCopy(_data, _position, arr, 0, size * 2); - _position += size * 2; - return arr; - } - - public short[] GetShortArray() - { - ushort size = BitConverter.ToUInt16(_data, _position); - _position += 2; - var arr = new short[size]; - Buffer.BlockCopy(_data, _position, arr, 0, size * 2); - _position += size * 2; - return arr; - } - - public long[] GetLongArray() - { - ushort size = BitConverter.ToUInt16(_data, _position); - _position += 2; - var arr = new long[size]; - Buffer.BlockCopy(_data, _position, arr, 0, size * 8); - _position += size * 8; - return arr; - } - - public ulong[] GetULongArray() - { - ushort size = BitConverter.ToUInt16(_data, _position); - _position += 2; - var arr = new ulong[size]; - Buffer.BlockCopy(_data, _position, arr, 0, size * 8); - _position += size * 8; - return arr; - } - - public int[] GetIntArray() - { - ushort size = BitConverter.ToUInt16(_data, _position); - _position += 2; - var arr = new int[size]; - Buffer.BlockCopy(_data, _position, arr, 0, size * 4); - _position += size * 4; - return arr; - } - - public uint[] GetUIntArray() - { - ushort size = BitConverter.ToUInt16(_data, _position); - _position += 2; - var arr = new uint[size]; - Buffer.BlockCopy(_data, _position, arr, 0, size * 4); - _position += size * 4; - return arr; - } - - public float[] GetFloatArray() - { - ushort size = BitConverter.ToUInt16(_data, _position); - _position += 2; - var arr = new float[size]; - Buffer.BlockCopy(_data, _position, arr, 0, size * 4); - _position += size * 4; - return arr; - } - - public double[] GetDoubleArray() - { - ushort size = BitConverter.ToUInt16(_data, _position); - _position += 2; - var arr = new double[size]; - Buffer.BlockCopy(_data, _position, arr, 0, size * 8); - _position += size * 8; - return arr; - } - - public string[] GetStringArray() - { - ushort arraySize = GetUShort(); - var arr = new string[arraySize]; - for (int i = 0; i < arraySize; i++) - { - arr[i] = GetString(); - } - return arr; - } - - public string[] GetStringArray(int maxStringLength) - { - ushort arraySize = GetUShort(); - var arr = new string[arraySize]; - for (int i = 0; i < arraySize; i++) - { - arr[i] = GetString(maxStringLength); - } - return arr; - } - - public bool GetBool() - { - bool res = _data[_position] > 0; - _position += 1; - return res; - } - - public char GetChar() - { - return (char)GetUShort(); - } - - public ushort GetUShort() - { - ushort result = BitConverter.ToUInt16(_data, _position); - _position += 2; - return result; - } - - public short GetShort() - { - short result = BitConverter.ToInt16(_data, _position); - _position += 2; - return result; - } - - public long GetLong() - { - long result = BitConverter.ToInt64(_data, _position); - _position += 8; - return result; - } - - public ulong GetULong() - { - ulong result = BitConverter.ToUInt64(_data, _position); - _position += 8; - return result; - } - - public int GetInt() - { - int result = BitConverter.ToInt32(_data, _position); - _position += 4; - return result; - } - - public uint GetUInt() - { - uint result = BitConverter.ToUInt32(_data, _position); - _position += 4; - return result; - } - - public float GetFloat() - { - float result = BitConverter.ToSingle(_data, _position); - _position += 4; - return result; - } - - public double GetDouble() - { - double result = BitConverter.ToDouble(_data, _position); - _position += 8; - return result; - } - - /// - /// Note that "maxLength" only limits the number of characters in a string, not its size in bytes. - /// - /// "string.Empty" if value > "maxLength" - public string GetString(int maxLength) - { - ushort size = GetUShort(); - if (size == 0) - { - return null; - } - - int actualSize = size - 1; - if (actualSize >= NetDataWriter.StringBufferMaxLength) - { - return null; - } - - ArraySegment data = GetBytesSegment(actualSize); - - return (maxLength > 0 && _uTF8Encoding.GetCharCount(data.Array, data.Offset, data.Count) > maxLength) ? - string.Empty : - _uTF8Encoding.GetString(data.Array, data.Offset, data.Count); - } - - public string GetString() - { - ushort size = GetUShort(); - if (size == 0) - { - return null; - } - - int actualSize = size - 1; - if (actualSize >= NetDataWriter.StringBufferMaxLength) - { - return null; - } - - ArraySegment data = GetBytesSegment(actualSize); - - return _uTF8Encoding.GetString(data.Array, data.Offset, data.Count); - } - - public ArraySegment GetBytesSegment(int count) - { - ArraySegment segment = new ArraySegment(_data, _position, count); - _position += count; - return segment; - } - - public ArraySegment GetRemainingBytesSegment() - { - ArraySegment segment = new ArraySegment(_data, _position, AvailableBytes); - _position = _data.Length; - return segment; - } - - public T Get() where T : INetSerializable, new() - { - var obj = new T(); - obj.Deserialize(this); - return obj; - } - - public byte[] GetRemainingBytes() - { - byte[] outgoingData = new byte[AvailableBytes]; - Buffer.BlockCopy(_data, _position, outgoingData, 0, AvailableBytes); - _position = _data.Length; - return outgoingData; - } - - public void GetBytes(byte[] destination, int start, int count) - { - Buffer.BlockCopy(_data, _position, destination, start, count); - _position += count; - } - - public void GetBytes(byte[] destination, int count) - { - Buffer.BlockCopy(_data, _position, destination, 0, count); - _position += count; - } - - public sbyte[] GetSBytesWithLength() - { - int length = GetInt(); - sbyte[] outgoingData = new sbyte[length]; - Buffer.BlockCopy(_data, _position, outgoingData, 0, length); - _position += length; - return outgoingData; - } - - public byte[] GetBytesWithLength() - { - int length = GetInt(); - byte[] outgoingData = new byte[length]; - Buffer.BlockCopy(_data, _position, outgoingData, 0, length); - _position += length; - return outgoingData; - } - #endregion - - #region PeekMethods - - public byte PeekByte() - { - return _data[_position]; - } - - public sbyte PeekSByte() - { - return (sbyte)_data[_position]; - } - - public bool PeekBool() - { - return _data[_position] > 0; - } - - public char PeekChar() - { - return (char)PeekUShort(); - } - - public ushort PeekUShort() - { - return BitConverter.ToUInt16(_data, _position); - } - - public short PeekShort() - { - return BitConverter.ToInt16(_data, _position); - } - - public long PeekLong() - { - return BitConverter.ToInt64(_data, _position); - } - - public ulong PeekULong() - { - return BitConverter.ToUInt64(_data, _position); - } - - public int PeekInt() - { - return BitConverter.ToInt32(_data, _position); - } - - public uint PeekUInt() - { - return BitConverter.ToUInt32(_data, _position); - } - - public float PeekFloat() - { - return BitConverter.ToSingle(_data, _position); - } - - public double PeekDouble() - { - return BitConverter.ToDouble(_data, _position); - } - - public string PeekString(int maxLength) - { - ushort size = PeekUShort(); - if (size == 0) - { - return null; - } - - int actualSize = size - 1; - if (actualSize >= NetDataWriter.StringBufferMaxLength) - { - return null; - } - - return (maxLength > 0 && _uTF8Encoding.GetCharCount(_data, _position + 2, actualSize) > maxLength) ? - string.Empty : - _uTF8Encoding.GetString(_data, _position + 2, actualSize); - } - - public string PeekString() - { - ushort size = PeekUShort(); - if (size == 0) - { - return null; - } - - int actualSize = size - 1; - if (actualSize >= NetDataWriter.StringBufferMaxLength) - { - return null; - } - - return _uTF8Encoding.GetString(_data, _position + 2, actualSize); - } - #endregion - - #region TryGetMethods - public bool TryGetByte(out byte result) - { - if (AvailableBytes >= 1) - { - result = GetByte(); - return true; - } - result = 0; - return false; - } - - public bool TryGetSByte(out sbyte result) - { - if (AvailableBytes >= 1) - { - result = GetSByte(); - return true; - } - result = 0; - return false; - } - - public bool TryGetBool(out bool result) - { - if (AvailableBytes >= 1) - { - result = GetBool(); - return true; - } - result = false; - return false; - } - - public bool TryGetChar(out char result) - { - if (!TryGetUShort(out ushort uShortValue)) - { - result = '\0'; - return false; - } - result = (char)uShortValue; - return true; - } - - public bool TryGetShort(out short result) - { - if (AvailableBytes >= 2) - { - result = GetShort(); - return true; - } - result = 0; - return false; - } - - public bool TryGetUShort(out ushort result) - { - if (AvailableBytes >= 2) - { - result = GetUShort(); - return true; - } - result = 0; - return false; - } - - public bool TryGetInt(out int result) - { - if (AvailableBytes >= 4) - { - result = GetInt(); - return true; - } - result = 0; - return false; - } - - public bool TryGetUInt(out uint result) - { - if (AvailableBytes >= 4) - { - result = GetUInt(); - return true; - } - result = 0; - return false; - } - - public bool TryGetLong(out long result) - { - if (AvailableBytes >= 8) - { - result = GetLong(); - return true; - } - result = 0; - return false; - } - - public bool TryGetULong(out ulong result) - { - if (AvailableBytes >= 8) - { - result = GetULong(); - return true; - } - result = 0; - return false; - } - - public bool TryGetFloat(out float result) - { - if (AvailableBytes >= 4) - { - result = GetFloat(); - return true; - } - result = 0; - return false; - } - - public bool TryGetDouble(out double result) - { - if (AvailableBytes >= 8) - { - result = GetDouble(); - return true; - } - result = 0; - return false; - } - - public bool TryGetString(out string result) - { - if (AvailableBytes >= 2) - { - ushort strSize = PeekUShort(); - if (AvailableBytes >= strSize + 1) - { - result = GetString(); - return true; - } - } - result = null; - return false; - } - - public bool TryGetStringArray(out string[] result) - { - ushort strArrayLength; - if (!TryGetUShort(out strArrayLength)) - { - result = null; - return false; - } - - result = new string[strArrayLength]; - for (int i = 0; i < strArrayLength; i++) - { - if (!TryGetString(out result[i])) - { - result = null; - return false; - } - } - - return true; - } - - public bool TryGetBytesWithLength(out byte[] result) - { - if (AvailableBytes >= 4) - { - var length = PeekInt(); - if (length >= 0 && AvailableBytes >= length + 4) - { - result = GetBytesWithLength(); - return true; - } - } - result = null; - return false; - } - #endregion - - public void Clear() - { - _position = 0; - _dataSize = 0; - _data = null; - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataReader.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataReader.cs.meta deleted file mode 100644 index 31be4dd..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataReader.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2876e12b475627f448ca5a6850748bc3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataWriter.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataWriter.cs deleted file mode 100644 index 1c9d724..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataWriter.cs +++ /dev/null @@ -1,379 +0,0 @@ -using System; -using System.Net; -using System.Runtime.CompilerServices; -using System.Text; - -namespace LiteNetLib.Utils -{ - public class NetDataWriter - { - protected byte[] _data; - protected int _position; - private const int InitialSize = 64; - private readonly bool _autoResize; - - public int Capacity => _data.Length; - public byte[] Data => _data; - public int Length => _position; - - // Cache encoding instead of creating it with BinaryWriter each time - // 1000 readers before: 1MB GC, 30ms - // 1000 readers after: .8MB GC, 18ms - private static readonly UTF8Encoding _uTF8Encoding = new UTF8Encoding(false, true); - public const int StringBufferMaxLength = 1024 * 32; // <- short.MaxValue + 1 - private readonly byte[] _stringBuffer = new byte[StringBufferMaxLength]; - - public NetDataWriter() : this(true, InitialSize) - { - } - - public NetDataWriter(bool autoResize) : this(autoResize, InitialSize) - { - } - - public NetDataWriter(bool autoResize, int initialSize) - { - _data = new byte[initialSize]; - _autoResize = autoResize; - } - - /// - /// Creates NetDataWriter from existing ByteArray - /// - /// Source byte array - /// Copy array to new location or use existing - public static NetDataWriter FromBytes(byte[] bytes, bool copy) - { - if (copy) - { - var netDataWriter = new NetDataWriter(true, bytes.Length); - netDataWriter.Put(bytes); - return netDataWriter; - } - return new NetDataWriter(true, 0) {_data = bytes, _position = bytes.Length}; - } - - /// - /// Creates NetDataWriter from existing ByteArray (always copied data) - /// - /// Source byte array - /// Offset of array - /// Length of array - public static NetDataWriter FromBytes(byte[] bytes, int offset, int length) - { - var netDataWriter = new NetDataWriter(true, bytes.Length); - netDataWriter.Put(bytes, offset, length); - return netDataWriter; - } - - public static NetDataWriter FromString(string value) - { - var netDataWriter = new NetDataWriter(); - netDataWriter.Put(value); - return netDataWriter; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ResizeIfNeed(int newSize) - { - if (_data.Length < newSize) - { - Array.Resize(ref _data, Math.Max(newSize, _data.Length * 2)); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void EnsureFit(int additionalSize) - { - if (_data.Length < _position + additionalSize) - { - Array.Resize(ref _data, Math.Max(_position + additionalSize, _data.Length * 2)); - } - } - - public void Reset(int size) - { - ResizeIfNeed(size); - _position = 0; - } - - public void Reset() - { - _position = 0; - } - - public byte[] CopyData() - { - byte[] resultData = new byte[_position]; - Buffer.BlockCopy(_data, 0, resultData, 0, _position); - return resultData; - } - - /// - /// Sets position of NetDataWriter to rewrite previous values - /// - /// new byte position - /// previous position of data writer - public int SetPosition(int position) - { - int prevPosition = _position; - _position = position; - return prevPosition; - } - - public void Put(float value) - { - if (_autoResize) - ResizeIfNeed(_position + 4); - FastBitConverter.GetBytes(_data, _position, value); - _position += 4; - } - - public void Put(double value) - { - if (_autoResize) - ResizeIfNeed(_position + 8); - FastBitConverter.GetBytes(_data, _position, value); - _position += 8; - } - - public void Put(long value) - { - if (_autoResize) - ResizeIfNeed(_position + 8); - FastBitConverter.GetBytes(_data, _position, value); - _position += 8; - } - - public void Put(ulong value) - { - if (_autoResize) - ResizeIfNeed(_position + 8); - FastBitConverter.GetBytes(_data, _position, value); - _position += 8; - } - - public void Put(int value) - { - if (_autoResize) - ResizeIfNeed(_position + 4); - FastBitConverter.GetBytes(_data, _position, value); - _position += 4; - } - - public void Put(uint value) - { - if (_autoResize) - ResizeIfNeed(_position + 4); - FastBitConverter.GetBytes(_data, _position, value); - _position += 4; - } - - public void Put(char value) - { - Put((ushort)value); - } - - public void Put(ushort value) - { - if (_autoResize) - ResizeIfNeed(_position + 2); - FastBitConverter.GetBytes(_data, _position, value); - _position += 2; - } - - public void Put(short value) - { - if (_autoResize) - ResizeIfNeed(_position + 2); - FastBitConverter.GetBytes(_data, _position, value); - _position += 2; - } - - public void Put(sbyte value) - { - if (_autoResize) - ResizeIfNeed(_position + 1); - _data[_position] = (byte)value; - _position++; - } - - public void Put(byte value) - { - if (_autoResize) - ResizeIfNeed(_position + 1); - _data[_position] = value; - _position++; - } - - public void Put(byte[] data, int offset, int length) - { - if (_autoResize) - ResizeIfNeed(_position + length); - Buffer.BlockCopy(data, offset, _data, _position, length); - _position += length; - } - - public void Put(byte[] data) - { - if (_autoResize) - ResizeIfNeed(_position + data.Length); - Buffer.BlockCopy(data, 0, _data, _position, data.Length); - _position += data.Length; - } - - public void PutSBytesWithLength(sbyte[] data, int offset, int length) - { - if (_autoResize) - ResizeIfNeed(_position + length + 4); - FastBitConverter.GetBytes(_data, _position, length); - Buffer.BlockCopy(data, offset, _data, _position + 4, length); - _position += length + 4; - } - - public void PutSBytesWithLength(sbyte[] data) - { - if (_autoResize) - ResizeIfNeed(_position + data.Length + 4); - FastBitConverter.GetBytes(_data, _position, data.Length); - Buffer.BlockCopy(data, 0, _data, _position + 4, data.Length); - _position += data.Length + 4; - } - - public void PutBytesWithLength(byte[] data, int offset, int length) - { - if (_autoResize) - ResizeIfNeed(_position + length + 4); - FastBitConverter.GetBytes(_data, _position, length); - Buffer.BlockCopy(data, offset, _data, _position + 4, length); - _position += length + 4; - } - - public void PutBytesWithLength(byte[] data) - { - if (_autoResize) - ResizeIfNeed(_position + data.Length + 4); - FastBitConverter.GetBytes(_data, _position, data.Length); - Buffer.BlockCopy(data, 0, _data, _position + 4, data.Length); - _position += data.Length + 4; - } - - public void Put(bool value) - { - Put((byte)(value ? 1 : 0)); - } - - private void PutArray(Array arr, int sz) - { - ushort length = arr == null ? (ushort) 0 : (ushort)arr.Length; - sz *= length; - if (_autoResize) - ResizeIfNeed(_position + sz + 2); - FastBitConverter.GetBytes(_data, _position, length); - if (arr != null) - Buffer.BlockCopy(arr, 0, _data, _position + 2, sz); - _position += sz + 2; - } - - public void PutArray(float[] value) - { - PutArray(value, 4); - } - - public void PutArray(double[] value) - { - PutArray(value, 8); - } - - public void PutArray(long[] value) - { - PutArray(value, 8); - } - - public void PutArray(ulong[] value) - { - PutArray(value, 8); - } - - public void PutArray(int[] value) - { - PutArray(value, 4); - } - - public void PutArray(uint[] value) - { - PutArray(value, 4); - } - - public void PutArray(ushort[] value) - { - PutArray(value, 2); - } - - public void PutArray(short[] value) - { - PutArray(value, 2); - } - - public void PutArray(bool[] value) - { - PutArray(value, 1); - } - - public void PutArray(string[] value) - { - ushort strArrayLength = value == null ? (ushort)0 : (ushort)value.Length; - Put(strArrayLength); - for (int i = 0; i < strArrayLength; i++) - Put(value[i]); - } - - public void PutArray(string[] value, int strMaxLength) - { - ushort strArrayLength = value == null ? (ushort)0 : (ushort)value.Length; - Put(strArrayLength); - for (int i = 0; i < strArrayLength; i++) - Put(value[i], strMaxLength); - } - - public void Put(IPEndPoint endPoint) - { - Put(endPoint.Address.ToString()); - Put(endPoint.Port); - } - - public void Put(string value) - { - Put(value, 0); - } - - /// - /// Note that "maxLength" only limits the number of characters in a string, not its size in bytes. - /// - public void Put(string value, int maxLength) - { - if (value == null) - { - Put((ushort)0); - return; - } - - int length = maxLength > 0 && value.Length > maxLength ? maxLength : value.Length; - int size = _uTF8Encoding.GetBytes(value, 0, length, _stringBuffer, 0); - - if (size >= StringBufferMaxLength) - { - Put((ushort)0); - return; - } - - Put(checked((ushort)(size + 1))); - Put(_stringBuffer, 0, size); - } - - public void Put(T obj) where T : INetSerializable - { - obj.Serialize(this); - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataWriter.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataWriter.cs.meta deleted file mode 100644 index 448549c..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetDataWriter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: bb3b55fb59ddd9044b1fd56b8543053b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetPacketProcessor.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetPacketProcessor.cs deleted file mode 100644 index 007d520..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetPacketProcessor.cs +++ /dev/null @@ -1,296 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LiteNetLib.Utils -{ - public class NetPacketProcessor - { - private static class HashCache - { - public static readonly ulong Id; - - //FNV-1 64 bit hash - static HashCache() - { - ulong hash = 14695981039346656037UL; //offset - string typeName = typeof(T).ToString(); - for (var i = 0; i < typeName.Length; i++) - { - hash ^= typeName[i]; - hash *= 1099511628211UL; //prime - } - Id = hash; - } - } - - protected delegate void SubscribeDelegate(NetDataReader reader, object userData); - private readonly NetSerializer _netSerializer; - private readonly Dictionary _callbacks = new Dictionary(); - private readonly NetDataWriter _netDataWriter = new NetDataWriter(); - - public NetPacketProcessor() - { - _netSerializer = new NetSerializer(); - } - - public NetPacketProcessor(int maxStringLength) - { - _netSerializer = new NetSerializer(maxStringLength); - } - - protected virtual ulong GetHash() - { - return HashCache.Id; - } - - protected virtual SubscribeDelegate GetCallbackFromData(NetDataReader reader) - { - ulong hash = reader.GetULong(); - if (!_callbacks.TryGetValue(hash, out var action)) - { - throw new ParseException("Undefined packet in NetDataReader"); - } - return action; - } - - protected virtual void WriteHash(NetDataWriter writer) - { - writer.Put(GetHash()); - } - - /// - /// Register nested property type - /// - /// INetSerializable structure - public void RegisterNestedType() where T : struct, INetSerializable - { - _netSerializer.RegisterNestedType(); - } - - /// - /// Register nested property type - /// - /// - /// - public void RegisterNestedType(Action writeDelegate, Func readDelegate) - { - _netSerializer.RegisterNestedType(writeDelegate, readDelegate); - } - - /// - /// Register nested property type - /// - /// INetSerializable class - public void RegisterNestedType(Func constructor) where T : class, INetSerializable - { - _netSerializer.RegisterNestedType(constructor); - } - - /// - /// Reads all available data from NetDataReader and calls OnReceive delegates - /// - /// NetDataReader with packets data - public void ReadAllPackets(NetDataReader reader) - { - while (reader.AvailableBytes > 0) - ReadPacket(reader); - } - - /// - /// Reads all available data from NetDataReader and calls OnReceive delegates - /// - /// NetDataReader with packets data - /// Argument that passed to OnReceivedEvent - /// Malformed packet - public void ReadAllPackets(NetDataReader reader, object userData) - { - while (reader.AvailableBytes > 0) - ReadPacket(reader, userData); - } - - /// - /// Reads one packet from NetDataReader and calls OnReceive delegate - /// - /// NetDataReader with packet - /// Malformed packet - public void ReadPacket(NetDataReader reader) - { - ReadPacket(reader, null); - } - - public void Send(NetPeer peer, T packet, DeliveryMethod options) where T : class, new() - { - _netDataWriter.Reset(); - Write(_netDataWriter, packet); - peer.Send(_netDataWriter, options); - } - - public void SendNetSerializable(NetPeer peer, ref T packet, DeliveryMethod options) where T : INetSerializable - { - _netDataWriter.Reset(); - WriteNetSerializable(_netDataWriter, ref packet); - peer.Send(_netDataWriter, options); - } - - public void Send(NetManager manager, T packet, DeliveryMethod options) where T : class, new() - { - _netDataWriter.Reset(); - Write(_netDataWriter, packet); - manager.SendToAll(_netDataWriter, options); - } - - public void SendNetSerializable(NetManager manager, ref T packet, DeliveryMethod options) where T : INetSerializable - { - _netDataWriter.Reset(); - WriteNetSerializable(_netDataWriter, ref packet); - manager.SendToAll(_netDataWriter, options); - } - - public void Write(NetDataWriter writer, T packet) where T : class, new() - { - WriteHash(writer); - _netSerializer.Serialize(writer, packet); - } - - public void WriteNetSerializable(NetDataWriter writer, ref T packet) where T : INetSerializable - { - WriteHash(writer); - packet.Serialize(writer); - } - - /// - /// Reads one packet from NetDataReader and calls OnReceive delegate - /// - /// NetDataReader with packet - /// Argument that passed to OnReceivedEvent - /// Malformed packet - public void ReadPacket(NetDataReader reader, object userData) - { - GetCallbackFromData(reader)(reader, userData); - } - - /// - /// Register and subscribe to packet receive event - /// - /// event that will be called when packet deserialized with ReadPacket method - /// Method that constructs packet instead of slow Activator.CreateInstance - /// 's fields are not supported, or it has no fields - public void Subscribe(Action onReceive, Func packetConstructor) where T : class, new() - { - _netSerializer.Register(); - _callbacks[GetHash()] = (reader, userData) => - { - var reference = packetConstructor(); - _netSerializer.Deserialize(reader, reference); - onReceive(reference); - }; - } - - /// - /// Register and subscribe to packet receive event (with userData) - /// - /// event that will be called when packet deserialized with ReadPacket method - /// Method that constructs packet instead of slow Activator.CreateInstance - /// 's fields are not supported, or it has no fields - public void Subscribe(Action onReceive, Func packetConstructor) where T : class, new() - { - _netSerializer.Register(); - _callbacks[GetHash()] = (reader, userData) => - { - var reference = packetConstructor(); - _netSerializer.Deserialize(reader, reference); - onReceive(reference, (TUserData)userData); - }; - } - - /// - /// Register and subscribe to packet receive event - /// This method will overwrite last received packet class on receive (less garbage) - /// - /// event that will be called when packet deserialized with ReadPacket method - /// 's fields are not supported, or it has no fields - public void SubscribeReusable(Action onReceive) where T : class, new() - { - _netSerializer.Register(); - var reference = new T(); - _callbacks[GetHash()] = (reader, userData) => - { - _netSerializer.Deserialize(reader, reference); - onReceive(reference); - }; - } - - /// - /// Register and subscribe to packet receive event - /// This method will overwrite last received packet class on receive (less garbage) - /// - /// event that will be called when packet deserialized with ReadPacket method - /// 's fields are not supported, or it has no fields - public void SubscribeReusable(Action onReceive) where T : class, new() - { - _netSerializer.Register(); - var reference = new T(); - _callbacks[GetHash()] = (reader, userData) => - { - _netSerializer.Deserialize(reader, reference); - onReceive(reference, (TUserData)userData); - }; - } - - public void SubscribeNetSerializable( - Action onReceive, - Func packetConstructor) where T : INetSerializable - { - _callbacks[GetHash()] = (reader, userData) => - { - var pkt = packetConstructor(); - pkt.Deserialize(reader); - onReceive(pkt, (TUserData)userData); - }; - } - - public void SubscribeNetSerializable( - Action onReceive, - Func packetConstructor) where T : INetSerializable - { - _callbacks[GetHash()] = (reader, userData) => - { - var pkt = packetConstructor(); - pkt.Deserialize(reader); - onReceive(pkt); - }; - } - - public void SubscribeNetSerializable( - Action onReceive) where T : INetSerializable, new() - { - var reference = new T(); - _callbacks[GetHash()] = (reader, userData) => - { - reference.Deserialize(reader); - onReceive(reference, (TUserData)userData); - }; - } - - public void SubscribeNetSerializable( - Action onReceive) where T : INetSerializable, new() - { - var reference = new T(); - _callbacks[GetHash()] = (reader, userData) => - { - reference.Deserialize(reader); - onReceive(reference); - }; - } - - /// - /// Remove any subscriptions by type - /// - /// Packet type - /// true if remove is success - public bool RemoveSubscription() - { - return _callbacks.Remove(GetHash()); - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetPacketProcessor.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetPacketProcessor.cs.meta deleted file mode 100644 index e076011..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetPacketProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f0d5a653362556943a36db010a601057 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetSerializer.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetSerializer.cs deleted file mode 100644 index 63f6cd6..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetSerializer.cs +++ /dev/null @@ -1,738 +0,0 @@ -using System; -using System.Reflection; -using System.Collections.Generic; -using System.Net; -using System.Runtime.Serialization; - -namespace LiteNetLib.Utils -{ - public class InvalidTypeException : ArgumentException - { - public InvalidTypeException(string message) : base(message) { } - } - - public class ParseException : Exception - { - public ParseException(string message) : base(message) { } - } - - public class NetSerializer - { - private enum CallType - { - Basic, - Array, - List - } - - private abstract class FastCall - { - public CallType Type; - public virtual void Init(MethodInfo getMethod, MethodInfo setMethod, CallType type) { Type = type; } - public abstract void Read(T inf, NetDataReader r); - public abstract void Write(T inf, NetDataWriter w); - public abstract void ReadArray(T inf, NetDataReader r); - public abstract void WriteArray(T inf, NetDataWriter w); - public abstract void ReadList(T inf, NetDataReader r); - public abstract void WriteList(T inf, NetDataWriter w); - } - - private abstract class FastCallSpecific : FastCall - { - protected Func Getter; - protected Action Setter; - protected Func GetterArr; - protected Action SetterArr; - protected Func> GetterList; - protected Action> SetterList; - - public override void ReadArray(TClass inf, NetDataReader r) { throw new InvalidTypeException("Unsupported type: " + typeof(TProperty) + "[]"); } - public override void WriteArray(TClass inf, NetDataWriter w) { throw new InvalidTypeException("Unsupported type: " + typeof(TProperty) + "[]"); } - public override void ReadList(TClass inf, NetDataReader r) { throw new InvalidTypeException("Unsupported type: List<" + typeof(TProperty) + ">"); } - public override void WriteList(TClass inf, NetDataWriter w) { throw new InvalidTypeException("Unsupported type: List<" + typeof(TProperty) + ">"); } - - protected TProperty[] ReadArrayHelper(TClass inf, NetDataReader r) - { - ushort count = r.GetUShort(); - var arr = GetterArr(inf); - arr = arr == null || arr.Length != count ? new TProperty[count] : arr; - SetterArr(inf, arr); - return arr; - } - - protected TProperty[] WriteArrayHelper(TClass inf, NetDataWriter w) - { - var arr = GetterArr(inf); - w.Put((ushort)arr.Length); - return arr; - } - - protected List ReadListHelper(TClass inf, NetDataReader r, out int len) - { - len = r.GetUShort(); - var list = GetterList(inf); - if (list == null) - { - list = new List(len); - SetterList(inf, list); - } - return list; - } - - protected List WriteListHelper(TClass inf, NetDataWriter w, out int len) - { - var list = GetterList(inf); - if (list == null) - { - len = 0; - w.Put(0); - return null; - } - len = list.Count; - w.Put((ushort)len); - return list; - } - - public override void Init(MethodInfo getMethod, MethodInfo setMethod, CallType type) - { - base.Init(getMethod, setMethod, type); - switch (type) - { - case CallType.Array: - GetterArr = (Func)Delegate.CreateDelegate(typeof(Func), getMethod); - SetterArr = (Action)Delegate.CreateDelegate(typeof(Action), setMethod); - break; - case CallType.List: - GetterList = (Func>)Delegate.CreateDelegate(typeof(Func>), getMethod); - SetterList = (Action>)Delegate.CreateDelegate(typeof(Action>), setMethod); - break; - default: - Getter = (Func)Delegate.CreateDelegate(typeof(Func), getMethod); - Setter = (Action)Delegate.CreateDelegate(typeof(Action), setMethod); - break; - } - } - } - - private abstract class FastCallSpecificAuto : FastCallSpecific - { - protected abstract void ElementRead(NetDataReader r, out TProperty prop); - protected abstract void ElementWrite(NetDataWriter w, ref TProperty prop); - - public override void Read(TClass inf, NetDataReader r) - { - ElementRead(r, out var elem); - Setter(inf, elem); - } - - public override void Write(TClass inf, NetDataWriter w) - { - var elem = Getter(inf); - ElementWrite(w, ref elem); - } - - public override void ReadArray(TClass inf, NetDataReader r) - { - var arr = ReadArrayHelper(inf, r); - for (int i = 0; i < arr.Length; i++) - ElementRead(r, out arr[i]); - } - - public override void WriteArray(TClass inf, NetDataWriter w) - { - var arr = WriteArrayHelper(inf, w); - for (int i = 0; i < arr.Length; i++) - ElementWrite(w, ref arr[i]); - } - } - - private sealed class FastCallStatic : FastCallSpecific - { - private readonly Action _writer; - private readonly Func _reader; - - public FastCallStatic(Action write, Func read) - { - _writer = write; - _reader = read; - } - - public override void Read(TClass inf, NetDataReader r) { Setter(inf, _reader(r)); } - public override void Write(TClass inf, NetDataWriter w) { _writer(w, Getter(inf)); } - - public override void ReadList(TClass inf, NetDataReader r) - { - var list = ReadListHelper(inf, r, out int len); - int listCount = list.Count; - for (int i = 0; i < len; i++) - { - if (i < listCount) - list[i] = _reader(r); - else - list.Add(_reader(r)); - } - if (len < listCount) - list.RemoveRange(len, listCount - len); - } - - public override void WriteList(TClass inf, NetDataWriter w) - { - var list = WriteListHelper(inf, w, out int len); - for (int i = 0; i < len; i++) - _writer(w, list[i]); - } - - public override void ReadArray(TClass inf, NetDataReader r) - { - var arr = ReadArrayHelper(inf, r); - int len = arr.Length; - for (int i = 0; i < len; i++) - arr[i] = _reader(r); - } - - public override void WriteArray(TClass inf, NetDataWriter w) - { - var arr = WriteArrayHelper(inf, w); - int len = arr.Length; - for (int i = 0; i < len; i++) - _writer(w, arr[i]); - } - } - - private sealed class FastCallStruct : FastCallSpecific where TProperty : struct, INetSerializable - { - private TProperty _p; - - public override void Read(TClass inf, NetDataReader r) - { - _p.Deserialize(r); - Setter(inf, _p); - } - - public override void Write(TClass inf, NetDataWriter w) - { - _p = Getter(inf); - _p.Serialize(w); - } - - public override void ReadList(TClass inf, NetDataReader r) - { - var list = ReadListHelper(inf, r, out int len); - int listCount = list.Count; - for (int i = 0; i < len; i++) - { - var itm = default(TProperty); - itm.Deserialize(r); - if(i < listCount) - list[i] = itm; - else - list.Add(itm); - } - if (len < listCount) - list.RemoveRange(len, listCount - len); - } - - public override void WriteList(TClass inf, NetDataWriter w) - { - var list = WriteListHelper(inf, w, out int len); - for (int i = 0; i < len; i++) - list[i].Serialize(w); - } - - public override void ReadArray(TClass inf, NetDataReader r) - { - var arr = ReadArrayHelper(inf, r); - int len = arr.Length; - for (int i = 0; i < len; i++) - arr[i].Deserialize(r); - } - - public override void WriteArray(TClass inf, NetDataWriter w) - { - var arr = WriteArrayHelper(inf, w); - int len = arr.Length; - for (int i = 0; i < len; i++) - arr[i].Serialize(w); - } - } - - private sealed class FastCallClass : FastCallSpecific where TProperty : class, INetSerializable - { - private readonly Func _constructor; - public FastCallClass(Func constructor) { _constructor = constructor; } - - public override void Read(TClass inf, NetDataReader r) - { - var p = _constructor(); - p.Deserialize(r); - Setter(inf, p); - } - - public override void Write(TClass inf, NetDataWriter w) - { - var p = Getter(inf); - p?.Serialize(w); - } - - public override void ReadList(TClass inf, NetDataReader r) - { - var list = ReadListHelper(inf, r, out int len); - int listCount = list.Count; - for (int i = 0; i < len; i++) - { - if (i < listCount) - { - list[i].Deserialize(r); - } - else - { - var itm = _constructor(); - itm.Deserialize(r); - list.Add(itm); - } - } - if (len < listCount) - list.RemoveRange(len, listCount - len); - } - - public override void WriteList(TClass inf, NetDataWriter w) - { - var list = WriteListHelper(inf, w, out int len); - for (int i = 0; i < len; i++) - list[i].Serialize(w); - } - - public override void ReadArray(TClass inf, NetDataReader r) - { - var arr = ReadArrayHelper(inf, r); - int len = arr.Length; - for (int i = 0; i < len; i++) - { - arr[i] = _constructor(); - arr[i].Deserialize(r); - } - } - - public override void WriteArray(TClass inf, NetDataWriter w) - { - var arr = WriteArrayHelper(inf, w); - int len = arr.Length; - for (int i = 0; i < len; i++) - arr[i].Serialize(w); - } - } - - private class IntSerializer : FastCallSpecific - { - public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetInt()); } - public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); } - public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetIntArray()); } - public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); } - } - - private class UIntSerializer : FastCallSpecific - { - public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetUInt()); } - public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); } - public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetUIntArray()); } - public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); } - } - - private class ShortSerializer : FastCallSpecific - { - public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetShort()); } - public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); } - public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetShortArray()); } - public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); } - } - - private class UShortSerializer : FastCallSpecific - { - public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetUShort()); } - public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); } - public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetUShortArray()); } - public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); } - } - - private class LongSerializer : FastCallSpecific - { - public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetLong()); } - public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); } - public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetLongArray()); } - public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); } - } - - private class ULongSerializer : FastCallSpecific - { - public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetULong()); } - public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); } - public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetULongArray()); } - public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); } - } - - private class ByteSerializer : FastCallSpecific - { - public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetByte()); } - public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); } - public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetBytesWithLength()); } - public override void WriteArray(T inf, NetDataWriter w) { w.PutBytesWithLength(GetterArr(inf)); } - } - - private class SByteSerializer : FastCallSpecific - { - public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetSByte()); } - public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); } - public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetSBytesWithLength()); } - public override void WriteArray(T inf, NetDataWriter w) { w.PutSBytesWithLength(GetterArr(inf)); } - } - - private class FloatSerializer : FastCallSpecific - { - public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetFloat()); } - public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); } - public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetFloatArray()); } - public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); } - } - - private class DoubleSerializer : FastCallSpecific - { - public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetDouble()); } - public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); } - public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetDoubleArray()); } - public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); } - } - - private class BoolSerializer : FastCallSpecific - { - public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetBool()); } - public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); } - public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetBoolArray()); } - public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); } - } - - private class CharSerializer : FastCallSpecificAuto - { - protected override void ElementWrite(NetDataWriter w, ref char prop) { w.Put(prop); } - protected override void ElementRead(NetDataReader r, out char prop) { prop = r.GetChar(); } - } - - private class IPEndPointSerializer : FastCallSpecificAuto - { - protected override void ElementWrite(NetDataWriter w, ref IPEndPoint prop) { w.Put(prop); } - protected override void ElementRead(NetDataReader r, out IPEndPoint prop) { prop = r.GetNetEndPoint(); } - } - - private class StringSerializer : FastCallSpecific - { - private readonly int _maxLength; - public StringSerializer(int maxLength) { _maxLength = maxLength > 0 ? maxLength : short.MaxValue; } - public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetString(_maxLength)); } - public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf), _maxLength); } - public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetStringArray(_maxLength)); } - public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf), _maxLength); } - } - - private class EnumByteSerializer : FastCall - { - protected readonly PropertyInfo Property; - protected readonly Type PropertyType; - public EnumByteSerializer(PropertyInfo property, Type propertyType) - { - Property = property; - PropertyType = propertyType; - } - public override void Read(T inf, NetDataReader r) { Property.SetValue(inf, Enum.ToObject(PropertyType, r.GetByte()), null); } - public override void Write(T inf, NetDataWriter w) { w.Put((byte)Property.GetValue(inf, null)); } - public override void ReadArray(T inf, NetDataReader r) { throw new InvalidTypeException("Unsupported type: Enum[]"); } - public override void WriteArray(T inf, NetDataWriter w) { throw new InvalidTypeException("Unsupported type: Enum[]"); } - public override void ReadList(T inf, NetDataReader r) { throw new InvalidTypeException("Unsupported type: List"); } - public override void WriteList(T inf, NetDataWriter w) { throw new InvalidTypeException("Unsupported type: List"); } - } - - private class EnumIntSerializer : EnumByteSerializer - { - public EnumIntSerializer(PropertyInfo property, Type propertyType) : base(property, propertyType) { } - public override void Read(T inf, NetDataReader r) { Property.SetValue(inf, Enum.ToObject(PropertyType, r.GetInt()), null); } - public override void Write(T inf, NetDataWriter w) { w.Put((int)Property.GetValue(inf, null)); } - } - - private sealed class ClassInfo - { - public static ClassInfo Instance; - private readonly FastCall[] _serializers; - private readonly int _membersCount; - - public ClassInfo(List> serializers) - { - _membersCount = serializers.Count; - _serializers = serializers.ToArray(); - } - - public void Write(T obj, NetDataWriter writer) - { - for (int i = 0; i < _membersCount; i++) - { - var s = _serializers[i]; - if (s.Type == CallType.Basic) - s.Write(obj, writer); - else if (s.Type == CallType.Array) - s.WriteArray(obj, writer); - else - s.WriteList(obj, writer); - } - } - - public void Read(T obj, NetDataReader reader) - { - for (int i = 0; i < _membersCount; i++) - { - var s = _serializers[i]; - if (s.Type == CallType.Basic) - s.Read(obj, reader); - else if(s.Type == CallType.Array) - s.ReadArray(obj, reader); - else - s.ReadList(obj, reader); - } - } - } - - private abstract class CustomType - { - public abstract FastCall Get(); - } - - private sealed class CustomTypeStruct : CustomType where TProperty : struct, INetSerializable - { - public override FastCall Get() { return new FastCallStruct(); } - } - - private sealed class CustomTypeClass : CustomType where TProperty : class, INetSerializable - { - private readonly Func _constructor; - public CustomTypeClass(Func constructor) { _constructor = constructor; } - public override FastCall Get() { return new FastCallClass(_constructor); } - } - - private sealed class CustomTypeStatic : CustomType - { - private readonly Action _writer; - private readonly Func _reader; - public CustomTypeStatic(Action writer, Func reader) - { - _writer = writer; - _reader = reader; - } - public override FastCall Get() { return new FastCallStatic(_writer, _reader); } - } - - /// - /// Register custom property type - /// - /// INetSerializable structure - public void RegisterNestedType() where T : struct, INetSerializable - { - _registeredTypes.Add(typeof(T), new CustomTypeStruct()); - } - - /// - /// Register custom property type - /// - /// INetSerializable class - public void RegisterNestedType(Func constructor) where T : class, INetSerializable - { - _registeredTypes.Add(typeof(T), new CustomTypeClass(constructor)); - } - - /// - /// Register custom property type - /// - /// Any packet - /// custom type writer - /// custom type reader - public void RegisterNestedType(Action writer, Func reader) - { - _registeredTypes.Add(typeof(T), new CustomTypeStatic(writer, reader)); - } - - private NetDataWriter _writer; - private readonly int _maxStringLength; - private readonly Dictionary _registeredTypes = new Dictionary(); - - public NetSerializer() : this(0) - { - } - - public NetSerializer(int maxStringLength) - { - _maxStringLength = maxStringLength; - } - - private ClassInfo RegisterInternal() - { - if (ClassInfo.Instance != null) - return ClassInfo.Instance; - - Type t = typeof(T); - var props = t.GetProperties( - BindingFlags.Instance | - BindingFlags.Public | - BindingFlags.GetProperty | - BindingFlags.SetProperty); - var serializers = new List>(); - for (int i = 0; i < props.Length; i++) - { - var property = props[i]; - var propertyType = property.PropertyType; - - var elementType = propertyType.IsArray ? propertyType.GetElementType() : propertyType; - var callType = propertyType.IsArray ? CallType.Array : CallType.Basic; - - if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List<>)) - { - elementType = propertyType.GetGenericArguments()[0]; - callType = CallType.List; - } - - if (Attribute.IsDefined(property, typeof(IgnoreDataMemberAttribute))) - continue; - - var getMethod = property.GetGetMethod(); - var setMethod = property.GetSetMethod(); - if (getMethod == null || setMethod == null) - continue; - - FastCall serialzer = null; - if (propertyType.IsEnum) - { - var underlyingType = Enum.GetUnderlyingType(propertyType); - if (underlyingType == typeof(byte)) - serialzer = new EnumByteSerializer(property, propertyType); - else if (underlyingType == typeof(int)) - serialzer = new EnumIntSerializer(property, propertyType); - else - throw new InvalidTypeException("Not supported enum underlying type: " + underlyingType.Name); - } - else if (elementType == typeof(string)) - serialzer = new StringSerializer(_maxStringLength); - else if (elementType == typeof(bool)) - serialzer = new BoolSerializer(); - else if (elementType == typeof(byte)) - serialzer = new ByteSerializer(); - else if (elementType == typeof(sbyte)) - serialzer = new SByteSerializer(); - else if (elementType == typeof(short)) - serialzer = new ShortSerializer(); - else if (elementType == typeof(ushort)) - serialzer = new UShortSerializer(); - else if (elementType == typeof(int)) - serialzer = new IntSerializer(); - else if (elementType == typeof(uint)) - serialzer = new UIntSerializer(); - else if (elementType == typeof(long)) - serialzer = new LongSerializer(); - else if (elementType == typeof(ulong)) - serialzer = new ULongSerializer(); - else if (elementType == typeof(float)) - serialzer = new FloatSerializer(); - else if (elementType == typeof(double)) - serialzer = new DoubleSerializer(); - else if (elementType == typeof(char)) - serialzer = new CharSerializer(); - else if (elementType == typeof(IPEndPoint)) - serialzer = new IPEndPointSerializer(); - else - { - _registeredTypes.TryGetValue(elementType, out var customType); - if (customType != null) - serialzer = customType.Get(); - } - - if (serialzer != null) - { - serialzer.Init(getMethod, setMethod, callType); - serializers.Add(serialzer); - } - else - { - throw new InvalidTypeException("Unknown property type: " + propertyType.FullName); - } - } - ClassInfo.Instance = new ClassInfo(serializers); - return ClassInfo.Instance; - } - - /// 's fields are not supported, or it has no fields - public void Register() - { - RegisterInternal(); - } - - /// - /// Reads packet with known type - /// - /// NetDataReader with packet - /// Returns packet if packet in reader is matched type - /// 's fields are not supported, or it has no fields - public T Deserialize(NetDataReader reader) where T : class, new() - { - var info = RegisterInternal(); - var result = new T(); - try - { - info.Read(result, reader); - } - catch - { - return null; - } - return result; - } - - /// - /// Reads packet with known type (non alloc variant) - /// - /// NetDataReader with packet - /// Deserialization target - /// Returns true if packet in reader is matched type - /// 's fields are not supported, or it has no fields - public bool Deserialize(NetDataReader reader, T target) where T : class, new() - { - var info = RegisterInternal(); - try - { - info.Read(target, reader); - } - catch - { - return false; - } - return true; - } - - /// - /// Serialize object to NetDataWriter (fast) - /// - /// Serialization target NetDataWriter - /// Object to serialize - /// 's fields are not supported, or it has no fields - public void Serialize(NetDataWriter writer, T obj) where T : class, new() - { - RegisterInternal().Write(obj, writer); - } - - /// - /// Serialize object to byte array - /// - /// Object to serialize - /// byte array with serialized data - public byte[] Serialize(T obj) where T : class, new() - { - if (_writer == null) - _writer = new NetDataWriter(); - _writer.Reset(); - Serialize(_writer, obj); - return _writer.CopyData(); - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetSerializer.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetSerializer.cs.meta deleted file mode 100644 index 87dacc8..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NetSerializer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 503136cdfd845ea439d6eb1e7fcfa924 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpPacket.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpPacket.cs deleted file mode 100644 index 1ba5210..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpPacket.cs +++ /dev/null @@ -1,423 +0,0 @@ -using System; - -namespace LiteNetLib.Utils -{ - /// - /// Represents RFC4330 SNTP packet used for communication to and from a network time server. - /// - /// - /// - /// Most applications should just use the property. - /// - /// - /// The same data structure represents both request and reply packets. - /// Request and reply differ in which properties are set and to what values. - /// - /// - /// The only real property is . - /// All other properties read from and write to the underlying byte array - /// with the exception of , - /// which is not part of the packet on network and it is instead set locally after receiving the packet. - /// - /// - /// Copied from GuerrillaNtp project - /// with permission from Robert Vazan (@robertvazan) under MIT license, see https://github.com/RevenantX/LiteNetLib/pull/236 - /// - /// - public class NtpPacket - { - private static readonly DateTime Epoch = new DateTime(1900, 1, 1); - - /// - /// Gets RFC4330-encoded SNTP packet. - /// - /// - /// Byte array containing RFC4330-encoded SNTP packet. It is at least 48 bytes long. - /// - /// - /// This is the only real property. All other properties except - /// read from or write to this byte array. - /// - public byte[] Bytes { get; } - - /// - /// Gets the leap second indicator. - /// - /// - /// Leap second warning, if any. Special value - /// indicates unsynchronized server clock. - /// Default is . - /// - /// - /// Only servers fill in this property. Clients can consult this property for possible leap second warning. - /// - public NtpLeapIndicator LeapIndicator => (NtpLeapIndicator)((Bytes[0] & 0xC0) >> 6); - - /// - /// Gets or sets protocol version number. - /// - /// - /// SNTP protocol version. Default is 4, which is the latest version at the time of this writing. - /// - /// - /// In request packets, clients should leave this property at default value 4. - /// Servers usually reply with the same protocol version. - /// - public int VersionNumber - { - get => (Bytes[0] & 0x38) >> 3; - private set => Bytes[0] = (byte)((Bytes[0] & ~0x38) | value << 3); - } - - /// - /// Gets or sets SNTP packet mode, i.e. whether this is client or server packet. - /// - /// - /// SNTP packet mode. Default is in newly created packets. - /// Server reply should have this property set to . - /// - public NtpMode Mode - { - get => (NtpMode)(Bytes[0] & 0x07); - private set => Bytes[0] = (byte)((Bytes[0] & ~0x07) | (int)value); - } - - /// - /// Gets server's distance from the reference clock. - /// - /// - /// - /// Distance from the reference clock. This property is set only in server reply packets. - /// Servers connected directly to reference clock hardware set this property to 1. - /// Statum number is incremented by 1 on every hop down the NTP server hierarchy. - /// - /// - /// Special value 0 indicates that this packet is a Kiss-o'-Death message - /// with kiss code stored in . - /// - /// - public int Stratum => Bytes[1]; - - /// - /// Gets server's preferred polling interval. - /// - /// - /// Polling interval in log2 seconds, e.g. 4 stands for 16s and 17 means 131,072s. - /// - public int Poll => Bytes[2]; - - /// - /// Gets the precision of server clock. - /// - /// - /// Clock precision in log2 seconds, e.g. -20 for microsecond precision. - /// - public int Precision => (sbyte)Bytes[3]; - - /// - /// Gets the total round-trip delay from the server to the reference clock. - /// - /// - /// Round-trip delay to the reference clock. Normally a positive value smaller than one second. - /// - public TimeSpan RootDelay => GetTimeSpan32(4); - - /// - /// Gets the estimated error in time reported by the server. - /// - /// - /// Estimated error in time reported by the server. Normally a positive value smaller than one second. - /// - public TimeSpan RootDispersion => GetTimeSpan32(8); - - /// - /// Gets the ID of the time source used by the server or Kiss-o'-Death code sent by the server. - /// - /// - /// - /// ID of server's time source or Kiss-o'-Death code. - /// Purpose of this property depends on value of property. - /// - /// - /// Stratum 1 servers write here one of several special values that describe the kind of hardware clock they use. - /// - /// - /// Stratum 2 and lower servers set this property to IPv4 address of their upstream server. - /// If upstream server has IPv6 address, the address is hashed, because it doesn't fit in this property. - /// - /// - /// When server sets to special value 0, - /// this property contains so called kiss code that instructs the client to stop querying the server. - /// - /// - public uint ReferenceId => GetUInt32BE(12); - - /// - /// Gets or sets the time when the server clock was last set or corrected. - /// - /// - /// Time when the server clock was last set or corrected or null when not specified. - /// - /// - /// This Property is usually set only by servers. It usually lags server's current time by several minutes, - /// so don't use this property for time synchronization. - /// - public DateTime? ReferenceTimestamp => GetDateTime64(16); - - /// - /// Gets or sets the time when the client sent its request. - /// - /// - /// This property is null in request packets. - /// In reply packets, it is the time when the client sent its request. - /// Servers copy this value from - /// that they find in received request packet. - /// - /// - /// - public DateTime? OriginTimestamp => GetDateTime64(24); - - /// - /// Gets or sets the time when the request was received by the server. - /// - /// - /// This property is null in request packets. - /// In reply packets, it is the time when the server received client request. - /// - /// - /// - public DateTime? ReceiveTimestamp => GetDateTime64(32); - - /// - /// Gets or sets the time when the packet was sent. - /// - /// - /// Time when the packet was sent. It should never be null. - /// Default value is . - /// - /// - /// This property must be set by both clients and servers. - /// - /// - /// - public DateTime? TransmitTimestamp { get { return GetDateTime64(40); } private set { SetDateTime64(40, value); } } - - /// - /// Gets or sets the time of reception of response SNTP packet on the client. - /// - /// - /// Time of reception of response SNTP packet on the client. It is null in request packets. - /// - /// - /// This property is not part of the protocol and has to be set when reply packet is received. - /// - /// - /// - public DateTime? DestinationTimestamp { get; private set; } - - /// - /// Gets the round-trip time to the server. - /// - /// - /// Time the request spent traveling to the server plus the time the reply spent traveling back. - /// This is calculated from timestamps in the packet as (t1 - t0) + (t3 - t2) - /// where t0 is , - /// t1 is , - /// t2 is , - /// and t3 is . - /// This property throws an exception in request packets. - /// - public TimeSpan RoundTripTime - { - get - { - CheckTimestamps(); - return (ReceiveTimestamp.Value - OriginTimestamp.Value) + (DestinationTimestamp.Value - TransmitTimestamp.Value); - } - } - - /// - /// Gets the offset that should be added to local time to synchronize it with server time. - /// - /// - /// Time difference between server and client. It should be added to local time to get server time. - /// It is calculated from timestamps in the packet as 0.5 * ((t1 - t0) - (t3 - t2)) - /// where t0 is , - /// t1 is , - /// t2 is , - /// and t3 is . - /// This property throws an exception in request packets. - /// - public TimeSpan CorrectionOffset - { - get - { - CheckTimestamps(); - return TimeSpan.FromTicks(((ReceiveTimestamp.Value - OriginTimestamp.Value) - (DestinationTimestamp.Value - TransmitTimestamp.Value)).Ticks / 2); - } - } - - /// - /// Initializes default request packet. - /// - /// - /// Properties and - /// are set appropriately for request packet. Property - /// is set to . - /// - public NtpPacket() : this(new byte[48]) - { - Mode = NtpMode.Client; - VersionNumber = 4; - TransmitTimestamp = DateTime.UtcNow; - } - - /// - /// Initializes packet from received data. - /// - internal NtpPacket(byte[] bytes) - { - if (bytes.Length < 48) - throw new ArgumentException("SNTP reply packet must be at least 48 bytes long.", "bytes"); - Bytes = bytes; - } - - /// - /// Initializes packet from data received from a server. - /// - /// Data received from the server. - /// Utc time of reception of response SNTP packet on the client. - /// - public static NtpPacket FromServerResponse(byte[] bytes, DateTime destinationTimestamp) - { - return new NtpPacket(bytes) { DestinationTimestamp = destinationTimestamp }; - } - - internal void ValidateRequest() - { - if (Mode != NtpMode.Client) - throw new InvalidOperationException("This is not a request SNTP packet."); - if (VersionNumber == 0) - throw new InvalidOperationException("Protocol version of the request is not specified."); - if (TransmitTimestamp == null) - throw new InvalidOperationException("TransmitTimestamp must be set in request packet."); - } - - internal void ValidateReply() - { - if (Mode != NtpMode.Server) - throw new InvalidOperationException("This is not a reply SNTP packet."); - if (VersionNumber == 0) - throw new InvalidOperationException("Protocol version of the reply is not specified."); - if (Stratum == 0) - throw new InvalidOperationException(string.Format("Received Kiss-o'-Death SNTP packet with code 0x{0:x}.", ReferenceId)); - if (LeapIndicator == NtpLeapIndicator.AlarmCondition) - throw new InvalidOperationException("SNTP server has unsynchronized clock."); - CheckTimestamps(); - } - - private void CheckTimestamps() - { - if (OriginTimestamp == null) - throw new InvalidOperationException("Origin timestamp is missing."); - if (ReceiveTimestamp == null) - throw new InvalidOperationException("Receive timestamp is missing."); - if (TransmitTimestamp == null) - throw new InvalidOperationException("Transmit timestamp is missing."); - if (DestinationTimestamp == null) - throw new InvalidOperationException("Destination timestamp is missing."); - } - - private DateTime? GetDateTime64(int offset) - { - var field = GetUInt64BE(offset); - if (field == 0) - return null; - return new DateTime(Epoch.Ticks + Convert.ToInt64(field * (1.0 / (1L << 32) * 10000000.0))); - } - - private void SetDateTime64(int offset, DateTime? value) - { - SetUInt64BE(offset, value == null ? 0 : Convert.ToUInt64((value.Value.Ticks - Epoch.Ticks) * (0.0000001 * (1L << 32)))); - } - - private TimeSpan GetTimeSpan32(int offset) - { - return TimeSpan.FromSeconds(GetInt32BE(offset) / (double)(1 << 16)); - } - - private ulong GetUInt64BE(int offset) - { - return SwapEndianness(BitConverter.ToUInt64(Bytes, offset)); - } - - private void SetUInt64BE(int offset, ulong value) - { - FastBitConverter.GetBytes(Bytes, offset, SwapEndianness(value)); - } - - private int GetInt32BE(int offset) - { - return (int)GetUInt32BE(offset); - } - - private uint GetUInt32BE(int offset) - { - return SwapEndianness(BitConverter.ToUInt32(Bytes, offset)); - } - - private static uint SwapEndianness(uint x) - { - return ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24); - } - - private static ulong SwapEndianness(ulong x) - { - return ((ulong)SwapEndianness((uint)x) << 32) | SwapEndianness((uint)(x >> 32)); - } - } - - /// - /// Represents leap second warning from the server that instructs the client to add or remove leap second. - /// - /// - public enum NtpLeapIndicator - { - /// - /// No leap second warning. No action required. - /// - NoWarning, - - /// - /// Warns the client that the last minute of the current day has 61 seconds. - /// - LastMinuteHas61Seconds, - - /// - /// Warns the client that the last minute of the current day has 59 seconds. - /// - LastMinuteHas59Seconds, - - /// - /// Special value indicating that the server clock is unsynchronized and the returned time is unreliable. - /// - AlarmCondition - } - - /// - /// Describes SNTP packet mode, i.e. client or server. - /// - /// - public enum NtpMode - { - /// - /// Identifies client-to-server SNTP packet. - /// - Client = 3, - - /// - /// Identifies server-to-client SNTP packet. - /// - Server = 4, - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpPacket.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpPacket.cs.meta deleted file mode 100644 index fdbbe00..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpPacket.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: daf31cf4ab8132943b2c8ca301fc919a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpRequest.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpRequest.cs deleted file mode 100644 index bd7f74f..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpRequest.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Net; -using System.Net.Sockets; - -namespace LiteNetLib.Utils -{ - internal sealed class NtpRequest - { - private const int ResendTimer = 1000; - private const int KillTimer = 10000; - public const int DefaultPort = 123; - private readonly IPEndPoint _ntpEndPoint; - private int _resendTime = ResendTimer; - private int _killTime = 0; - - public NtpRequest(IPEndPoint endPoint) - { - _ntpEndPoint = endPoint; - } - - public bool NeedToKill => _killTime >= KillTimer; - - public bool Send(Socket socket, int time) - { - _resendTime += time; - _killTime += time; - if (_resendTime < ResendTimer) - { - return false; - } - var packet = new NtpPacket(); - try - { - int sendCount = socket.SendTo(packet.Bytes, 0, packet.Bytes.Length, SocketFlags.None, _ntpEndPoint); - return sendCount == packet.Bytes.Length; - } - catch - { - return false; - } - } - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpRequest.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpRequest.cs.meta deleted file mode 100644 index aa80855..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/LiteNetLib/Utils/NtpRequest.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c3fa3bfbb02dd944e939070e3cf0638c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Tugboat.cs b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Tugboat.cs deleted file mode 100644 index 5ef6969..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Tugboat.cs +++ /dev/null @@ -1,505 +0,0 @@ -using FishNet.Managing; -using FishNet.Managing.Logging; -using FishNet.Managing.Transporting; -using LiteNetLib; -using LiteNetLib.Layers; -using System; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Transporting.Tugboat -{ - [DisallowMultipleComponent] - [AddComponentMenu("FishNet/Transport/Tugboat")] - public class Tugboat : Transport - { - ~Tugboat() - { - Shutdown(); - } - - #region Serialized. - [Header("Channels")] - /// - /// Maximum transmission unit for the unreliable channel. - /// - [Tooltip("Maximum transmission unit for the unreliable channel.")] - [Range(MINIMUM_UDP_MTU, MAXIMUM_UDP_MTU)] - [SerializeField] - private int _unreliableMTU = 1023; - - [Header("Server")] - /// - /// IPv4 address to bind server to. - /// - [Tooltip("IPv4 Address to bind server to.")] - [SerializeField] - private string _ipv4BindAddress; - /// - /// IPv6 address to bind server to. - /// - [Tooltip("IPv6 Address to bind server to.")] - [SerializeField] - private string _ipv6BindAddress; - /// - /// Port to use. - /// - [Tooltip("Port to use.")] - [SerializeField] - private ushort _port = 7770; - /// - /// Maximum number of players which may be connected at once. - /// - [Tooltip("Maximum number of players which may be connected at once.")] - [Range(1, 9999)] - [SerializeField] - private int _maximumClients = 4095; - - - [Header("Client")] - /// - /// Address to connect. - /// - [Tooltip("Address to connect.")] - [SerializeField] - private string _clientAddress = "localhost"; - - [Header("Misc")] - /// - /// How long in seconds until either the server or client socket must go without data before being timed out. Use 0f to disable timing out. - /// - [Tooltip("How long in seconds until either the server or client socket must go without data before being timed out. Use 0f to disable timing out.")] - [Range(0, MAX_TIMEOUT_SECONDS)] - [SerializeField] - private ushort _timeout = 15; - #endregion - - #region Private. - /// - /// PacketLayer to use with LiteNetLib. - /// - private PacketLayerBase _packetLayer; - /// - /// Server socket and handler. - /// - private Server.ServerSocket _server = new Server.ServerSocket(); - /// - /// Client socket and handler. - /// - private Client.ClientSocket _client = new Client.ClientSocket(); - #endregion - - #region Const. - private const ushort MAX_TIMEOUT_SECONDS = 1800; - /// - /// Minimum UDP packet size allowed. - /// - private const int MINIMUM_UDP_MTU = 576; - /// - /// Maximum UDP packet size allowed. - /// - private const int MAXIMUM_UDP_MTU = 1023; - #endregion - - #region Initialization and unity. - public override void Initialize(NetworkManager networkManager, int transportIndex) - { - base.Initialize(networkManager, transportIndex); - } - - protected void OnDestroy() - { - Shutdown(); - } - #endregion - - #region ConnectionStates. - /// - /// Gets the address of a remote connection Id. - /// - /// - /// - public override string GetConnectionAddress(int connectionId) - { - return _server.GetConnectionAddress(connectionId); - } - /// - /// Called when a connection state changes for the local client. - /// - public override event Action OnClientConnectionState; - /// - /// Called when a connection state changes for the local server. - /// - public override event Action OnServerConnectionState; - /// - /// Called when a connection state changes for a remote client. - /// - public override event Action OnRemoteConnectionState; - /// - /// Gets the current local ConnectionState. - /// - /// True if getting ConnectionState for the server. - public override LocalConnectionState GetConnectionState(bool server) - { - if (server) - return _server.GetConnectionState(); - else - return _client.GetConnectionState(); - } - /// - /// Gets the current ConnectionState of a remote client on the server. - /// - /// ConnectionId to get ConnectionState for. - public override RemoteConnectionState GetConnectionState(int connectionId) - { - return _server.GetConnectionState(connectionId); - } - /// - /// Handles a ConnectionStateArgs for the local client. - /// - /// - public override void HandleClientConnectionState(ClientConnectionStateArgs connectionStateArgs) - { - OnClientConnectionState?.Invoke(connectionStateArgs); - } - /// - /// Handles a ConnectionStateArgs for the local server. - /// - /// - public override void HandleServerConnectionState(ServerConnectionStateArgs connectionStateArgs) - { - OnServerConnectionState?.Invoke(connectionStateArgs); - UpdateTimeout(); - } - /// - /// Handles a ConnectionStateArgs for a remote client. - /// - /// - public override void HandleRemoteConnectionState(RemoteConnectionStateArgs connectionStateArgs) - { - OnRemoteConnectionState?.Invoke(connectionStateArgs); - } - #endregion - - #region Iterating. - /// - /// Processes data received by the socket. - /// - /// True to process data received on the server. - public override void IterateIncoming(bool server) - { - if (server) - _server.IterateIncoming(); - else - _client.IterateIncoming(); - } - - /// - /// Processes data to be sent by the socket. - /// - /// True to process data received on the server. - public override void IterateOutgoing(bool server) - { - if (server) - _server.IterateOutgoing(); - else - _client.IterateOutgoing(); - } - #endregion - - #region ReceivedData. - /// - /// Called when client receives data. - /// - public override event Action OnClientReceivedData; - /// - /// Handles a ClientReceivedDataArgs. - /// - /// - public override void HandleClientReceivedDataArgs(ClientReceivedDataArgs receivedDataArgs) - { - OnClientReceivedData?.Invoke(receivedDataArgs); - } - /// - /// Called when server receives data. - /// - public override event Action OnServerReceivedData; - /// - /// Handles a ClientReceivedDataArgs. - /// - /// - public override void HandleServerReceivedDataArgs(ServerReceivedDataArgs receivedDataArgs) - { - OnServerReceivedData?.Invoke(receivedDataArgs); - } - #endregion - - #region Sending. - /// - /// Sends to the server or all clients. - /// - /// Channel to use. - /// Data to send. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void SendToServer(byte channelId, ArraySegment segment) - { - SanitizeChannel(ref channelId); - _client.SendToServer(channelId, segment); - } - /// - /// Sends data to a client. - /// - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void SendToClient(byte channelId, ArraySegment segment, int connectionId) - { - SanitizeChannel(ref channelId); - _server.SendToClient(channelId, segment, connectionId); - } - #endregion - - #region Configuration. - /// - /// Sets which PacketLayer to use with LiteNetLib. - /// - /// - public void SetPacketLayer(PacketLayerBase packetLayer) - { - _packetLayer = packetLayer; - if (GetConnectionState(true) != LocalConnectionState.Stopped) - base.NetworkManager.LogWarning("PacketLayer is set but will not be applied until the server stops."); - if (GetConnectionState(false) != LocalConnectionState.Stopped) - base.NetworkManager.LogWarning("PacketLayer is set but will not be applied until the client stops."); - - _server.Initialize(this, _unreliableMTU, _packetLayer); - _client.Initialize(this, _unreliableMTU, _packetLayer); - } - /// - /// How long in seconds until either the server or client socket must go without data before being timed out. - /// - /// True to get the timeout for the server socket, false for the client socket. - /// - public override float GetTimeout(bool asServer) - { - //Server and client uses the same timeout. - return (float)_timeout; - } - /// - /// Sets how long in seconds until either the server or client socket must go without data before being timed out. - /// - /// True to set the timeout for the server socket, false for the client socket. - public override void SetTimeout(float value, bool asServer) - { - _timeout = (ushort)value; - } - /// - /// Returns the maximum number of clients allowed to connect to the server. If the transport does not support this method the value -1 is returned. - /// - /// - public override int GetMaximumClients() - { - return _server.GetMaximumClients(); - } - /// - /// Sets maximum number of clients allowed to connect to the server. If applied at runtime and clients exceed this value existing clients will stay connected but new clients may not connect. - /// - /// - public override void SetMaximumClients(int value) - { - _maximumClients = value; - _server.SetMaximumClients(value); - } - /// - /// Sets which address the client will connect to. - /// - /// - public override void SetClientAddress(string address) - { - _clientAddress = address; - } - /// - /// Gets which address the client will connect to. - /// - public override string GetClientAddress() - { - return _clientAddress; - } - - /// - /// Sets which address the server will bind to. - /// - /// - public override void SetServerBindAddress(string address, IPAddressType addressType) - { - if (addressType == IPAddressType.IPv4) - _ipv4BindAddress = address; - else - _ipv6BindAddress = address; - } - /// - /// Gets which address the server will bind to. - /// - /// - public override string GetServerBindAddress(IPAddressType addressType) - { - if (addressType == IPAddressType.IPv4) - return _ipv4BindAddress; - else - return _ipv6BindAddress; - } - /// - /// Sets which port to use. - /// - /// - public override void SetPort(ushort port) - { - _port = port; - } - /// - /// Gets which port to use. - /// - /// - public override ushort GetPort() - { - return _port; - } - #endregion - - #region Start and stop. - /// - /// Starts the local server or client using configured settings. - /// - /// True to start server. - public override bool StartConnection(bool server) - { - if (server) - return StartServer(); - else - return StartClient(_clientAddress); - } - - /// - /// Stops the local server or client. - /// - /// True to stop server. - public override bool StopConnection(bool server) - { - if (server) - return StopServer(); - else - return StopClient(); - } - - /// - /// Stops a remote client from the server, disconnecting the client. - /// - /// ConnectionId of the client to disconnect. - /// True to abrutly stop the client socket. The technique used to accomplish immediate disconnects may vary depending on the transport. - /// When not using immediate disconnects it's recommended to perform disconnects using the ServerManager rather than accessing the transport directly. - /// - public override bool StopConnection(int connectionId, bool immediately) - { - return _server.StopConnection(connectionId); - } - - /// - /// Stops both client and server. - /// - public override void Shutdown() - { - //Stops client then server connections. - StopConnection(false); - StopConnection(true); - } - - #region Privates. - /// - /// Starts server. - /// - private bool StartServer() - { - _server.Initialize(this, _unreliableMTU, _packetLayer); - UpdateTimeout(); - return _server.StartConnection(_port, _maximumClients, _ipv4BindAddress, _ipv6BindAddress); - } - - /// - /// Stops server. - /// - private bool StopServer() - { - return _server.StopConnection(); - } - - /// - /// Starts the client. - /// - /// - private bool StartClient(string address) - { - _client.Initialize(this, _unreliableMTU, _packetLayer); - UpdateTimeout(); - return _client.StartConnection(address, _port); - } - - /// - /// Updates clients timeout values. - /// - private void UpdateTimeout() - { - //If server is running set timeout to max. This is for host only. - //int timeout = (GetConnectionState(true) != LocalConnectionState.Stopped) ? MAX_TIMEOUT_SECONDS : _timeout; - int timeout = (Application.isEditor) ? MAX_TIMEOUT_SECONDS : _timeout; - _client.UpdateTimeout(timeout); - _server.UpdateTimeout(timeout); - } - /// - /// Stops the client. - /// - private bool StopClient() - { - return _client.StopConnection(); - } - #endregion - #endregion - - #region Channels. - /// - /// If channelId is invalid then channelId becomes forced to reliable. - /// - /// - private void SanitizeChannel(ref byte channelId) - { - if (channelId < 0 || channelId >= TransportManager.CHANNEL_COUNT) - { - NetworkManager.LogWarning($"Channel of {channelId} is out of range of supported channels. Channel will be defaulted to reliable."); - channelId = 0; - } - } - /// - /// Gets the MTU for a channel. This should take header size into consideration. - /// For example, if MTU is 1200 and a packet header for this channel is 10 in size, this method should return 1190. - /// - /// - /// - public override int GetMTU(byte channel) - { - return _unreliableMTU; - } - #endregion - - #region Editor. -#if UNITY_EDITOR - private void OnValidate() - { - if (_unreliableMTU < 0) - _unreliableMTU = MINIMUM_UDP_MTU; - else if (_unreliableMTU > MAXIMUM_UDP_MTU) - _unreliableMTU = MAXIMUM_UDP_MTU; - } -#endif - #endregion - } -} diff --git a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Tugboat.cs.meta b/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Tugboat.cs.meta deleted file mode 100644 index cb42e47..0000000 --- a/Assets/FishNet/Runtime/Transporting/Transports/Tugboat/Tugboat.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6f48f002b825cbd45a19bd96d90f9edb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility.meta b/Assets/FishNet/Runtime/Utility.meta deleted file mode 100644 index 8cca6c1..0000000 --- a/Assets/FishNet/Runtime/Utility.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: b01cb2614bcfb9249b6c78abcf482943 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/ApplicationState.cs b/Assets/FishNet/Runtime/Utility/ApplicationState.cs deleted file mode 100644 index 1efa14b..0000000 --- a/Assets/FishNet/Runtime/Utility/ApplicationState.cs +++ /dev/null @@ -1,64 +0,0 @@ -using FishNet.Utility.Constant; -using System.Runtime.CompilerServices; -using UnityEngine; -#if UNITY_EDITOR -using UnityEditor; -#endif - - - -namespace FishNet.Utility -{ -#if UNITY_EDITOR - [InitializeOnLoad] -#endif - public static class ApplicationState - { - -#if !UNITY_EDITOR - /// - /// True if application is quitting. - /// - private static bool _isQuitting; -#endif - static ApplicationState() - { -#if !UNITY_EDITOR - _isQuitting = false; -#endif - Application.quitting -= Application_quitting; - Application.quitting += Application_quitting; - } - - private static void Application_quitting() - { -#if !UNITY_EDITOR - _isQuitting = true; -#endif - } - - public static bool IsQuitting() - { -#if UNITY_EDITOR - if (!EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying) - return true; - else - return false; -#else - return _isQuitting; -#endif - } - - public static bool IsPlaying() - { -#if UNITY_EDITOR - return EditorApplication.isPlaying; -#else - return Application.isPlaying; -#endif - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/ApplicationState.cs.meta b/Assets/FishNet/Runtime/Utility/ApplicationState.cs.meta deleted file mode 100644 index 7861977..0000000 --- a/Assets/FishNet/Runtime/Utility/ApplicationState.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 54eb82a57a65e8548b57f5ca2a62bb76 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Constants.cs b/Assets/FishNet/Runtime/Utility/Constants.cs deleted file mode 100644 index 4da2021..0000000 --- a/Assets/FishNet/Runtime/Utility/Constants.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace FishNet.Utility.Constant -{ - internal static class UtilityConstants - { - public const string CODEGEN_ASSEMBLY_NAME = "Unity.FishNet.CodeGen"; - public const string GENERATED_ASSEMBLY_NAME = "FishNet.Generated"; - public const string DEMOS_ASSEMBLY_NAME = "FishNet.Demos"; - public const string TEST_ASSEMBLY_NAME = "FishNet.Test"; - public const string RUNTIME_ASSEMBLY_NAME = "FishNet.Runtime"; - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Constants.cs.meta b/Assets/FishNet/Runtime/Utility/Constants.cs.meta deleted file mode 100644 index ef98347..0000000 --- a/Assets/FishNet/Runtime/Utility/Constants.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3f2a3c23b44e4ef4e9783ef53ec0d5da -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/DDOLFinder.cs b/Assets/FishNet/Runtime/Utility/DDOLFinder.cs deleted file mode 100644 index 4c0118c..0000000 --- a/Assets/FishNet/Runtime/Utility/DDOLFinder.cs +++ /dev/null @@ -1,60 +0,0 @@ -using UnityEngine; - -namespace FishNet.Utility -{ - - - public class DDOLFinder : MonoBehaviour - { - #region Public. - /// - /// Singleton instance of this class. - /// - public static DDOLFinder Instance { get; private set; } - #endregion - - private void Awake() - { - FirstInitialize(); - } - - /// - /// Initializes this script for use. Should only be completed once. - /// - private void FirstInitialize() - { - if (Instance != null && Instance != this) - { - Debug.LogError("Multiple DDOL scripts found. There should be only one."); - return; - } - else - { - Instance = this; - gameObject.name = "DDOLFinder"; - DontDestroyOnLoad(gameObject); - } - } - - /// - /// Returns the current DDOL or creates one if not yet created. - /// - public static DDOLFinder GetDDOL() - { - //Not yet made. - if (Instance == null) - { - GameObject obj = new GameObject(); - DDOLFinder ddol = obj.AddComponent(); - return ddol; - } - //Already made. - else - { - return Instance; - } - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/DDOLFinder.cs.meta b/Assets/FishNet/Runtime/Utility/DDOLFinder.cs.meta deleted file mode 100644 index bf2dcdb..0000000 --- a/Assets/FishNet/Runtime/Utility/DDOLFinder.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 47bed61fc24f71942a7437612621bbfd -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Editor.meta b/Assets/FishNet/Runtime/Utility/Editor.meta deleted file mode 100644 index 3d5a891..0000000 --- a/Assets/FishNet/Runtime/Utility/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 66122940cd5d35e49908ec08d1daf7db -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Editor/SceneDrawer.cs b/Assets/FishNet/Runtime/Utility/Editor/SceneDrawer.cs deleted file mode 100644 index 147a9b4..0000000 --- a/Assets/FishNet/Runtime/Utility/Editor/SceneDrawer.cs +++ /dev/null @@ -1,51 +0,0 @@ -#if UNITY_EDITOR -using UnityEditor; -using UnityEngine; - -namespace FishNet.Utility.Editing -{ - /* Source https://forum.unity.com/threads/how-to-link-scenes-in-the-inspector.383140/ */ - - [CustomPropertyDrawer(typeof(SceneAttribute))] - public class SceneDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - if (property.propertyType == SerializedPropertyType.String) - { - SceneAsset sceneObject = AssetDatabase.LoadAssetAtPath(property.stringValue); - - if (sceneObject == null && !string.IsNullOrEmpty(property.stringValue)) - { - // try to load it from the build settings for legacy compatibility - sceneObject = GetBuildSettingsSceneObject(property.stringValue); - } - if (sceneObject == null && !string.IsNullOrEmpty(property.stringValue)) - { - Debug.Log($"Could not find scene {property.stringValue} in {property.propertyPath}, assign the proper scenes in your NetworkManager"); - } - SceneAsset scene = (SceneAsset)EditorGUI.ObjectField(position, label, sceneObject, typeof(SceneAsset), true); - - property.stringValue = AssetDatabase.GetAssetPath(scene); - } - else - { - EditorGUI.LabelField(position, label.text, "Use [Scene] with strings."); - } - } - - protected SceneAsset GetBuildSettingsSceneObject(string sceneName) - { - foreach (EditorBuildSettingsScene buildScene in EditorBuildSettings.scenes) - { - SceneAsset sceneAsset = AssetDatabase.LoadAssetAtPath(buildScene.path); - if (sceneAsset != null && sceneAsset.name == sceneName) - { - return sceneAsset; - } - } - return null; - } - } -} -#endif \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Editor/SceneDrawer.cs.meta b/Assets/FishNet/Runtime/Utility/Editor/SceneDrawer.cs.meta deleted file mode 100644 index 8f3c47d..0000000 --- a/Assets/FishNet/Runtime/Utility/Editor/SceneDrawer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2b2c813205b39ed46953611f7a5659fd -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Extension.meta b/Assets/FishNet/Runtime/Utility/Extension.meta deleted file mode 100644 index bb462bb..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 8f30057a48bb0104d8a7813443607804 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Extension/Bool.cs b/Assets/FishNet/Runtime/Utility/Extension/Bool.cs deleted file mode 100644 index 1907675..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Bool.cs +++ /dev/null @@ -1,18 +0,0 @@ - -namespace FishNet.Utility.Extension -{ - public static class BooleanExtensions - { - /// - /// Converts a boolean to an integer. - /// - /// - /// - public static int ToInt(this bool b) - { - return (b) ? 1 : 0; - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Extension/Bool.cs.meta b/Assets/FishNet/Runtime/Utility/Extension/Bool.cs.meta deleted file mode 100644 index 807bccb..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Bool.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c688c9bd497f4a749b692b9b1d628c51 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Extension/Collection.cs b/Assets/FishNet/Runtime/Utility/Extension/Collection.cs deleted file mode 100644 index f1c2ae2..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Collection.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace FishNet.Utility.Extension -{ - public static class CollectionFN - { - /// - /// Random for shuffling. - /// - private static Random _random = new Random(); - - /// - /// Shuffle based on Fisher-Yates shuffle. - /// https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle - /// https://stackoverflow.com/questions/273313/randomize-a-listt - /// - public static void Shuffle(this IList lst) - { - int n = lst.Count; - while (n > 1) - { - n--; - int k = _random.Next(n + 1); - T value = lst[k]; - lst[k] = lst[n]; - lst[n] = value; - } - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Extension/Collection.cs.meta b/Assets/FishNet/Runtime/Utility/Extension/Collection.cs.meta deleted file mode 100644 index 0fa0ef3..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Collection.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9a6539089deb687469d1abdc1b8964a1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Extension/Dictionary.cs b/Assets/FishNet/Runtime/Utility/Extension/Dictionary.cs deleted file mode 100644 index 4f9a5f4..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Dictionary.cs +++ /dev/null @@ -1,35 +0,0 @@ -using FishNet.Documenting; -using System.Collections.Generic; - -namespace FishNet.Utility.Extension -{ - [APIExclude] - public static class DictionaryFN - { - - /// - /// Uses a hacky way to TryGetValue on a dictionary when using IL2CPP and on mobile. - /// This is to support older devices that don't properly handle IL2CPP builds. - /// - public static bool TryGetValueIL2CPP(this IDictionary dict, TKey key, out TValue value) - { -#if ENABLE_IL2CPP && UNITY_IOS || UNITY_ANDROID - if (dict.ContainsKey(key)) - { - value = dict[key]; - return true; - } - else - { - value = default; - return false; - } -#else - return dict.TryGetValue(key, out value); -#endif - } - - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Extension/Dictionary.cs.meta b/Assets/FishNet/Runtime/Utility/Extension/Dictionary.cs.meta deleted file mode 100644 index 67297e5..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Dictionary.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d286695e7464ce943bc321215aaa2ee1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Extension/Enum.cs b/Assets/FishNet/Runtime/Utility/Extension/Enum.cs deleted file mode 100644 index 246d34b..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Enum.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; - -namespace FishNet.Utility.Extension -{ - public static class EnumFN - { - - /// - /// Returns the highest numeric value for T. - /// - public static int GetHighestValue() - { - Type enumType = typeof(T); - /* Brute force enum values. - * Linq Last/Max lookup throws for IL2CPP. */ - int highestValue = 0; - Array pidValues = Enum.GetValues(enumType); - foreach (T pid in pidValues) - { - object obj = Enum.Parse(enumType, pid.ToString()); - int value = Convert.ToInt32(obj); - highestValue = Math.Max(highestValue, value); - } - - return highestValue; - } - - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Extension/Enum.cs.meta b/Assets/FishNet/Runtime/Utility/Extension/Enum.cs.meta deleted file mode 100644 index d4b39d4..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Enum.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f58b410f20b8e694aa852d2ea5240626 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Extension/List.cs b/Assets/FishNet/Runtime/Utility/Extension/List.cs deleted file mode 100644 index ede1347..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/List.cs +++ /dev/null @@ -1,24 +0,0 @@ -using FishNet.Documenting; -using System.Collections.Generic; - -namespace FishNet.Utility.Extension -{ - [APIExclude] - public static class ListFN - { - - /// - /// Adds a value to the list only if the value does not already exist. - /// - /// Collection being added to. - /// Value to add. - public static void AddUnique(this List lst, T value) - { - if (!lst.Contains(value)) - lst.Add(value); - } - - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Extension/List.cs.meta b/Assets/FishNet/Runtime/Utility/Extension/List.cs.meta deleted file mode 100644 index 82b83a8..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/List.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 953eb4b102d504544b49087104e6b747 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Extension/Math.cs b/Assets/FishNet/Runtime/Utility/Extension/Math.cs deleted file mode 100644 index 84d97e6..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Math.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace FishNet.Utility.Extension -{ - - public static class MathFN - { - - /// - /// Returns a clamped SBytte. - /// - public static sbyte ClampSByte(long value, sbyte min, sbyte max) - { - if (value < min) - return min; - else if (value > max) - return max; - else - return (sbyte)value; - } - - /// - /// Returns a clamped double. - /// - public static double ClampDouble(double value, double min, double max) - { - if (value < min) - return min; - else if (value > max) - return max; - else - return value; - } - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Extension/Math.cs.meta b/Assets/FishNet/Runtime/Utility/Extension/Math.cs.meta deleted file mode 100644 index 2df9023..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Math.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: feb978e97a6aa6b4cbb99481d925c00c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Extension/Object.cs b/Assets/FishNet/Runtime/Utility/Extension/Object.cs deleted file mode 100644 index 6ec0ff5..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Object.cs +++ /dev/null @@ -1,27 +0,0 @@ -using FishNet.Connection; -using FishNet.Object; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Utility.Extension -{ - - public static class ObjectFN - { - /// - /// Spawns an object over the network using InstanceFinder. Only call from the server. - /// - public static void Spawn(this NetworkObject nob, NetworkConnection owner = null) - { - InstanceFinder.ServerManager.Spawn(nob, owner); - } - /// - /// Spawns an object over the network using InstanceFinder. Only call from the server. - /// - public static void Spawn(this GameObject go, NetworkConnection owner = null) - { - InstanceFinder.ServerManager.Spawn(go, owner); - } - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Extension/Object.cs.meta b/Assets/FishNet/Runtime/Utility/Extension/Object.cs.meta deleted file mode 100644 index 6d573f8..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Object.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3d1cdee4c45e73a4fa9adba1177483ca -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Extension/Quaternion.cs b/Assets/FishNet/Runtime/Utility/Extension/Quaternion.cs deleted file mode 100644 index 5f5e69d..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Quaternion.cs +++ /dev/null @@ -1,43 +0,0 @@ -using FishNet.Documenting; -using UnityEngine; - -namespace FishNet.Utility.Extension -{ - [APIExclude] - public static class QuaternionFN - { - - /// - /// Returns if two quaternions match. - /// - /// True to use a custom implementation with no error tolerance. False to use Unity's implementation which may return a match even when not true due to error tolerance. - /// - public static bool Matches(this Quaternion a, Quaternion b, bool precise = false) - { - if (precise) - return (a.w == b.w && a.x == b.x && a.y == b.y && a.z == b.z); - else - return (a == b); - } - - /// - /// Returns the angle between two quaterions. - /// - /// True to use a custom implementation with no error tolerance. False to use Unity's implementation which may return 0f due to error tolerance, even while there is a difference. - /// - public static float Angle(this Quaternion a, Quaternion b, bool precise = false) - { - if (precise) - { - //This is run Unitys implementation without the error tolerance. - float dot = (a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w); - return (Mathf.Acos(Mathf.Min(Mathf.Abs(dot), 1f)) * 2f * 57.29578f); - } - else - { - return Quaternion.Angle(a, b); - } - } - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Extension/Quaternion.cs.meta b/Assets/FishNet/Runtime/Utility/Extension/Quaternion.cs.meta deleted file mode 100644 index 4bdf137..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Quaternion.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4b8122e8a7592784896b4173707188ce -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Extension/Scene.cs b/Assets/FishNet/Runtime/Utility/Extension/Scene.cs deleted file mode 100644 index 1ea499b..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Scene.cs +++ /dev/null @@ -1,76 +0,0 @@ -using FishNet.Object; -using FishNet.Utility.Performance; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.SceneManagement; - -namespace FishNet.Utility.Extension -{ - - public static class SceneFN - { - #region Private. - - /// - /// Used for performance gains when getting objects. - /// - private static List _gameObjectList = new List(); - /// - /// List for NetworkObjects. - /// - private static List _networkObjectListA = new List(); - /// - /// List for NetworkObjects. - /// - private static List _networkObjectListB = new List(); - #endregion - - /// - /// Gets all NetworkObjects in a scene. - /// - /// Scene to get objects in. - /// True to only return the first NetworkObject within an object chain. False will return nested NetworkObjects. - /// ListCache of found NetworkObjects. - /// - public static void GetSceneNetworkObjects(Scene s, bool firstOnly, out ListCache nobCache) - { - nobCache = ListCaches.GetNetworkObjectCache(); - //Iterate all root objects for the scene. - s.GetRootGameObjects(_gameObjectList); - foreach (GameObject go in _gameObjectList) - { - - //Get NetworkObjects within children of each root. - go.GetComponentsInChildren(true, _networkObjectListA); - //If network objects are found. - if (_networkObjectListA.Count > 0) - { - //Add only the first networkobject - if (firstOnly) - { - /* The easiest way to see if a nob is nested is to - * get nobs in parent and if the count is greater than 1, then - * it is nested. The technique used here isn't exactly fast but - * it will only occur during scene loads, so I'm trading off speed - * for effort and readability. */ - foreach (NetworkObject nob in _networkObjectListA) - { - nob.GetComponentsInParent(true, _networkObjectListB); - //No extra nobs, only this one. - if (_networkObjectListB.Count == 1) - nobCache.AddValue(nob); - } - } - //Not first only, add them all. - else - { - nobCache.AddValues(_networkObjectListA); - } - - } - } - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Extension/Scene.cs.meta b/Assets/FishNet/Runtime/Utility/Extension/Scene.cs.meta deleted file mode 100644 index e079485..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Scene.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a02f3d03f737e304e9854278f4e9211d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Extension/Transforms.cs b/Assets/FishNet/Runtime/Utility/Extension/Transforms.cs deleted file mode 100644 index d264059..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Transforms.cs +++ /dev/null @@ -1,42 +0,0 @@ -using FishNet.Documenting; -using UnityEngine; - -namespace FishNet.Utility.Extension -{ - [APIExclude] - public static class TransformFN - { - /// - /// Sets the offset values of target from a transform. - /// - /// Position offset result. - /// Rotation offset result. - public static void SetTransformOffsets(this Transform t, Transform target, ref Vector3 pos, ref Quaternion rot) - { - if (target == null) - return; - pos = (t.position - target.position); - rot = (t.rotation * Quaternion.Inverse(target.rotation)); - } - - /// - /// Sets local position and rotation for a transform. - /// - public static void SetLocalPositionAndRotation(this Transform t, Vector3 pos, Quaternion rot) - { - t.localPosition = pos; - t.localRotation = rot; - } - /// - /// Sets local position, rotation, and scale for a transform. - /// - public static void SetLocalPositionRotationAndScale(this Transform t, Vector3 pos, Quaternion rot, Vector3 scale) - { - t.localPosition = pos; - t.localRotation = rot; - t.localScale = scale; - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Extension/Transforms.cs.meta b/Assets/FishNet/Runtime/Utility/Extension/Transforms.cs.meta deleted file mode 100644 index bdee36b..0000000 --- a/Assets/FishNet/Runtime/Utility/Extension/Transforms.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3d311fc1bf09b9e4fbc5a17a9c50ab0d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Performance.meta b/Assets/FishNet/Runtime/Utility/Performance.meta deleted file mode 100644 index d114a4d..0000000 --- a/Assets/FishNet/Runtime/Utility/Performance.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: c297487b42ef1b640a26b7c41fef6e27 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Performance/ByteArrayPool.cs b/Assets/FishNet/Runtime/Utility/Performance/ByteArrayPool.cs deleted file mode 100644 index 9adcc58..0000000 --- a/Assets/FishNet/Runtime/Utility/Performance/ByteArrayPool.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace FishNet.Utility.Performance -{ - - /// - /// Retrieves and stores byte arrays using a pooling system. - /// - public static class ByteArrayPool - { - /// - /// Stored byte arrays. - /// - private static Queue _byteArrays = new Queue(); - - /// - /// Returns a byte array which will be of at lesat minimum length. The returned array must manually be stored. - /// - public static byte[] Retrieve(int minimumLength) - { - byte[] result = null; - - if (_byteArrays.Count > 0) - result = _byteArrays.Dequeue(); - - int doubleMinimumLength = (minimumLength * 2); - if (result == null) - result = new byte[doubleMinimumLength]; - else if (result.Length < minimumLength) - Array.Resize(ref result, doubleMinimumLength); - - return result; - } - - /// - /// Stores a byte array for re-use. - /// - public static void Store(byte[] buffer) - { - /* Holy cow that's a lot of buffered - * buffers. This wouldn't happen under normal - * circumstances but if the user is stress - * testing connections in one executable perhaps. */ - if (_byteArrays.Count > 300) - return; - _byteArrays.Enqueue(buffer); - } - - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Performance/ByteArrayPool.cs.meta b/Assets/FishNet/Runtime/Utility/Performance/ByteArrayPool.cs.meta deleted file mode 100644 index 4c5401f..0000000 --- a/Assets/FishNet/Runtime/Utility/Performance/ByteArrayPool.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c7620a5e6fedc18408f8f04821b35bbd -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Performance/DefaultObjectPool.cs b/Assets/FishNet/Runtime/Utility/Performance/DefaultObjectPool.cs deleted file mode 100644 index ac01d71..0000000 --- a/Assets/FishNet/Runtime/Utility/Performance/DefaultObjectPool.cs +++ /dev/null @@ -1,203 +0,0 @@ -using FishNet.Managing.Object; -using FishNet.Object; -using FishNet.Utility.Extension; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Utility.Performance -{ - - - public class DefaultObjectPool : ObjectPool - { - #region Public. - /// - /// Cache for pooled NetworkObjects. - /// - public IReadOnlyCollection>> Cache => _cache; - private List>> _cache = new List>>(); - #endregion - - #region Serialized. - /// - /// True if to use object pooling. - /// - [Tooltip("True if to use object pooling.")] - [SerializeField] - private bool _enabled = true; - #endregion - - #region Private. - /// - /// Current count of the cache collection. - /// - private int _cacheCount = 0; - #endregion - - /// - /// Returns an object that has been stored with a collectionId of 0. A new object will be created if no stored objects are available. - /// - /// PrefabId of the object to return. - /// True if being called on the server side. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override NetworkObject RetrieveObject(int prefabId, bool asServer) - { - return RetrieveObject(prefabId, 0, asServer); - } - - /// - /// Returns an object that has been stored. A new object will be created if no stored objects are available. - /// - /// PrefabId of the object to return. - /// CollectionId of the prefab. - /// True if being called on the server side. - /// - public override NetworkObject RetrieveObject(int prefabId, ushort collectionId, bool asServer) - { - PrefabObjects po = base.NetworkManager.GetPrefabObjects(collectionId, false); - //Quick exit/normal retrieval when not using pooling. - if (!_enabled) - { - NetworkObject prefab = po.GetObject(asServer, prefabId); - return Instantiate(prefab); - } - - Stack cache = GetOrCreateCache(collectionId, prefabId); - NetworkObject nob; - //Iterate until nob is populated just in case cache entries have been destroyed. - do - { - if (cache.Count == 0) - { - NetworkObject prefab = po.GetObject(asServer, prefabId); - /* A null nob should never be returned from spawnables. This means something - * else broke, likely unrelated to the object pool. */ - nob = Instantiate(prefab); - //Can break instantly since we know nob is not null. - break; - } - else - { - nob = cache.Pop(); - } - - } while (nob == null); - - nob.gameObject.SetActive(true); - return nob; - } - /// - /// Stores an object into the pool. - /// - /// Object to store. - /// True if being called on the server side. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override void StoreObject(NetworkObject instantiated, bool asServer) - { - //Pooling is not enabled. - if (!_enabled) - { - Destroy(instantiated.gameObject); - return; - } - - instantiated.gameObject.SetActive(false); - instantiated.ResetForObjectPool(); - Stack cache = GetOrCreateCache(instantiated.SpawnableCollectionId, instantiated.PrefabId); - cache.Push(instantiated); - } - - /// - /// Instantiates a number of objects and adds them to the pool. - /// - /// Prefab to cache. - /// Quantity to spawn. - /// True if storing prefabs for the server collection. This is only applicable when using DualPrefabObjects. - public void CacheObjects(NetworkObject prefab, int count, bool asServer) - { - if (!_enabled) - return; - if (count <= 0) - return; - if (prefab == null) - return; - if (prefab.PrefabId == NetworkObject.UNSET_PREFABID_VALUE) - { - InstanceFinder.NetworkManager.LogError($"Pefab {prefab.name} has an invalid prefabId and cannot be cached."); - return; - } - - Stack cache = GetOrCreateCache(prefab.SpawnableCollectionId, prefab.PrefabId); - for (int i = 0; i < count; i++) - { - NetworkObject nob = Instantiate(prefab); - nob.gameObject.SetActive(false); - cache.Push(nob); - } - } - - /// - /// Clears pools for all collectionIds - /// - public void ClearPool() - { - int count = _cache.Count; - for (int i = 0; i < count; i++) - ClearPool(i); - } - - /// - /// Clears a pool for collectionId. - /// - /// CollectionId to clear for. - public void ClearPool(int collectionId) - { - if (collectionId >= _cacheCount) - return; - - Dictionary> dict = _cache[collectionId]; - //Convert to a list from the stack so we do not modify the stack directly. - ListCache nobCache = ListCaches.GetNetworkObjectCache(); - foreach (Stack item in dict.Values) - { - while (item.Count > 0) - nobCache.AddValue(item.Pop()); - } - } - - - /// - /// Gets a cache for an id or creates one if does not exist. - /// - /// - /// - private Stack GetOrCreateCache(int collectionId, int prefabId) - { - if (collectionId >= _cacheCount) - { - //Add more to the cache. - while (_cache.Count <= collectionId) - { - Dictionary> dict = new Dictionary>(); - _cache.Add(dict); - } - _cacheCount = collectionId; - } - - Dictionary> dictionary = _cache[collectionId]; - Stack cache; - //No cache for prefabId yet, make one. - if (!dictionary.TryGetValueIL2CPP(prefabId, out cache)) - { - cache = new Stack(); - dictionary[prefabId] = cache; - } - return cache; - } - } - - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Performance/DefaultObjectPool.cs.meta b/Assets/FishNet/Runtime/Utility/Performance/DefaultObjectPool.cs.meta deleted file mode 100644 index c88391a..0000000 --- a/Assets/FishNet/Runtime/Utility/Performance/DefaultObjectPool.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: cb13d174096685549b1d6a94d726ff7d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Performance/ListCache.cs b/Assets/FishNet/Runtime/Utility/Performance/ListCache.cs deleted file mode 100644 index d252efa..0000000 --- a/Assets/FishNet/Runtime/Utility/Performance/ListCache.cs +++ /dev/null @@ -1,341 +0,0 @@ -using FishNet.Connection; -using FishNet.Managing; -using FishNet.Object; -using FishNet.Serializing.Helping; -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Utility.Performance -{ - /// - /// Various ListCache instances that may be used on the Unity thread. - /// - public static class ListCaches - { - - /// - /// Cache collection for NetworkObjects. - /// - private static Stack> _networkObjectCaches = new Stack>(); - /// - /// Cache collection for NetworkObjects. - /// - private static Stack> _networkBehaviourCaches = new Stack>(); - /// - /// Cache collection for NetworkObjects. - /// - private static Stack> _transformCaches = new Stack>(); - /// - /// Cache collection for NetworkConnections. - /// - private static Stack> _networkConnectionCaches = new Stack>(); - /// - /// Cache collection for ints. - /// - private static Stack> _intCaches = new Stack>(); - - - #region GetCache. - /// - /// Returns a NetworkObject cache. Use StoreCache to return the cache. - /// - /// - public static ListCache GetNetworkObjectCache() - { - ListCache result; - if (_networkObjectCaches.Count == 0) - result = new ListCache(); - else - result = _networkObjectCaches.Pop(); - - return result; - } - /// - /// Returns a NetworkConnection cache. Use StoreCache to return the cache. - /// - /// - public static ListCache GetNetworkConnectionCache() - { - ListCache result; - if (_networkConnectionCaches.Count == 0) - result = new ListCache(); - else - result = _networkConnectionCaches.Pop(); - - return result; - } - /// - /// Returns a Transform cache. Use StoreCache to return the cache. - /// - /// - public static ListCache GetTransformCache() - { - ListCache result; - if (_transformCaches.Count == 0) - result = new ListCache(); - else - result = _transformCaches.Pop(); - - return result; - } - /// - /// Returns a NetworkBehaviour cache. Use StoreCache to return the cache. - /// - /// - public static ListCache GetNetworkBehaviourCache() - { - ListCache result; - if (_networkBehaviourCaches.Count == 0) - result = new ListCache(); - else - result = _networkBehaviourCaches.Pop(); - - return result; - } - /// - /// Returns an int cache. Use StoreCache to return the cache. - /// - /// - public static ListCache GetIntCache() - { - ListCache result; - if (_intCaches.Count == 0) - result = new ListCache(); - else - result = _intCaches.Pop(); - - return result; - } - #endregion - - #region StoreCache. - /// - /// Stores a NetworkObject cache. - /// - /// - public static void StoreCache(ListCache cache) - { - cache.Reset(); - _networkObjectCaches.Push(cache); - } - /// - /// Stores a NetworkConnection cache. - /// - /// - public static void StoreCache(ListCache cache) - { - cache.Reset(); - _networkConnectionCaches.Push(cache); - } - /// - /// Stores a Transform cache. - /// - /// - public static void StoreCache(ListCache cache) - { - cache.Reset(); - _transformCaches.Push(cache); - } - /// - /// Stores a NetworkBehaviour cache. - /// - /// - public static void StoreCache(ListCache cache) - { - cache.Reset(); - _networkBehaviourCaches.Push(cache); - } - /// - /// Stores an int cache. - /// - /// - public static void StoreCache(ListCache cache) - { - cache.Reset(); - _intCaches.Push(cache); - } - #endregion - - } - - /// - /// Creates a reusable cache of T which auto expands. - /// - public class ListCache - { - #region Public. - /// - /// Collection cache is for. - /// - public List Collection = new List(); - /// - /// Entries currently written. - /// - public int Written => Collection.Count; - #endregion - - #region Private. - /// - /// Cache for type. - /// - private Stack _cache = new Stack(); - #endregion - - public ListCache() - { - Collection = new List(); - } - public ListCache(int capacity) - { - Collection = new List(capacity); - } - - /// - /// Returns T from cache when possible, or creates a new object when not. - /// - /// - private T Retrieve() - { - if (_cache.Count > 0) - return _cache.Pop(); - else - return Activator.CreateInstance(); - } - /// - /// Stores value into the cache. - /// - /// - private void Store(T value) - { - _cache.Push(value); - } - - /// - /// Adds a new value to Collection and returns it. - /// - /// - public T AddReference() - { - T next = Retrieve(); - Collection.Add(next); - return next; - } - - /// - /// Inserts an bject into Collection and returns it. - /// - /// - public T InsertReference(int index) - { - //Would just be at the end anyway. - if (index >= Collection.Count) - return AddReference(); - - T next = Retrieve(); - Collection.Insert(index, next); - return next; - } - - /// - /// Adds value to Collection. - /// - /// - public void AddValue(T value) - { - Collection.Add(value); - } - - /// - /// Inserts value into Collection. - /// - /// - - public void InsertValue(int index, T value) - { - //Would just be at the end anyway. - if (index >= Collection.Count) - AddValue(value); - else - Collection.Insert(index, value); - } - - /// - /// Adds values to Collection. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void AddValues(ListCache values) - { - int w = values.Written; - List c = values.Collection; - for (int i = 0; i < w; i++) - AddValue(c[i]); - } - /// - /// Adds values to Collection. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void AddValues(T[] values) - { - for (int i = 0; i < values.Length; i++) - AddValue(values[i]); - } - /// - /// Adds values to Collection. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void AddValues(List values) - { - for (int i = 0; i < values.Count; i++) - AddValue(values[i]); - } - /// - /// Adds values to Collection. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void AddValues(HashSet values) - { - foreach (T item in values) - AddValue(item); - } - /// - /// Adds values to Collection. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void AddValues(ISet values) - { - foreach (T item in values) - AddValue(item); - } - - /// - /// Adds values to Collection. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void AddValues(IReadOnlyCollection values) - { - foreach (T item in values) - AddValue(item); - } - - - /// - /// Resets cache. - /// - public void Reset() - { - foreach (T item in Collection) - Store(item); - Collection.Clear(); - } - } - - -} diff --git a/Assets/FishNet/Runtime/Utility/Performance/ListCache.cs.meta b/Assets/FishNet/Runtime/Utility/Performance/ListCache.cs.meta deleted file mode 100644 index 4b13d4c..0000000 --- a/Assets/FishNet/Runtime/Utility/Performance/ListCache.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 488b0788adfd9ee43977abd5d0280124 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Performance/ObjectPool.cs b/Assets/FishNet/Runtime/Utility/Performance/ObjectPool.cs deleted file mode 100644 index f35d6b4..0000000 --- a/Assets/FishNet/Runtime/Utility/Performance/ObjectPool.cs +++ /dev/null @@ -1,47 +0,0 @@ -using FishNet.Managing; -using FishNet.Object; -using System; -using UnityEngine; - -namespace FishNet.Utility.Performance -{ - - public abstract class ObjectPool : MonoBehaviour - { - /// - /// NetworkManager this ObjectPool belongs to. - /// - protected NetworkManager NetworkManager {get; private set;} - - /// - /// Initializes this script for use. - /// - public virtual void InitializeOnce(NetworkManager nm) - { - NetworkManager = nm; - } - - /// - /// Returns an object that has been stored using collectioNid of 0. A new object will be created if no stored objects are available. - /// - /// PrefabId of the object to return. - /// True if being called on the server side. - /// - public abstract NetworkObject RetrieveObject(int prefabId, bool asServer); - /// - /// Returns an object that has been stored. A new object will be created if no stored objects are available. - /// - /// PrefabId of the object to return. - /// True if being called on the server side. - /// - public virtual NetworkObject RetrieveObject(int prefabId, ushort collectionId, bool asServer) => null; - /// - /// Stores an object into the pool. - /// - /// Object to store. - /// True if being called on the server side. - /// - public abstract void StoreObject(NetworkObject instantiated, bool asServer); - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Performance/ObjectPool.cs.meta b/Assets/FishNet/Runtime/Utility/Performance/ObjectPool.cs.meta deleted file mode 100644 index e5ee86a..0000000 --- a/Assets/FishNet/Runtime/Utility/Performance/ObjectPool.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6ec7d855ffa7afc45b619b84ddbda27c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Performance/RingBuffer.cs b/Assets/FishNet/Runtime/Utility/Performance/RingBuffer.cs deleted file mode 100644 index 0486c16..0000000 --- a/Assets/FishNet/Runtime/Utility/Performance/RingBuffer.cs +++ /dev/null @@ -1,339 +0,0 @@ -using FishNet.Documenting; -using FishNet.Managing; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine; - -namespace FishNet.Utility -{ - - /// - /// Writes values to a collection of a set size, overwriting old values as needed. - /// - public class RingBuffer - { - #region Types. - /// - /// Custom enumerator to prevent garbage collection. - /// - [APIExclude] - public struct Enumerator : IEnumerator - { - #region Public. - /// - /// Current entry in the enumerator. - /// - public T Current { get; private set; } - /// - /// Actual index of the last enumerated value. - /// - public int ActualIndex - { - get - { - int total = (_startIndex + (_read - 1)); - int capacity = _rollingCollection.Capacity; - if (total >= capacity) - total -= capacity; - - return total; - } - } - /// - /// Simulated index of the last enumerated value. - /// - public int SimulatedIndex => (_read - 1); - #endregion - - #region Private. - /// - /// RollingCollection to use. - /// - private RingBuffer _rollingCollection; - /// - /// Collection to iterate. - /// - private readonly T[] _collection; - /// - /// Number of entries read during the enumeration. - /// - private int _read; - /// - /// Start index of enumerations. - /// - private int _startIndex; - #endregion - - public Enumerator(RingBuffer c) - { - _read = 0; - _startIndex = 0; - _rollingCollection = c; - _collection = c.Collection; - Current = default; - } - - public bool MoveNext() - { - int written = _rollingCollection.Count; - if (_read >= written) - { - ResetRead(); - return false; - } - - int index = (_startIndex + _read); - int capacity = _rollingCollection.Capacity; - if (index >= capacity) - index -= capacity; - Current = _collection[index]; - - _read++; - - return true; - } - - /// - /// Sets a new start index to begin reading at. - /// - public void SetStartIndex(int index) - { - _startIndex = index; - ResetRead(); - } - - - /// - /// Sets a new start index to begin reading at. - /// - public void AddStartIndex(int value) - { - _startIndex += value; - - int cap = _rollingCollection.Capacity; - if (_startIndex > cap) - _startIndex -= cap; - else if (_startIndex < 0) - _startIndex += cap; - - ResetRead(); - } - - /// - /// Resets number of entries read during the enumeration. - /// - public void ResetRead() - { - _read = 0; - } - - /// - /// Resets read count. - /// - public void Reset() - { - _startIndex = 0; - ResetRead(); - } - - object IEnumerator.Current => Current; - public void Dispose() { } - } - - #endregion - - #region Public. - /// - /// Current write index of the collection. - /// - public int WriteIndex { get; private set; } - /// - /// Number of entries currently written. - /// - public int Count => _written; - /// - /// Maximum size of the collection. - /// - public int Capacity => Collection.Length; - /// - /// Collection being used. - /// - public T[] Collection = new T[0]; - /// - /// True if initialized. - /// - public bool Initialized { get; private set; } - #endregion - - #region Private. - /// - /// Number of entries written. This will never go beyond the capacity but will be less until capacity is filled. - /// - private int _written; - /// - /// Enumerator for the collection. - /// - private Enumerator _enumerator; - #endregion - - /// - /// Initializes the collection at length. - /// - /// Size to initialize the collection as. This cannot be changed after initialized. - public void Initialize(int capacity) - { - if (capacity <= 0) - { - NetworkManager.StaticLogError($"Collection length must be larger than 0."); - return; - } - - Collection = new T[capacity]; - _enumerator = new Enumerator(this); - Initialized = true; - } - - /// - /// Clears the collection to default values and resets indexing. - /// - public void Clear() - { - for (int i = 0; i < Collection.Length; i++) - Collection[i] = default; - - Reset(); - } - /// - /// Resets the collection without clearing. - /// - public void Reset() - { - _written = 0; - WriteIndex = 0; - _enumerator.Reset(); - } - - /// - /// Adds an entry to the collection, returning a replaced entry. - /// - /// Data to add. - /// Replaced entry. Value will be default if no entry was replaced. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public T Add(T data) - { - if (!IsInitializedWithError()) - return default; - - int capacity = Capacity; - T current = Collection[WriteIndex]; - Collection[WriteIndex] = data; - - WriteIndex++; - _written++; - //If index would exceed next iteration reset it. - if (WriteIndex >= capacity) - WriteIndex = 0; - - /* If written has exceeded capacity - * then the start index needs to be moved - * to adjust for overwritten values. */ - if (_written > capacity) - { - _written = capacity; - _enumerator.SetStartIndex(WriteIndex); - } - - return current; - } - - /// - /// Returns value in actual index as it relates to simulated index. - /// - /// Simulated index to return. A value of 0 would return the first simulated index in the collection. - /// - public T this[int simulatedIndex] - { - get - { - int offset = (Capacity - _written) + simulatedIndex + WriteIndex; - if (offset >= Capacity) - offset -= Capacity; - return Collection[offset]; - } - set - { - int offset = (Capacity - _written) + simulatedIndex + WriteIndex; - if (offset >= Capacity) - offset -= Capacity; - Collection[offset] = value; - } - } - - /// - /// Returns Enumerator for the collection. - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator GetEnumerator() - { - if (!IsInitializedWithError()) - return default; - - _enumerator.ResetRead(); - return _enumerator; - } - - /// - /// Removes values from the simulated start of the collection. - /// - /// True to remove from the start, false to remove from the end. - /// Number of entries to remove. - public void RemoveRange(bool fromStart, int length) - { - if (length == 0) - return; - if (length < 0) - { - NetworkManager.StaticLogError($"Negative values cannot be removed."); - return; - } - //Full reset if value is at or more than written. - if (length >= _written) - { - Reset(); - return; - } - - _written -= length; - if (fromStart) - { - _enumerator.AddStartIndex(length); - } - else - { - - WriteIndex -= length; - if (WriteIndex < 0) - WriteIndex += Capacity; - } - } - - /// - /// Returns if initialized and errors if not. - /// - /// - private bool IsInitializedWithError() - { - if (!Initialized) - { - NetworkManager.StaticLogError($"RingBuffer has not yet been initialized."); - return false; - } - - return true; - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Performance/RingBuffer.cs.meta b/Assets/FishNet/Runtime/Utility/Performance/RingBuffer.cs.meta deleted file mode 100644 index 05ff562..0000000 --- a/Assets/FishNet/Runtime/Utility/Performance/RingBuffer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a066c51d748a04546875bd7d43118837 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/Performance/Transforms.cs b/Assets/FishNet/Runtime/Utility/Performance/Transforms.cs deleted file mode 100644 index 59eb1a5..0000000 --- a/Assets/FishNet/Runtime/Utility/Performance/Transforms.cs +++ /dev/null @@ -1,39 +0,0 @@ -using FishNet.Object; -using System.Collections.Generic; -using UnityEngine; - -namespace FishNet.Utility.Performance -{ - - public static class GetNonAlloc - { - /// - /// - /// - private static List _transformList = new List(); - /// - /// - /// - private static List _networkBehavioursList = new List(); - - /// - /// Gets all NetworkBehaviours on a transform. - /// - public static List GetNetworkBehaviours(this Transform t) - { - t.GetComponents(_networkBehavioursList); - return _networkBehavioursList; - } - - /// - /// Gets all transforms on transform and it's children. - /// - public static List GetTransformsInChildrenNonAlloc(this Transform t, bool includeInactive = false) - { - t.GetComponentsInChildren(includeInactive, _transformList); - return _transformList; - } - - } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/Performance/Transforms.cs.meta b/Assets/FishNet/Runtime/Utility/Performance/Transforms.cs.meta deleted file mode 100644 index b2bc83c..0000000 --- a/Assets/FishNet/Runtime/Utility/Performance/Transforms.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7d0740f919077254c8ffb131b9587407 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Runtime/Utility/SceneAttribute.cs b/Assets/FishNet/Runtime/Utility/SceneAttribute.cs deleted file mode 100644 index dd343a7..0000000 --- a/Assets/FishNet/Runtime/Utility/SceneAttribute.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UnityEngine; - -namespace FishNet.Utility -{ - /* Source https://forum.unity.com/threads/how-to-link-scenes-in-the-inspector.383140/ */ - - /// - /// Converts a string property into a Scene property in the inspector - /// - public class SceneAttribute : PropertyAttribute { } - -} \ No newline at end of file diff --git a/Assets/FishNet/Runtime/Utility/SceneAttribute.cs.meta b/Assets/FishNet/Runtime/Utility/SceneAttribute.cs.meta deleted file mode 100644 index 5d3afce..0000000 --- a/Assets/FishNet/Runtime/Utility/SceneAttribute.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3684fb9a5dec7454b8ad791f5ef19164 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/THIRD PARTY NOTICE.md b/Assets/FishNet/THIRD PARTY NOTICE.md deleted file mode 100644 index 343ab60..0000000 --- a/Assets/FishNet/THIRD PARTY NOTICE.md +++ /dev/null @@ -1,82 +0,0 @@ -This package contains third-party software components governed by the license(s) indicated below: - -Component Name: LiteNetLib -License Type: MIT -Copyright (c) 2020 Ruslan Pyrch -Copyright (c) 2021, Benjamin Berwick of FirstGearGames LLC, registered 2018, North Carolina. - -Paths: FishNet\Runtime\Transporting\Transports\Tugboat\LiteNetLib - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - - -Component Name: CodeGen Helpers(extensions). -License Type: MIT -Copyright (c) 2015, Unity Technologies -Copyright (c) 2019, vis2k, Paul and Contributors -Copyright (c) 2021, Benjamin Berwick of FirstGearGames LLC, registered 2018, North Carolina. - -Paths: FishNet/CodeGenerating/Helpers/ - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - - -Component Name: MonoCecil -License Type: MIT -Copyright (c) 2008 - 2015 Jb Evain -Copyright (c) 2008 - 2011 Novell, Inc. - -Paths: FishNet/CodeGenerating/cecil-xxxxx - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Assets/FishNet/THIRD PARTY NOTICE.md.meta b/Assets/FishNet/THIRD PARTY NOTICE.md.meta deleted file mode 100644 index f9ad4bb..0000000 --- a/Assets/FishNet/THIRD PARTY NOTICE.md.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 6ee8e3f1530d3594488bfe438dced5ea -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Upgrading.meta b/Assets/FishNet/Upgrading.meta deleted file mode 100644 index 96ab21b..0000000 --- a/Assets/FishNet/Upgrading.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 45e9a7bff88078f49ae15609740702eb -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Upgrading/MirrorUpgrade.cs b/Assets/FishNet/Upgrading/MirrorUpgrade.cs deleted file mode 100644 index 31a2d99..0000000 --- a/Assets/FishNet/Upgrading/MirrorUpgrade.cs +++ /dev/null @@ -1,428 +0,0 @@ -#if UNITY_EDITOR -#if MIRROR -using UnityEditor; -using UnityEngine; -using FishNet.Object; -using FishNet.Documenting; -using System.Collections.Generic; -using FNNetworkTransform = FishNet.Component.Transforming.NetworkTransform; -using FNNetworkAnimator = FishNet.Component.Animating.NetworkAnimator; -using FNNetworkObserver = FishNet.Observing.NetworkObserver; -using FishNet.Observing; -using FishNet.Component.Observing; -using FishNet.Editing; -using System.IO; -using System.Collections; -using Mirror; -using MirrorNetworkTransformBase = Mirror.NetworkTransformBase; -using MirrorNetworkTransformChild = Mirror.NetworkTransformChild; -using MirrorNetworkAnimator = Mirror.NetworkAnimator; -#if !MIRROR_57_0_OR_NEWER -using MirrorNetworkProximityChecker = Mirror.NetworkProximityChecker; -using MirrorNetworkSceneChecker = Mirror.NetworkSceneChecker; -#endif - -#if FGG_ASSETS -using FlexNetworkAnimator = FirstGearGames.Mirrors.Assets.FlexNetworkAnimators.FlexNetworkAnimator; -using FlexNetworkTransformBase = FirstGearGames.Mirrors.Assets.FlexNetworkTransforms.FlexNetworkTransformBase; -using FastProximityChecker = FirstGearGames.Mirrors.Assets.NetworkProximities.FastProximityChecker; -#endif - -#if FGG_PROJECTS -using FlexSceneChecker = FirstGearGames.FlexSceneManager.FlexSceneChecker; -#endif - -namespace FishNet.Upgrading.Mirror.Editing -{ - - /* IMPORTANT IMPORTANT IMPORTANT IMPORTANT - * If you receive errors about missing Mirror components, - * such as NetworkIdentity, then remove MIRROR and any other - * MIRROR defines. - * Project Settings -> Player -> Other -> Scripting Define Symbols. - * - * If you are also using my assets add FGG_ASSETS to the defines, and - * then remove it after running this script. */ - [APIExclude] - [ExecuteInEditMode] - [InitializeOnLoad] - public class MirrorUpgrade : MonoBehaviour - { - /// - /// SceneCondition within FishNet. - /// - private SceneCondition _sceneCondition = null; - /// - /// DistanceCondition created for the user. - /// - private DistanceCondition _distanceCondition = null; - /// - /// - /// - private int _replacedNetworkTransforms; - /// - /// - /// - private int _replacedNetworkAnimators; - /// - /// - /// - private int _replacedNetworkIdentities; - /// - /// - /// - private int _replacedSceneCheckers; - /// - /// - /// - private int _replacedProximityCheckers; - /// - /// True if anything was changed. - /// - private bool _changed; - /// - /// Index in gameObjects to iterate. - /// - private int _goIndex = -1; - /// - /// Found gameObjects to iterate. - /// - private List _gameObjects = new List(); - /// - /// True if initialized. - /// - private bool _initialized; - - - private const string OBJECT_NAME_PREFIX = "MirrorUpgrade"; - - - private void Awake() - { - gameObject.name = OBJECT_NAME_PREFIX; - Debug.Log($"{gameObject.name} is working. Please wait until this object is removed from your hierarchy."); - EditorApplication.update += EditorUpdate; - } - - private void OnDestroy() - { - EditorApplication.update -= EditorUpdate; - } - - private void EditorUpdate() - { - if (!_initialized) - { - FindConditions(true); - _gameObjects = Finding.GetGameObjects(true, false, true, new string[] { "/Mirror/" }); - _goIndex = 0; - _initialized = true; - } - - if (_goIndex == -1) - return; - if (_goIndex >= _gameObjects.Count) - { - gameObject.name = $"{OBJECT_NAME_PREFIX} - 100%"; - Debug.Log($"Switched {_replacedNetworkTransforms} NetworkTransforms."); - Debug.Log($"Switched {_replacedNetworkAnimators} NetworkAnimators."); - Debug.Log($"Switched {_replacedSceneCheckers} SceneCheckers."); - Debug.Log($"Switched {_replacedProximityCheckers} ProximityCheckers."); - Debug.Log($"Switched {_replacedNetworkIdentities} NetworkIdentities."); - - if (_changed) - PrintSaveWarning(); - - DestroyImmediate(gameObject); - return; - } - - float percentFloat = ((float)_goIndex / (float)_gameObjects.Count) * 100f; - int percentInt = Mathf.FloorToInt(percentFloat); - gameObject.name = $"{OBJECT_NAME_PREFIX} - {percentInt}%"; - - GameObject go = _gameObjects[_goIndex]; - _goIndex++; - //Go went empty? - if (go == null) - return; - - /* When a component is removed - * changed is set true and remove count is increased. - * _goIndex is also returned before exiting the method. - * This will cause the same gameObject to iterate - * next update. This is important because the components - * must be Switched in order, and I can only remove one - * component per frame without Unity throwing a fit and - * freezing. A while loop doesn't let Unity recognize the component - * is gone(weird right? maybe editor thing), and a coroutine - * doesn't show errors well, they just fail silently. */ - - bool changedThisFrame = false; - if (IterateNetworkTransform(go)) - { - changedThisFrame = true; - _changed = true; - _replacedNetworkTransforms++; - } - if (IterateNetworkAnimator(go)) - { - changedThisFrame = true; - _changed = true; - _replacedNetworkAnimators++; - } - - if (IterateSceneChecker(go)) - { - changedThisFrame = true; - _changed = true; - _replacedSceneCheckers++; - } - if (IterateProximityChecker(go)) - { - changedThisFrame = true; - _changed = true; - _replacedProximityCheckers++; - } - if (changedThisFrame) - { - _goIndex--; - return; - } - //NetworkIdentity must be done last. - if (IterateNetworkIdentity(go)) - { - _changed = true; - _replacedNetworkIdentities++; - } - } - - - /// - /// Finds Condition scripts to be used with NetworkObserver. - /// - /// - private void FindConditions(bool error) - { - List scriptableObjects; - - if (_sceneCondition == null) - { - scriptableObjects = Finding.GetScriptableObjects(true, true); - //Use the first found scene condition, there should be only one. - if (scriptableObjects.Count > 0) - _sceneCondition = (SceneCondition)scriptableObjects[0]; - - if (_sceneCondition == null && error) - Debug.LogError("SceneCondition could not be found. Upgrading scene checker components will not function."); - } - - if (_distanceCondition == null) - { - scriptableObjects = Finding.GetScriptableObjects(false, true); - if (scriptableObjects.Count > 0) - { - _distanceCondition = (DistanceCondition)scriptableObjects[0]; - } - else - { - DistanceCondition dc = ScriptableObject.CreateInstance(); - string savePath = "Assets"; - AssetDatabase.CreateAsset(dc, Path.Combine(savePath, $"CreatedDistanceCondition.asset")); - Debug.LogWarning($"DistanceCondition has been created at {savePath}. Place this file somewhere within your project and change settings to your liking."); - } - - if (_distanceCondition == null && error) - Debug.LogError("DistanceCondition could not be found. Upgrading proximity checker components will not function."); - } - } - - - private bool IterateNetworkTransform(GameObject go) - { - if (go.TryGetComponent(out MirrorNetworkTransformBase nt1)) - { - Transform target; - if (nt1 is MirrorNetworkTransformChild mc1) - target = mc1.target; - else - target = go.transform; - Replace(nt1, target); - return true; - } -#if FGG_ASSETS - if (go.TryGetComponent(out FlexNetworkTransformBase fntb)) - { - Replace(fntb, fntb.TargetTransform); - return true; - } -#endif - - void Replace(UnityEngine.Component component, Transform target) - { - EditorUtility.SetDirty(go); - DestroyImmediate(component, true); - - if (target != null && !target.TryGetComponent(out _)) - target.gameObject.AddComponent(); - } - - //Fall through, nothing was replaced. - return false; - } - - private bool IterateNetworkAnimator(GameObject go) - { - if (go.TryGetComponent(out MirrorNetworkAnimator mna)) - { - Replace(mna, mna.transform); - return true; - } -#if FGG_ASSETS - if (go.TryGetComponent(out FlexNetworkAnimator fna)) - { - Replace(fna, fna.transform); - return true; - } -#endif - - void Replace(UnityEngine.Component component, Transform target) - { - EditorUtility.SetDirty(go); - DestroyImmediate(component, true); - - if (target == null) - return; - if (!target.TryGetComponent(out _)) - target.gameObject.AddComponent(); - } - - return false; - } - - - private bool IterateSceneChecker(GameObject go) - { -#if !MIRROR_57_0_OR_NEWER - if (_sceneCondition == null) - return false; - - if (go.TryGetComponent(out MirrorNetworkSceneChecker msc)) - { - Replace(msc); - return true; - } -#if FGG_PROJECTS - if (go.TryGetComponent(out FlexSceneChecker fsc)) - { - Replace(fsc); - return true; - } -#endif - - void Replace(UnityEngine.Component component) - { - EditorUtility.SetDirty(go); - DestroyImmediate(component, true); - - FNNetworkObserver networkObserver; - if (!go.TryGetComponent(out networkObserver)) - networkObserver = go.AddComponent(); - - bool conditionFound = false; - foreach (ObserverCondition condition in networkObserver.ObserverConditions) - { - if (condition.GetType() == typeof(SceneCondition)) - { - conditionFound = true; - break; - } - } - - //If not able to find scene condition then add one. - if (!conditionFound) - networkObserver.ObserverConditionsInternal.Add(_sceneCondition); - } - -#endif - return false; - } - - - - private bool IterateProximityChecker(GameObject go) - { -#if !MIRROR_57_0_OR_NEWER - if (_distanceCondition == null) - return false; - - if (go.TryGetComponent(out MirrorNetworkProximityChecker mnpc)) - { - Replace(mnpc); - return true; - } -#if FGG_PROJECTS - if (go.TryGetComponent(out FastProximityChecker fpc)) - { - Replace(fpc); - return true; - } -#endif - - void Replace(UnityEngine.Component component) - { - EditorUtility.SetDirty(go); - DestroyImmediate(component, true); - - FNNetworkObserver networkObserver; - if (!go.TryGetComponent(out networkObserver)) - networkObserver = go.AddComponent(); - - bool conditionFound = false; - foreach (ObserverCondition condition in networkObserver.ObserverConditions) - { - if (condition.GetType() == typeof(DistanceCondition)) - { - conditionFound = true; - break; - } - } - - //If not able to find scene condition then add one. - if (!conditionFound) - networkObserver.ObserverConditionsInternal.Add(_distanceCondition); - } -#endif - - return false; - } - - - private bool IterateNetworkIdentity(GameObject go) - { - if (go.TryGetComponent(out NetworkIdentity netIdentity)) - { - EditorUtility.SetDirty(go); - DestroyImmediate(netIdentity, true); - - //Add nob if doesn't exist. - if (!go.TryGetComponent(out _)) - go.AddComponent(); - - return true; - } - - return false; - } - - - private static void PrintSaveWarning() - { - Debug.LogWarning("You must File -> Save for changes to complete."); - } - } - - -} -#endif -#endif \ No newline at end of file diff --git a/Assets/FishNet/Upgrading/MirrorUpgrade.cs.meta b/Assets/FishNet/Upgrading/MirrorUpgrade.cs.meta deleted file mode 100644 index b1d33a8..0000000 --- a/Assets/FishNet/Upgrading/MirrorUpgrade.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 491b9891492df1444937419bc0e39642 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/Upgrading/UpgradeFromMirrorMenu.cs b/Assets/FishNet/Upgrading/UpgradeFromMirrorMenu.cs deleted file mode 100644 index 5d77c2b..0000000 --- a/Assets/FishNet/Upgrading/UpgradeFromMirrorMenu.cs +++ /dev/null @@ -1,75 +0,0 @@ -#if UNITY_EDITOR -using FishNet.Documenting; -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; - -namespace FishNet.Upgrading.Mirror.Editing -{ - - /* IMPORTANT IMPORTANT IMPORTANT IMPORTANT - * If you receive errors about missing Mirror components, - * such as NetworkIdentity, then remove MIRROR and any other - * MIRROR defines. - * Project Settings -> Player -> Other -> Scripting Define Symbols. - * - * If you are also using my assets add FGG_ASSETS to the defines, and - * then remove it after running this script. */ - [APIExclude] - public class UpgradeFromMirrorMenu : MonoBehaviour - { - - /// - /// Replaces all components. - /// - [MenuItem("Fish-Networking/Upgrading/From Mirror/Replace Components", false,2)] - private static void ReplaceComponents() - { -#if MIRROR - MirrorUpgrade result = GameObject.FindObjectOfType(); - if (result != null) - { - Debug.LogError("MirrorUpgrade already exist in the scene. This suggests an operation is currently running."); - return; - } - - GameObject iteratorGo = new GameObject(); - iteratorGo.AddComponent(); -#else - Debug.LogError("Mirror must be imported to perform this function."); -#endif - } - - [MenuItem("Fish-Networking/Upgrading/From Mirror/Remove Defines", false, 2)] - private static void RemoveDefines() - { - string currentDefines = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup); - /* Convert current defines into a hashset. This is so we can - * determine if any of our defines were added. Only save playersettings - * when a define is added. */ - HashSet definesHs = new HashSet(); - string[] currentArr = currentDefines.Split(';'); - - bool removed = false; - //Add any define which doesn't contain MIRROR. - foreach (string item in currentArr) - { - string itemLower = item.ToLower(); - if (itemLower != "mirror" && !itemLower.StartsWith("mirror_")) - definesHs.Add(item); - else - removed = true; - } - - if (removed) - { - Debug.Log("Removed Mirror defines to player settings."); - string changedDefines = string.Join(";", definesHs); - PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, changedDefines); - } - } - - - } -} -#endif diff --git a/Assets/FishNet/Upgrading/UpgradeFromMirrorMenu.cs.meta b/Assets/FishNet/Upgrading/UpgradeFromMirrorMenu.cs.meta deleted file mode 100644 index 726fd8d..0000000 --- a/Assets/FishNet/Upgrading/UpgradeFromMirrorMenu.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 55cd1de3399bf564a9545f089421a88d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/FishNet/VERSION.txt b/Assets/FishNet/VERSION.txt deleted file mode 100644 index a37a75c..0000000 --- a/Assets/FishNet/VERSION.txt +++ /dev/null @@ -1 +0,0 @@ -3.5.8 \ No newline at end of file diff --git a/Assets/FishNet/VERSION.txt.meta b/Assets/FishNet/VERSION.txt.meta deleted file mode 100644 index fbab156..0000000 --- a/Assets/FishNet/VERSION.txt.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 84a91b39bff26504e9cf03f8aa4fe3ab -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Packages/Facepunch.meta b/Assets/Packages/Facepunch.meta deleted file mode 100644 index 740c17e..0000000 --- a/Assets/Packages/Facepunch.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 4c5607fd7c7f1864698e3d6f4d2f3a10 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Packages/Facepunch/Facepunch.Steamworks.Posix.dll b/Assets/Packages/Facepunch/Facepunch.Steamworks.Posix.dll deleted file mode 100644 index 6901913174ff26b92ffff48fcd702ecedac0f51f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 545280 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%0Aa&J4^y@ylDT?>!_)P)+YwD5zO=f;?!u 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�eh)E{Bg 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�&Oi}KD^^|+)Ar)jKO?d#OD-Xd;*?4 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

4PC(V6 zJtBGD2r{#XxkGB57)0op@x*tvv9xt?UlPsI1N7^7bEHX}zop3vMY@guu!#5Qvf9#Z zL3YNIwvLFA2hIQDQj>U9B=ArX)Qsew#->JGF;)?~9R@lr0w#lkS$HeS{$`W$;t=L; zZefb?t46Qil#mg$`uGnL-U)-7i~tM@CB6y+JwEqL!qB-ZY4da5x06~zBE_Y9@fHkO zf>J{7vV^jxNH!8H8;$IXNR+_q5t{c6_J5Md20V~d6C&3j*eaW_4v~Rnm}AmY)_3Xb zyYOCzstR7{L=#7qNA)`hhc6v6Wu7tf?@|s6Kaz$BjYkZx4_M8z3}I)rIuCsQ6888N z^jEURD)TE;5wx(l!QO{#-uO{#GS+q&m%}`*Aa)pOwk$TV*@LPYB#L1WE@+7uvhd3W zs8UnYA%^2a8bp#P#bMI1$QI|tDR)A>5~W6(o+UIZv?y_d0Vy4P9?LxAIFlqsRgIX5 zvqh08HR~5OQed5XQTmV$Yz>vsEs+#9y@x(-*I5_Z-cV?`Te-`jjWkd}>r_|RXk+UX zvXo@DMbB}_fn?*6@Grvxd;vqQG5_*z7UC;G3l@Txfc7$AnV*+nWsSEMyG#$xDFz;xMzirPqi^9V$1;Do zmne8|qg^GEYfmeyFiaS_iWdvY>j);4y8hc z069Gv%^I2>%g~x-g3Fssg=;ZbZRE0$EWnsO`*_Ec7Vp+&DQ6T&V4?ZZTi-m?1@sex9qvX0kmMFLzgvW%~z8xl4sA)ao+IMJiR zX+lhNA)fuh)jE>q1B&$R#LAZfexOam3L9d8A4pTP@&I@6h|^(|wgFk8ssaUpvbo1G zSM&htD?x49xV99vrKqjM3O#_@64XPf_4rC$Q4baMP(6TpD5yskMU_WVj}-L?cN*6t zK|Qu9K33FYMLouc=ZbnPs3$hACyIKas3(aPdLYFog2Go_5H~(3Qq)sLJyj2&o(k%j zMLkp0GeteaOSBr-GeK=z)V89w6}62o;1#tksOOgZ=Zbo+sORWM74=+DFKk>d6!k(; zFR*f;s275IX;Ci~^-@tU@wvUCUJB}!P4ShYUMcETVuc>a<13=dMp0!Ws4}J>dD9%haYZ3GuBf;q)z}6Hb3cumRHLFA z)dOG}-wAwC1qV;f8VnP)StDtd;8q*ls*$uR3brCWK-Ma#wzuG5X{Ak3ZHhwLWFdi< zf8gK=Z|yKUhw)$h?Qo!+RI;Q7C-FLuMxGSZ5i5)%iaMgGBbc00)Dc0oTU5KE+7;EF zDANOswhOA$qB<4Tsi;o$3ySI#RJTQSYjC$N2qKbh3GTJQy&6fcqA*+5E5WC1@F@*G zrNO5XWqKfzQ-Z?Q98!jTit1BTU!qJ8p!x)L+M-S?>a?OxC(85y>a?Iz7L`&|N>M4S zv?(ejs3D6Q(%>Pyrmew45Kc@?@(*-hy;(?T#ah*DBpW!*^XQPaZP(%gU1n| z)Z>D>Xi*mxbx~0lG0CB*i-MZ4s0l?)C~5+4D=TV3P?s#~k_KPmcU#3-DK`q#7x}c~9MJ|)J;LHS=5>a zui;%Hjbu%N*KP2+MzXG`b(kO${G|>4l2iH^aL78yeXO9Ah7Q0EUAT`?V`&JhOLB{O zlhROw_`?Vu63eq$ECR6$mRiLETWW7Rl-%30_#Wmc+FBOBa~Mg(c787yoXLO*8ThfV zaL2Mh6P9x>1Y-^cb|8&DoQh@d$`9)dOMX*No!lfj96q7Jmch+ptN3kMF>lf0EI;C` zFbwRJTu&!zM>geWn7ThyF}N}Nwc5k!Suq=fe##K z!%LP4$kVgL@|N1OoNB=8q&01q?tmf8Lf)YrkGTs@RyXZGh!Wt`Ij5>91cZ}Q97jd& zpX(=KaN`KXb1h5T1ma~}Qt_Q!&e^C`R}F)f_KH+FX@Vg1l=JxV35#O<9#r$C<0hbZ z`V?$z&H91r?I9V8HgXW&K(^y8Sw$xgf~c~s4DPW7{a?zaVh|^Gk*PchZ_C^2yui?+ z3E4*O@D3k2_zALfPdqlO9-D$LvFgCOy{!(b2%cCe;854$+zN zj3@0BE^bi8b-;>I{f2%1g2^>tzZ7|1(7`h%1Mg}|nuF4Fd0K8%$7t9KbzU+bl%mbp zswRD-S%Po0s-rYFq+}8+r^R!nQ=H|LI$FW*2N5mZS5&t;y*gONz5?=mLz%gusg*L~ zSsGDiRGo1}7R9l{x)M7G$ncUn)9U!@D6+I5Ps>^$%lGt2xmkXsPmiVaHUehL8ydrw zIuF%(tj<$$R*tCC9#rvdDkzS?Sh>Z#$^ICsp+CV8kh^6x$jreeieo>kP69IwqO5<7 z>axj4D*qSjl!$eBhC`cGXw`DjZM~%;>*(|<`-#|NeGHA!#XB=wUysw=L zLbzha7rssS9T2}$;&*3n97{W2!>|UwCOlwt4!WhU@F+20v4zjKi0k8J{6M_Y9Ngyf z#kW92ZG?mD(Q87Ie$Lw>FFv0!7aqr4I3DNmh&gMy-eeGFjuEHKe-U&*{MsdaO|I+J zH1CVYmvX%YFbw;Rw$A(pR`tyIp09uEImL5@{F!TMx5zCh$EUr*=d&^3 z_G6n+V}@hqce~D=86WhV8JF8gc2>5&yxQA!0#P)z20^LpY%%9tKL=zBX_7%m5?Jh( z`|X;|C<%7_^mIqxNTE<1$YtHU-#>djpZuRl=#1E40eC-sNtsuKb)WSom|e%q}*b`pC!Su40?r`vBI2}b}RY$Ud&)SP}iB!-9hCxU~RxjPrDapU9U!R)r>*hCu8R5uGGlb z*bGG2f7S7wYB5nDr()*V>*&t9ne5z5m=NNBQ-ULoH|2)uPDJZPkj>%Q!9p%q_&l2z z(H{qcQNIyiZvk-$gfe5+Rk5?5q-jvnUN5&KKwWj=m|^|7@U;_dO(r zt!9}Fv?5A&!}+VIIR)=}N8hJT7TkF$_i{F$Wn~t+9u(F<%zQsA^cq6ss)mSKHR@&4 zZdH?eP+y`nxjv5mTyEHRXR2h!dZLT1jx6tbj_;B%(63{t{!ztHLpR_#m;HJoF?0NNGWDFiKZ;6M2+0Hm{|3@=FFQ4bng@}jyh5>> zDpVk<7Su4?pUDJiR_RW?QFX>pP5n`{4%5zTO*T>NQ95^)4fl+51^V34H{iJ_zmdY^ z3~w7eIx`EJbghD#(&I)wU%%2G=S z>70(4KMYfzbA2|9$m0bct$I+sM&Xk}vle8w2bnz{Gu`0`Mj_Iy3qn@r{VDul z>6&VZZR5MbROj890&)f>oheso*|$h0k0O(OF>^9Zqq#vD`bh1(`{#4+tk1Svd;&gE zKcdQ{j+p66voEA!R-Ijuy1Aq8f~D(a+Af}^O+?pPbfr;e?wOYmV*v^KZgh=k z>*r>wg>e*x5o(G;6l29))`v2ruLMQHu~4W;LPY5Ft7sHpXyg>2&%3iYr9hjX%1DdN zdq>RteocX}-@2|nRYxB?=^%0xcZhu*QD_$;4YtI7ehwYh@JumBF+oaULsy0&kwhdw zd53Zkk;-{D?V>{^9;F>NQX&%=nC74^KjpIbCSgQZwUclRLp6e7C4@@h!c@BJOeTvS zv!icpZgM7DZNsS=?J@IvHBu#7wE~JBNc04le=lZ^L;?}%Y#L`zXfDwJMKGXIrotU7 zo8wTiRvEYet*nXppz8RUlPhjUroDkNo zyh2!PpaU$FBSH#Q)f_V7rc4n6x{Fvr0t1 ztm2^xA}Q4osR9d4H8m7=sDax_h~rT(RRFP4eC$3#J^D@xb`9jMI!^3Cwn8TO>&QHe zyff5_DyJy7{+Q{j(X-b?z^M@J5NcR}s)YLYoiWr%Om%3yP@_9NXiwfKXFEnG_v}nX z>3Yz%yc;vg9o%zFrA@Ha&5-IVhl-j)_k7l!nY6P7Ec9>3%)7h9Ni?aY(2(^|cUg_t z)-2m^Rt1jMD5{{fQKw1K(I=$R6$E6bP)?C#7`lkItLZhI_fyXGn!0sfKJ2 zV+$daTtTNWi>ZH3%v`jm{-77|exoP(;N?F2A*nq!F=PH^F#g{rc6O9LKg93xblg1t zNGDziB3r+M-?#9a%EryqA63KP#pBKD{?3o3#{TM^pS67B@1{QZ>DS-?$G3C;_9u)Z z_5Or2F^IZeoXe-DYlf1)hG${&&n8mt%RsObkpR7F9yFahN8G|V=FO|!kb+UOQXDzvI zS0(d+VrjmBqp5h7)$9LaBEvRg7V2@F^+ul%;ZNKUeis+wX1!XJxQ8N{Pt2J4 z4A(Q}Jnn|g$L1WKhjAUmJ^%iB?|?go_Kv#L`HeJ9}e#ZQ%`6lqp4G;73;5y*{9Ii8X zHb~V$S}u^5~f>NTJJ&;+`p8!+i#Es6JrL4e^fvKP52_097>C zh5ISQ<|7UAeOdVU*!ojK - - - Facepunch.Steamworks.Posix - - - -

- An awaitable version of a SteamAPICall_t - - - - - This gets called if IsComplete returned false on the first call. - The Action "continues" the async call. We pass it to the Dispatch - to be called when the callback returns. - - - - - Gets the result. This is called internally by the async shit. - - - - - Return true if complete or failed - - - - - This is what makes this struct awaitable - - - - - Gives us a generic way to get the CallbackId of structs - - - - - Cancels a ticket. - You should cancel your ticket when you close the game or leave a server. - - - - - Responsible for all callback/callresult handling - - This manually pumps Steam's message queue and dispatches those - events to any waiting callbacks/callresults. - - - - - If set then we'll call this function every time a callback is generated. - - This is SLOW!! - it's for debugging - don't keep it on all the time. If you want to access a specific - callback then please create an issue on github and I'll add it! - - Params are : [Callback Type] [Callback Contents] [server] - - - - - - Called if an exception happens during a callback/callresult. - This is needed because the exception isn't always accessible when running - async.. and can fail silently. With this hooked you won't be stuck wondering - what happened. - - - - - This gets called from Client/Server Init - It's important to switch to the manual dispatcher - - - - - Make sure we don't call Frame in a callback - because that'll cause some issues for everyone. - - - - - Calls RunFrame and processes events from this Steam Pipe - - - - - To be safe we don't call the continuation functions while iterating - the Callback list. This is maybe overly safe because the only way this - could be an issue is if the callback list is modified in the continuation - which would only happen if starting or shutting down in the callback. - - - - - A callback is a general global message - - - - - Given a callback, try to turn it into a string - - - - - A result is a reply to a specific command - - - - - Pumps the queue in an async loop so we don't - have to think about it. This has the advantage that - you can call .Wait() on async shit and it still works. - - - - - Pumps the queue in an async loop so we don't - have to think about it. This has the advantage that - you can call .Wait() on async shit and it still works. - - - - - Watch for a steam api call - - - - - Install a global callback. The passed function will get called if it's all good. - - - - - The score is just a simple numerical value - - - - - The score represents a time, in seconds - - - - - The score represents a time, in milliseconds - - - - - The top-score is the lowest number - - - - - The top-score is the highest number - - - - - Send the message unreliably. Can be lost. Messages *can* be larger than a - single MTU (UDP packet), but there is no retransmission, so if any piece - of the message is lost, the entire message will be dropped. - - The sending API does have some knowledge of the underlying connection, so - if there is no NAT-traversal accomplished or there is a recognized adjustment - happening on the connection, the packet will be batched until the connection - is open again. - - - - - Disable Nagle's algorithm. - By default, Nagle's algorithm is applied to all outbound messages. This means - that the message will NOT be sent immediately, in case further messages are - sent soon after you send this, which can be grouped together. Any time there - is enough buffered data to fill a packet, the packets will be pushed out immediately, - but partially-full packets not be sent until the Nagle timer expires. - - - - - If the message cannot be sent very soon (because the connection is still doing some initial - handshaking, route negotiations, etc), then just drop it. This is only applicable for unreliable - messages. Using this flag on reliable messages is invalid. - - - - Reliable message send. Can send up to 0.5mb in a single message. - Does fragmentation/re-assembly of messages under the hood, as well as a sliding window for - efficient sends of large chunks of data. - - - - Return a NetIdentity that represents LocalHost - - - - - Return true if this identity is localhost - - - - - Convert to a SteamId - - - - - - Set the specified Address - - - - - Automatically convert to a SteamId - - - - - - Returns NULL if we're not a SteamId - - - - - Returns NULL if we're not a NetAddress - - - - - We override tostring to provide a sensible representation - - - - - The Port. This is redundant documentation. - - - - - Any IP, specific port - - - - - Localhost IP, specific port - - - - - Specific IP, specific port - - - - - Specific IP, specific port - - - - - Set everything to zero - - - - - Return true if the IP is ::0. (Doesn't check port.) - - - - - Return true if IP is mapped IPv4 - - - - - Return true if this identity is localhost. (Either IPv6 ::1, or IPv4 127.0.0.1) - - - - - Get the Address section - - - - - Used as a base to create your client connection. This creates a socket - to a single connection. - - You can override all the virtual functions to turn it into what you - want it to do. - - - - - Accept an incoming connection that has been received on a listen socket. - - - - - Disconnects from the remote host and invalidates the connection handle. Any unread data on the - connection is discarded.. - reasonCode is defined and used by you. - - - - - Get/Set connection user data - - - - - A name for the connection, used mostly for debugging - - - - - This is the best version to use. - - - - - Ideally should be using an IntPtr version unless you're being really careful with the byte[] array and - you're not creating a new one every frame (like using .ToArray()) - - - - - Ideally should be using an IntPtr version unless you're being really careful with the byte[] array and - you're not creating a new one every frame (like using .ToArray()) - - - - - This creates a ton of garbage - so don't do anything with this beyond testing! - - - - - Flush any messages waiting on the Nagle timer and send them at the next transmission - opportunity (often that means right now). - - - - - Returns detailed connection stats in text format. Useful - for dumping to a log, etc. - - Plain text connection info - - - - Describe the state of a connection - - - - - High level state of the connection - - - - - Remote address. Might be all 0's if we don't know it, or if this is N/A. - - - - - Who is on the other end? Depending on the connection type and phase of the connection, we might not know - - - - - Basic cause of the connection termination or problem. - - - - - - Object that describes a "location" on the Internet with sufficient - detail that we can reasonably estimate an upper bound on the ping between - the two hosts, even if a direct route between the hosts is not possible, - and the connection must be routed through the Steam Datagram Relay network. - This does not contain any information that identifies the host. Indeed, - if two hosts are in the same building or otherwise have nearly identical - networking characteristics, then it's valid to use the same location - object for both of them. - - NOTE: This object should only be used in the same process! Do not serialize it, - send it over the wire, or persist it in a file or database! If you need - to do that, convert it to a string representation using the methods in - ISteamNetworkingUtils(). - - - - - Estimate the round-trip latency between two arbitrary locations, in - milliseconds. This is a conservative estimate, based on routing through - the relay network. For most basic relayed connections, this ping time - will be pretty accurate, since it will be based on the route likely to - be actually used. - - If a direct IP route is used (perhaps via NAT traversal), then the route - will be different, and the ping time might be better. Or it might actually - be a bit worse! Standard IP routing is frequently suboptimal! - - But even in this case, the estimate obtained using this method is a - reasonable upper bound on the ping time. (Also it has the advantage - of returning immediately and not sending any packets.) - - In a few cases we might not able to estimate the route. In this case - a negative value is returned. k_nSteamNetworkingPing_Failed means - the reason was because of some networking difficulty. (Failure to - ping, etc) k_nSteamNetworkingPing_Unknown is returned if we cannot - currently answer the question for some other reason. - - Do you need to be able to do this from a backend/matchmaking server? - You are looking for the "ticketgen" library. - - - - Destroy a listen socket. All the connections that were accepting on the listen - socket are closed ungracefully. - - - - - True if unlocked - - - - - Should hold the unlock time if State is true - - - - - Gets the icon of the achievement. This can return a null image even though the image exists if the image - hasn't been downloaded by Steam yet. You can use GetIconAsync if you want to wait for the image to be - downloaded. - - - - - Gets the icon of the achievement, waits for it to load if we have to - - - - - Returns the fraction (0-1) of users who have unlocked the specified achievement, or -1 if no data - available. - - - - - Make this achievement earned - - - - - Reset this achievement to not achieved - - - - - Sent for games with enabled anti indulgence / duration control, for enabled users. - Lets the game know whether persistent rewards or XP should be granted at normal rate, half rate, or zero - rate. - - - - - appid generating playtime - - - - - is duration control applicable to user + game combination - - - - - playtime since most recent 5 hour gap in playtime, only counting up to regulatory limit of playtime, in - seconds - - - - - playtime on current calendar day - - - - - recommended progress - - - - - the name of a leaderboard - - - - - Submit your score and replace your old score even if it was better - - - - - Submit your new score, but won't replace your high score if it's lower - - - - - Attaches a piece of user generated content the user's entry on a leaderboard - - - - - Used to query for a sequential range of leaderboard entries by leaderboard Sort. - - - - - Used to retrieve leaderboard entries relative a user's entry. If there are not enough entries in the - leaderboard - before or after the user's entry, Steam will adjust the range to try to return the number of entries - requested. - For example, if the user is #1 on the leaderboard and start is set to -2, end is set to 2, Steam will - return the first - 5 entries in the leaderboard. If The current user has no entry, this will return null. - - - - - Used to retrieve all leaderboard entries for friends of the current user - - - - - Try to join this room. Will return RoomEnter.Success on success, - and anything else is a failure - - - - - Leave a lobby; this will take effect immediately on the client side - other users in the lobby will be notified by a LobbyChatUpdate_t callback - - - - - Invite another user to the lobby - will return true if the invite is successfully sent, whether or not the target responds - returns false if the local user is not connected to the Steam servers - - - - - returns the number of users in the specified lobby - - - - - Returns current members. Need to be in the lobby to see the users. - - - - - Get data associated with this lobby - - - - - Get data associated with this lobby - - - - - Removes a metadata key from the lobby - - - - - Get all data for this lobby - - - - - Gets per-user metadata for someone in this lobby - - - - - Sets per-user metadata (for the local user implicitly) - - - - - Sends a string to the chat room - - - - - Sends bytes the the chat room - this isn't exposed because there's no way to read raw bytes atm, - and I figure people can send json if they want something more advanced - - - - - Refreshes metadata for a lobby you're not necessarily in right now - you never do this for lobbies you're a member of, only if your - this will send down all the metadata associated with a lobby - this is an asynchronous call - returns false if the local user is not connected to the Steam servers - results will be returned by a LobbyDataUpdate_t callback - if the specified lobby doesn't exist, LobbyDataUpdate_t::m_bSuccess will be set to false - - - - - Max members able to join this lobby. Cannot be over 250. - Can only be set by the owner - - - - - [SteamID variant] - Allows the owner to set the game server associated with the lobby. Triggers the - Steammatchmaking.OnLobbyGameCreated event. - - - - - [IP/Port variant] - Allows the owner to set the game server associated with the lobby. Triggers the - Steammatchmaking.OnLobbyGameCreated event. - - - - - Gets the details of the lobby's game server, if set. Returns true if the lobby is - valid and has a server set, otherwise returns false. - - - - - You must be the lobby owner to set the owner - - - - - Check if the specified SteamId owns the lobby - - - - - only lobbies in the same immediate region will be returned - - - - - only lobbies in the same immediate region will be returned - - - - - only lobbies in the same immediate region will be returned - - - - - Filter by specified key/value pair; string parameters - - - - - Numerical filter where value is less than the value provided - - - - - Numerical filter where value is greater than the value provided - - - - - Numerical filter where value must be equal to the value provided - - - - - Numerical filter where value must not equal the value provided - - - - - Test key, initialize numerical filter list if necessary, then add new numerical filter - - - - - Order filtered results according to key/values nearest the provided key/value pair. - Can specify multiple near value filters; each successive filter is lower priority than the previous. - - - - - returns only lobbies with the specified number of slots available - - - - - sets how many results to return, the lower the count the faster it is to download the lobby results - - - - - Run the query, get the matching lobbies - - - - - A server query packet. - - - - - Target IP address - - - - - Target port - - - - - This data is pooled. Make a copy if you don't use it immediately. - This buffer is also quite large - so pay attention to Size. - - - - - Size of the data - - - - - Represents a RemotePlaySession from the SteamRemotePlay interface - - - - - Returns true if this session was valid when created. This will stay true even - after disconnection - so be sure to watch SteamRemotePlay.OnSessionDisconnected - - - - - Get the SteamID of the connected user - - - - - Get the name of the session client device - - - - - Get the name of the session client device - - - - - Tags a user as being visible in the screenshot - - - - - Tags a user as being visible in the screenshot - - - - - Tags a user as being visible in the screenshot - - - - - Gets the individual tags for this server - - - - - Add this server to our history list - If we're already in the history list, weill set the last played time to now - - - - - If this server responds to source engine style queries, we'll be able to get a list of rules here - - - - - Remove this server from our history list - - - - - Add this server to our favourite list - - - - - Remove this server from our favourite list - - - - - Find out the status of an asynchronous inventory result handle. - - - - - Copies the contents of a result set into a flat array. The specific contents of the result set depend on - which query which was used. - - - - - Returns the server time at which the result was generated. Compare against the value of - IClientUtils::GetServerRealTime() to determine age. - - - - - Returns true if the result belongs to the target steam ID or false if the result does not. This is - important when using DeserializeResult to verify that a remote player is not pretending to have a - different users inventory. - - - - - Destroys a result handle and frees all associated memory. - - - - - Captures the entire state of the current users Steam inventory. - - - - - Captures the state of a subset of the current users Steam inventory identified by an array of item - instance IDs. - - - - - GrantPromoItems() checks the list of promotional items for which the user may be eligible and grants the - items (one time only). - - - - - ConsumeItem() removes items from the inventory permanently. - - - - - Deprecated method. Playtime accounting is performed on the Steam servers. - - - - - Playtime credit must be consumed and turned into item drops by your game. - - - - - LoadItemDefinitions triggers the automatic load and refresh of item definitions. - - - - - Downloads leaderboard entries for an arbitrary set of users - ELeaderboardDataRequest is - k_ELeaderboardDataRequestUsers - - - - - An optional interface to use instead of deriving - - - - - The actual connection we're managing - - - - - The last received ConnectionInfo - - - - - We're trying to connect! - - - - - Client is connected. They move from connecting to Connections - - - - - The connection has been closed remotely or disconnected locally. Check data.State for details. - - - - - We started connecting to this guy - - - - - Called when the connection is fully connected and can start being communicated with - - - - - We got disconnected - - - - - Received a message - - - - - Must call Accept or Close on the connection within a second or so - - - - - Called when the connection is fully connected and can start being communicated with - - - - - Called when the connection leaves - - - - - Received a message from a connection - - - - - Used as a base to create your networking server. This creates a socket - and listens/communicates with multiple queries. - - You can override all the virtual functions to turn it into what you - want it to do. - - - - - Default behaviour is to accept every connection - - - - - Client is connected. They move from connecting to Connections - - - - - The connection has been closed remotely or disconnected locally. Check data.State for details. - - - - - Which app we're querying. Defaults to the current app. - - - - - When a new server is added, this function will get called - - - - - Called for every responsive server - - - - - A list of servers that responded. If you're only interested in servers that responded since you - last updated, then simply clear this list. - - - - - A list of servers that were in the master list but didn't respond. - - - - - Query the server list. Task result will be true when finished - - - - - - Exposes a wide range of information and actions for applications and Downloadable Content (DLC). - - - - - posted after the user gains ownership of DLC and that DLC is installed - - - - - posted after the user gains executes a Steam URL with command line or query parameters - such as steam://run/appid//-commandline/?param1=value1(and)param2=value2(and)param3=value3 etc - while the game is already running. The new params can be queried - with GetLaunchQueryParam and GetLaunchCommandLine - - - - - Checks if the active user is subscribed to the current App ID - - - - - Check if user borrowed this game via Family Sharing, If true, call GetAppOwner() to get the lender - SteamID - - - - - Checks if the license owned by the user provides low violence depots. - Low violence depots are useful for copies sold in countries that have content restrictions - - - - - Checks whether the current App ID license is for Cyber Cafes. - - - - - CChecks if the user has a VAC ban on their account - - - - - Gets the current language that the user has set. - This falls back to the Steam UI language if the user hasn't explicitly picked a language for the title. - - - - - Gets a list of the languages the current app supports. - - - - - Checks if the active user is subscribed to a specified AppId. - Only use this if you need to check ownership of another game related to yours, a demo for example. - - - - - Checks if the user owns a specific DLC and if the DLC is installed - - - - - Returns the time of the purchase of the app - - - - - Checks if the user is subscribed to the current app through a free weekend - This function will return false for users who have a retail or other type of license - Before using, please ask your Valve technical contact how to package and secure your free weekened - - - - - Returns metadata for all available DLC - - - - - Install/Uninstall control for optional DLC - - - - - Install/Uninstall control for optional DLC - - - - - Returns null if we're not on a beta branch, else the name of the branch - - - - - Allows you to force verify game content on next launch. - - If you detect the game is out-of-date(for example, by having the client detect a version mismatch with a - server), - you can call use MarkContentCorrupt to force a verify, show a message to the user, and then quit. - - - - - Gets a list of all installed depots for a given App ID in mount order - - - - - Gets the install folder for a specific AppID. - This works even if the application is not installed, based on where the game would be installed with the - default Steam library location. - - - - - The app may not actually be owned by the current user, they may have it left over from a free weekend, - etc. - - - - - Gets the Steam ID of the original owner of the current app. If it's different from the current user then - it is borrowed.. - - - - - Gets the associated launch parameter if the game is run via - steam://run/appid/?param1=value1;param2=value2;param3=value3 etc. - Parameter names starting with the character '@' are reserved for internal use and will always return an - empty string. - Parameter names starting with an underscore '_' are reserved for steam features -- they can be queried - by the game, - but it is advised that you not param names beginning with an underscore for your own features. - - - - - Gets the download progress for optional DLC. - - - - - Gets the buildid of this app, may change at any time based on backend updates to the game. - Defaults to 0 if you're not running a build downloaded from steam. - - - - - Asynchronously retrieves metadata details about a specific file in the depot manifest. - Currently provides: - - - - - Get command line if game was launched via Steam URL, e.g. steam://run/appid//command line/. - This method of passing a connect string (used when joining via rich presence, accepting an - invite, etc) is preferable to passing the connect string on the operating system command - line, which is a security risk. In order for rich presence joins to go through this - path and not be placed on the OS command line, you must set a value in your app's - configuration on Steam. Ask Valve for help with this. - - - - - Initialize the steam client. - If asyncCallbacks is false you need to call RunCallbacks manually every frame. - - - - - Checks if the current user's Steam client is connected to the Steam servers. - If it's not then no real-time services provided by the Steamworks API will be enabled. The Steam - client will automatically be trying to recreate the connection as often as possible. When the - connection is restored a SteamServersConnected_t callback will be posted. - You usually don't need to check for this yourself. All of the API calls that rely on this will - check internally. Forcefully disabling stuff when the player loses access is usually not a - very good experience for the player and you could be preventing them from accessing APIs that do not - need a live connection to Steam. - - - - - Gets the Steam ID of the account currently logged into the Steam client. This is - commonly called the 'current user', or 'local user'. - A Steam ID is a unique identifier for a Steam accounts, Steam groups, Lobbies and Chat - rooms, and used to differentiate users in all parts of the Steamworks API. - - - - - returns the local players name - guaranteed to not be NULL. - this is the same name as on the users community profile page - - - - - gets the status of the current user - - - - - returns the appID of the current process - - - - - Checks if your executable was launched through Steam and relaunches it through Steam if it wasn't - this returns true then it starts the Steam client if required and launches your game again through it, - and you should quit your process as soon as possible. This effectively runs steam://run/AppId so it - may not relaunch the exact executable that called it, as it will always relaunch from the version - installed in your Steam library folder/ - Note that during development, when not launching via Steam, this might always return true. - - - - - Called in interfaces that rely on this being initialized - - - - - Undocumented Parental Settings - - - - - Called when chat message has been received from a friend. You'll need to turn on - ListenForFriendsMessages to recieve this. (friend, msgtype, message) - - - - - called when a friends' status changes - - - - - Called when the user tries to join a game from their friends list - rich presence will have been set with the "connect" key which is set here - - - - - Posted when game overlay activates or deactivates - the game can use this to be pause or resume single player games - - - - - Called when the user tries to join a different game server from their friends list - game client should attempt to connect to specified server when this is received - - - - - Called when the user tries to join a lobby from their friends list - game client should attempt to connect to specified lobby when this is received - - - - - Callback indicating updated data about friends rich presence information - - - - - The dialog to open. Valid options are: - "friends", - "community", - "players", - "settings", - "officialgamegroup", - "stats", - "achievements". - - - - - "steamid" - Opens the overlay web browser to the specified user or groups profile. - "chat" - Opens a chat window to the specified user, or joins the group chat. - "jointrade" - Opens a window to a Steam Trading session that was started with the - ISteamEconomy/StartTrade Web API. - "stats" - Opens the overlay web browser to the specified user's stats. - "achievements" - Opens the overlay web browser to the specified user's achievements. - "friendadd" - Opens the overlay in minimal mode prompting the user to add the target user as a friend. - "friendremove" - Opens the overlay in minimal mode prompting the user to remove the target friend. - "friendrequestaccept" - Opens the overlay in minimal mode prompting the user to accept an incoming - friend invite. - "friendrequestignore" - Opens the overlay in minimal mode prompting the user to ignore an incoming - friend invite. - - - - - Activates the Steam Overlay to the Steam store page for the provided app. - - - - - Activates Steam Overlay web browser directly to the specified URL. - - - - - Activates the Steam Overlay to open the invite dialog. Invitations sent from this dialog will be for the - provided lobby. - - - - - Mark a target user as 'played with'. - NOTE: The current user must be in game with the other player for the association to work. - - - - - Requests the persona name and optionally the avatar of a specified user. - NOTE: It's a lot slower to download avatars and churns the local cache, so if you don't need avatars, - don't request them. - returns true if we're fetching the data, false if we already have it - - - - - Find a rich presence value by key for current user. Will be null if not found. - - - - - Sets a rich presence value by key for current user. - - - - - Clears all of the current user's rich presence data. - - - - - Listens for Steam friends chat messages. - You can then show these chats inline in the game. For example with a Blizzard style chat message system - or the chat system in Dota 2. - After enabling this you will receive callbacks when ever the user receives a chat message. - - - - - You shouldn't really need to call this because it get called by RunCallbacks on SteamClient - but Valve think it might be a nice idea if you call it right before you get input info - - just to make sure the info you're getting is 100% up to date. - - - - - Return a list of connected controllers. - - - - - Return an absolute path to the PNG image glyph for the provided digital action name. The current - action set in use for the controller will be used for the lookup. You should cache the result and - maintain your own list of loaded PNG assets. - - - - - - - - Undocumented Parental Settings - - - - - Call this if you're going to want to access definition information. You should be able to get - away with calling this once at the start if your game, assuming your items don't change all the time. - This will trigger OnDefinitionsUpdated at which point Definitions should be set. - - - - - Will call LoadItemDefinitions and wait until Definitions is not null - - - - - Try to find the definition that matches this definition ID. - Uses a dictionary so should be about as fast as possible. - - - - - We will try to keep this list of your items automatically up to date. - - - - - Update the list of Items[] - - - - - Get all items and return the InventoryResult - - - - - This is used to grant a specific item to the user. This should - only be used for development prototyping, from a trusted server, - or if you don't care about hacked clients granting arbitrary items. - This call can be disabled by a setting on Steamworks. - - - - - Crafting! Uses the passed items to buy the target item. - You need to have set up the appropriate exchange rules in your item - definitions. This assumes all the items passed in aren't stacked. - - - - - Crafting! Uses the passed items to buy the target item. - You need to have set up the appropriate exchange rules in your item - definitions. This assumes all the items passed in aren't stacked. - - - - - Deserializes a result set and verifies the signature bytes. - This call has a potential soft-failure mode where the Result is expired, it will - still succeed in this mode.The "expired" - result could indicate that the data may be out of date - not just due to timed - expiration( one hour ), but also because one of the items in the result set may - have been traded or consumed since the result set was generated.You could compare - the timestamp from GetResultTimestamp to ISteamUtils::GetServerRealTime to determine - how old the data is. You could simply ignore the "expired" result code and - continue as normal, or you could request the player with expired data to send - an updated result set. - You should call CheckResultSteamID on the result handle when it completes to verify - that a remote player is not pretending to have a different user's inventory. - - - - - Grant all promotional items the user is eligible for - - - - - Trigger an item drop for this user. This is for timed drops. - - - - - Trigger a promo item drop. You can call this at startup, it won't - give users multiple promo drops. - - - - - Start buying a cart load of items. This will return a positive result is the purchase has - begun. You should listen out for SteamUser.OnMicroTxnAuthorizationResponse for a success. - - - - - Functions for clients to access matchmaking services, favorites, and to operate on game lobbies - - - - - Maximum number of characters a lobby metadata key can be - - - - - Someone invited you to a lobby - - - - - You joined a lobby - - - - - You created a lobby - - - - - A game server has been associated with the lobby - - - - - The lobby metadata has changed - - - - - The lobby member metadata has changed - - - - - The lobby member joined - - - - - The lobby member left the room - - - - - The lobby member left the room - - - - - The lobby member was kicked. The 3rd param is the user that kicked them. - - - - - The lobby member was banned. The 3rd param is the user that banned them. - - - - - A chat message was recieved from a member of a lobby - - - - - Creates a new invisible lobby. Call lobby.SetPublic to take it online. - - - - - Attempts to directly join the specified lobby - - - - - Get a list of servers that are on your favorites list - - - - - Get a list of servers that you have added to your play history - - - - - Functions for clients to access matchmaking services, favorites, and to operate on game lobbies - - - - - Functions to control music playback in the steam client. - This gives games the opportunity to do things like pause the music or lower the volume, - when an important cut scene is shown, and start playing afterwards. - Nothing uses Steam Music though so this can probably get fucked - - - - - Playback status changed - - - - - Volume changed, parameter is new volume - - - - - Checks if Steam Music is enabled - - - - - true if a song is currently playing, paused, or queued up to play; otherwise false. - - - - - Gets the current status of the Steam Music player - - - - - Have the Steam Music player play the previous song. - - - - - Have the Steam Music player skip to the next song - - - - - Gets/Sets the current volume of the Steam Music player - - - - - This SteamId wants to send you a message. You should respond by calling AcceptP2PSessionWithUser - if you want to recieve their messages - - - - - Called when packets can't get through to the specified user. - All queued packets unsent at this point will be dropped, further attempts - to send will retry making the connection (but will be dropped if we fail again). - - - - - This should be called in response to a OnP2PSessionRequest - - - - - Allow or disallow P2P connects to fall back on Steam server relay if direct - connection or NAT traversal can't be established. Applies to connections - created after setting or old connections that need to reconnect. - - - - - This should be called when you're done communicating with a user, as this will - free up all of the resources allocated for the connection under-the-hood. - If the remote user tries to send data to you again, a new OnP2PSessionRequest - callback will be posted - - - - - Checks if a P2P packet is available to read, and gets the size of the message if there is one. - - - - - Reads in a packet that has been sent from another user via SendP2PPacket.. - - - - - Reads in a packet that has been sent from another user via SendP2PPacket.. - - - - - Reads in a packet that has been sent from another user via SendP2PPacket.. - - - - - Sends a P2P packet to the specified user. - This is a session-less API which automatically establishes NAT-traversing or Steam relay server - connections. - NOTE: The first packet send may be delayed as the NAT-traversal code runs. - - - - - Sends a P2P packet to the specified user. - This is a session-less API which automatically establishes NAT-traversing or Steam relay server - connections. - NOTE: The first packet send may be delayed as the NAT-traversal code runs. - - - - - Creates a "server" socket that listens for clients to connect to by calling - Connect, over ordinary UDP (IPv4 or IPv6) - - To use this derive a class from SocketManager and override as much as you want. - - - - - - Creates a "server" socket that listens for clients to connect to by calling - Connect, over ordinary UDP (IPv4 or IPv6). - - To use this you should pass a class that inherits ISocketManager. You can use - SocketManager to get connections and send messages, but the ISocketManager class - will received all the appropriate callbacks. - - - - - - Connect to a socket created via - CreateListenSocketIP - - - - - Connect to a socket created via - CreateListenSocketIP - - - - - Creates a server that will be relayed via Valve's network (hiding the IP and improving ping) - - - - - Connect to a relay server - - - - - Undocumented Parental Settings - - - - - A function to receive debug network information on. This will do nothing - unless you set DebugLevel to something other than None. - - You should set this to an appropriate level instead of setting it to the highest - and then filtering it by hand because a lot of energy is used by creating the strings - and your frame rate will tank and you won't know why. - - - - - The latest available status gathered from the SteamRelayNetworkStatus callback - - - - - If you know that you are going to be using the relay network (for example, - because you anticipate making P2P connections), call this to initialize the - relay network. If you do not call this, the initialization will - be delayed until the first time you use a feature that requires access - to the relay network, which will delay that first access. - - You can also call this to force a retry if the previous attempt has failed. - Performing any action that requires access to the relay network will also - trigger a retry, and so calling this function is never strictly necessary, - but it can be useful to call it a program launch time, if access to the - relay network is anticipated. - - Use GetRelayNetworkStatus or listen for SteamRelayNetworkStatus_t - callbacks to know when initialization has completed. - Typically initialization completes in a few seconds. - - Note: dedicated servers hosted in known data centers do *not* need - to call this, since they do not make routing decisions. However, if - the dedicated server will be using P2P functionality, it will act as - a "client" and this should be called. - - - - - Return location info for the current host. - - It takes a few seconds to initialize access to the relay network. If - you call this very soon after startup the data may not be available yet. - - This always return the most up-to-date information we have available - right now, even if we are in the middle of re-calculating ping times. - - - - - Same as PingLocation.EstimatePingTo, but assumes that one location is the local host. - This is a bit faster, especially if you need to calculate a bunch of - these in a loop to find the fastest one. - - - - - If you need ping information straight away, wait on this. It will return - immediately if you already have up to date ping data - - - - - [0 - 100] - Randomly discard N pct of packets - - - - - [0 - 100] - Randomly discard N pct of packets - - - - - Delay all packets by N ms - - - - - Delay all packets by N ms - - - - - Timeout value (in ms) to use when first connecting - - - - - Timeout value (in ms) to use after connection is established - - - - - Upper limit of buffered pending bytes to be sent. - If this is reached SendMessage will return LimitExceeded. - Default is 524288 bytes (512k) - - - - - Get Debug Information via OnDebugOutput event - - Except when debugging, you should only use NetDebugOutput.Msg - or NetDebugOutput.Warning. For best performance, do NOT - request a high detail level and then filter out messages in the callback. - - This incurs all of the expense of formatting the messages, which are then discarded. - Setting a high priority value (low numeric value) here allows the library to avoid - doing this work. - - - - - So we can remember and provide a Get for DebugLEvel - - - - - We need to keep the delegate around until it's not used anymore - - - - - This can be called from other threads - so we're going to queue these up and process them in a safe - place. - - - - - Called regularly from the Dispatch loop so we can provide a timely - stream of messages. - - - - - Undocumented Parental Settings - - - - - Parental Settings Changed - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This API can be used to selectively advertise your multiplayer game session in a Steam chat room group. - Tell Steam the number of player spots that are available for your party, and a join-game string, and it - will show a beacon in the selected group and allow that many users to “follow” the beacon to your party. - Adjust the number of open slots if other players join through alternate matchmaking methods. - - - - - The list of possible Party beacon locations has changed - - - - - The list of active beacons may have changed - - - - - Functions that provide information about Steam Remote Play sessions, streaming your game content to - another computer or to a Steam Link app or hardware. - - - - - Called when a session is connected - - - - - Called when a session becomes disconnected - - - - - Get the number of currently connected Steam Remote Play sessions - - - - - Get the currently connected Steam Remote Play session ID at the specified index. - IsValid will return false if it's out of bounds - - - - - Invite a friend to Remote Play Together - This returns false if the invite can't be sent - - - - - Undocumented Parental Settings - - - - - Creates a new file, writes the bytes to the file, and then closes the file. - If the target file already exists, it is overwritten - - - - - Opens a binary file, reads the contents of the file into a byte array, and then closes the file. - - - - - Checks whether the specified file exists. - - - - - Checks if a specific file is persisted in the steam cloud. - - - - - Gets the specified file's last modified date/time. - - - - - Gets the specified files size in bytes. 0 if not exists. - - - - - Deletes the file from remote storage, but leaves it on the local disk and remains accessible from the - API. - - - - - Deletes a file from the local disk, and propagates that delete to the cloud. - - - - - Number of bytes total - - - - - Number of bytes used - - - - - Number of bytes remaining until your quota is used - - - - - returns true if IsCloudEnabledForAccount AND IsCloudEnabledForApp - - - - - Checks if the account wide Steam Cloud setting is enabled for this user - or if they disabled it in the Settings->Cloud dialog. - - - - - Checks if the per game Steam Cloud setting is enabled for this user - or if they disabled it in the Game Properties->Update dialog. - - This must only ever be set as the direct result of the user explicitly - requesting that it's enabled or not. This is typically accomplished with - a checkbox within your in-game options - - - - - Gets the total number of local files synchronized by Steam Cloud. - - - - - Get a list of filenames synchronized by Steam Cloud - - - - - Undocumented Parental Settings - - - - - A screenshot has been requested by the user from the Steam screenshot hotkey. - This will only be called if Hooked is true, in which case Steam - will not take the screenshot itself. - - - - - A screenshot successfully written or otherwise added to the library and can now be tagged. - - - - - A screenshot attempt failed - - - - - Writes a screenshot to the user's screenshot library given the raw image data, which must be in RGB - format. - The return value is a handle that is valid for the duration of the game process and can be used to apply - tags. - - - - - Adds a screenshot to the user's screenshot library from disk. If a thumbnail is provided, it must be 200 - pixels wide and the same aspect ratio - as the screenshot, otherwise a thumbnail will be generated if the user uploads the screenshot. The - screenshots must be in either JPEG or TGA format. - The return value is a handle that is valid for the duration of the game process and can be used to apply - tags. - JPEG, TGA, and PNG formats are supported. - - - - - Causes the Steam overlay to take a screenshot. - If screenshots are being hooked by the game then a - ScreenshotRequested callback is sent back to the game instead. - - - - - Toggles whether the overlay handles screenshots when the user presses the screenshot hotkey, or if the - game handles them. - Hooking is disabled by default, and only ever enabled if you do so with this function. - If the hooking is enabled, then the ScreenshotRequested_t callback will be sent if the user presses the - hotkey or - when TriggerScreenshot is called, and then the game is expected to call WriteScreenshot or - AddScreenshotToLibrary in response. - - - - - Provides the core of the Steam Game Servers API - - - - - User has been authed or rejected - - - - - Called when a connections to the Steam back-end has been established. - This means the server now is logged on and has a working connection to the Steam master server. - - - - - This will occur periodically if the Steam client is not connected, and has failed when retrying to - establish a connection (result, stilltrying) - - - - - Disconnected from Steam - - - - - Initialize the steam server. - If asyncCallbacks is false you need to call RunCallbacks manually every frame. - - - - - Run the callbacks. This is also called in Async callbacks. - - - - - Sets whether this should be marked as a dedicated server. - If not, it is assumed to be a listen server. - - - - - Gets or sets the current MaxPlayers. - This doesn't enforce any kind of limit, it just updates the master server. - - - - - Gets or sets the current BotCount. - This doesn't enforce any kind of limit, it just updates the master server. - - - - - Gets or sets the current Map Name. - - - - - Gets or sets the current ModDir - - - - - Gets the current product - - - - - Gets or sets the current Product - - - - - Gets or sets the current ServerName - - - - - Set whether the server should report itself as passworded - - - - - Gets or sets the current GameTags. This is a comma seperated list of tags for this server. - When querying the server list you can filter by these tags. - - - - - Log onto Steam anonymously. - - - - - Log onto Steam anonymously. - - - - - Returns true if the server is connected and registered with the Steam master server - You should have called LogOnAnonymous etc on startup. - - - - - To the best of its ability this tries to get the server's - current public ip address. Be aware that this is likely to return - null for the first few seconds after initialization. - - - - - Enable or disable heartbeats, which are sent regularly to the master server. - Enabled by default. - - - - - Set heartbeat interval, if automatic heartbeats are enabled. - You can leave this at the default. - - - - - Force send a heartbeat to the master server instead of waiting - for the next automatic update (if you've left them enabled) - - - - - Update this connected player's information. You should really call this - any time a player's name or score changes. This keeps the information shown - to server queries up to date. - - - - - Sets a Key Value. These can be anything you like, and are accessible - when querying servers from the server list. - - Information describing gamemodes are common here. - - - - - Remove all key values - - - - - Start authorizing a ticket. This user isn't authorized yet. Wait for a call to OnAuthChange. - - - - - Forget this guy. They're no longer in the game. - - - - - If true, Steam wants to send a packet. You should respond by sending - this packet in an unconnected way to the returned Address and Port. - - Packet to send. The Data passed is pooled - so use it immediately. - True if we want to send a packet - - - - We have received a server query on our game port. Pass it to Steam to handle. - - - - - We have received a server query on our game port. Pass it to Steam to handle. - - - - - Does the user own this app (which could be DLC) - - - - - Downloads stats for the user - If the user has no stats will return fail - these stats will only be auto-updated for clients playing on the server - - - - - Set the named stat for this user. Setting stats should follow the rules - you defined in Steamworks. - - - - - Set the named stat for this user. Setting stats should follow the rules - you defined in Steamworks. - - - - - Get the named stat for this user. If getting the stat failed, will return - defaultValue. You should have called Refresh for this userid - which downloads - the stats from the backend. If you didn't call it this will always return defaultValue. - - - - - Get the named stat for this user. If getting the stat failed, will return - defaultValue. You should have called Refresh for this userid - which downloads - the stats from the backend. If you didn't call it this will always return defaultValue. - - - - - Unlocks the specified achievement for the specified user. Must have called Refresh on a steamid first. - Remember to use Commit after use. - - - - - Resets the unlock status of an achievement for the specified user. Must have called Refresh on a steamid - first. - Remember to use Commit after use. - - - - - Return true if available, exists and unlocked - - - - - Once you've set a stat change on a user you need to commit your changes. - You can do that using this function. The callback will let you know if - your action succeeded, but most of the time you can fire and forget. - - - - - Functions for accessing and manipulating Steam user information. - This is also where the APIs for Steam Voice are exposed. - - - - - Posted after Download call - - - - - Start downloading this item. You'll get notified of completion via OnDownloadItemResult. - - The ID of the file you want to download - If true this should go straight to the top of the download list - true if nothing went wrong and the download is started - - - - Will attempt to download this item asyncronously - allowing you to instantly react to its installation - - The ID of the file you want to download - An optional callback - Allows you to send a message to cancel the download anywhere during the process - How often to call the progress function - true if downloaded and installed correctly - - - - Utility function to fetch a single item. Internally this uses Ugc.FileQuery - - which you can use to query multiple items if you need to. - - - - - Functions for accessing and manipulating Steam user information. - This is also where the APIs for Steam Voice are exposed. - - - - - Called when a connections to the Steam back-end has been established. - This means the Steam client now has a working connection to the Steam servers. - Usually this will have occurred before the game has launched, and should only be seen if the - user has dropped connection due to a networking issue or a Steam server update. - - - - - Called when a connection attempt has failed. - This will occur periodically if the Steam client is not connected, - and has failed when retrying to establish a connection. - - - - - Called if the client has lost connection to the Steam servers. - Real-time services will be disabled until a matching OnSteamServersConnected has been posted. - - - - - Sent by the Steam server to the client telling it to disconnect from the specified game server, - which it may be in the process of or already connected to. - The game client should immediately disconnect upon receiving this message. - This can usually occur if the user doesn't have rights to play on the game server. - - - - - Called whenever the users licenses (owned packages) changes. - - - - - Called when an auth ticket has been validated. - The first parameter is the steamid of this user - The second is the Steam ID that owns the game, this will be different from the first - if the game is being borrowed via Steam Family Sharing - - - - - Used internally for GetAuthSessionTicketAsync - - - - - Called when a user has responded to a microtransaction authorization request. - ( appid, orderid, user authorized ) - - - - - Sent to your game in response to a steam://gamewebcallback/ command from a user clicking a link in the - Steam overlay browser. - You can use this to add support for external site signups where you want to pop back into the browser - after some web page - signup sequence, and optionally get back some detail about that. - - - - - Sent for games with enabled anti indulgence / duration control, for enabled users. - Lets the game know whether persistent rewards or XP should be granted at normal rate, - half rate, or zero rate. - - - - - Starts/Stops voice recording. - Once started, use GetAvailableVoice and GetVoice to get the data, and then call StopVoiceRecording - when the user has released their push-to-talk hotkey or the game session has completed. - - - - - Returns true if we have voice data waiting to be read - - - - - Reads the voice data and returns the number of bytes written. - The compressed data can be transmitted by your application and decoded back into raw audio data using - DecompressVoice on the other side. The compressed data provided is in an arbitrary format and is not - meant to be played directly. - This should be called once per frame, and at worst no more than four times a second to keep the - microphone input delay as low as - possible. Calling this any less may result in gaps in the returned stream. - - - - - Reads the voice data and returns the bytes. You should obviously ideally be using - ReadVoiceData because it won't be creating a new byte array every call. But this - makes it easier to get it working, so let the babies have their bottle. - - - - - Decodes the compressed voice data returned by GetVoice. - The output data is raw single-channel 16-bit PCM audio.The decoder supports any sample rate from 11025 - to 48000. - - - - - Retrieve a authentication ticket to be sent to the entity who wishes to authenticate you. - - - - - Retrieve a authentication ticket to be sent to the entity who wishes to authenticate you. - This waits for a positive response from the backend before returning the ticket. This means - the ticket is definitely ready to go as soon as it returns. Will return null if the callback - times out or returns negatively. - - - - - Checks if the current users looks like they are behind a NAT device. - This is only valid if the user is connected to the Steam servers and may not catch all forms of NAT. - - - - - Gets the Steam level of the user, as shown on their Steam community profile. - - - - - Requests a URL which authenticates an in-game browser for store check-out, and then redirects to the - specified URL. - As long as the in-game browser accepts and handles session cookies, Steam microtransaction checkout - pages will automatically recognize the user instead of presenting a login page. - NOTE: The URL has a very short lifetime to prevent history-snooping attacks, so you should only call - this API when you are about to launch the browser, or else immediately navigate to the result URL using - a hidden browser window. - NOTE: The resulting authorization cookie has an expiration time of one day, so it would be a good idea - to request and visit a new auth URL every 12 hours. - - - - - Checks whether the current user has verified their phone number. - - - - - Checks whether the current user has Steam Guard two factor authentication enabled on their account. - - - - - Checks whether the user's phone number is used to uniquely identify them. - - - - - Checks whether the current user's phone number is awaiting (re)verification. - - - - - Requests an application ticket encrypted with the secret "encrypted app ticket key". - The encryption key can be obtained from the Encrypted App Ticket Key page on the App Admin for your app. - There can only be one call pending, and this call is subject to a 60 second rate limit. - If you get a null result from this it's probably because you're calling it too often. - This can fail if you don't have an encrypted ticket set for your app here - https://partner.steamgames.com/apps/sdkauth/ - - - - - Requests an application ticket encrypted with the secret "encrypted app ticket key". - The encryption key can be obtained from the Encrypted App Ticket Key page on the App Admin for your app. - There can only be one call pending, and this call is subject to a 60 second rate limit. - This can fail if you don't have an encrypted ticket set for your app here - https://partner.steamgames.com/apps/sdkauth/ - - - - - Get anti indulgence / duration control - - - - - called when the achivement icon is loaded - - - - - called when the latests stats and achievements have been received - from the server - - - - - result of a request to store the user stats for a game - - - - - result of a request to store the achievements for a game, or an - "indicate progress" call. If both m_nCurProgress and m_nMaxProgress - are zero, that means the achievement has been fully unlocked - - - - - Callback indicating that a user's stats have been unloaded - - - - - Get the available achievements - - - - - Show the user a pop-up notification with the current progress toward an achievement. - Will return false if RequestCurrentStats has not completed and successfully returned - its callback, if the achievement doesn't exist/has unpublished changes in the app's - Steamworks Admin page, or if the achievement is unlocked. - - - - - Tries to get the number of players currently playing this game. - Or -1 if failed. - - - - - Send the changed stats and achievements data to the server for permanent storage. - If this fails then nothing is sent to the server. It's advisable to keep trying until the call is - successful. - This call can be rate limited. Call frequency should be on the order of minutes, rather than seconds.You - should only be calling this during major state changes such as the end of a round, the map changing, or - the user leaving a server. This call is required to display the achievement unlock notification dialog - though, so if you have called SetAchievement then it's advisable to call this soon after that. - If you have stats or achievements that you have saved locally but haven't uploaded with this function - when your application process ends then this function will automatically be called. - You can find additional debug information written to the %steam_install%\logs\stats_log.txt file. - This function returns true upon success if : - RequestCurrentStats has completed and successfully returned its callback AND - the current game has stats associated with it in the Steamworks Partner backend, and those stats are - published. - - - - - Asynchronously request the user's current stats and achievements from the server. - You must always call this first to get the initial status of stats and achievements. - Only after the resulting callback comes back can you start calling the rest of the stats - and achievement functions for the current user. - - - - - Asynchronously fetches global stats data, which is available for stats marked as - "aggregated" in the App Admin panel of the Steamworks website. - You must have called RequestCurrentStats and it needs to return successfully via - its callback prior to calling this. - - How many days of day-by-day history to retrieve in addition to the overall totals. The - limit is 60. - - OK indicates success, InvalidState means you need to call RequestCurrentStats first, Fail means the - remote call failed - - - - - Gets a leaderboard by name, it will create it if it's not yet created. - Leaderboards created with this function will not automatically show up in the Steam Community. - You must manually set the Community Name field in the App Admin panel of the Steamworks website. - As such it's generally recommended to prefer creating the leaderboards in the App Admin panel on - the Steamworks website and using FindLeaderboard unless you're expected to have a large amount of - dynamically created leaderboards. - - - - - Adds this amount to the named stat. Internally this calls Get() and adds - to that value. Steam doesn't provide a mechanism for atomically increasing - stats like this, this functionality is added here as a convenience. - - - - - Adds this amount to the named stat. Internally this calls Get() and adds - to that value. Steam doesn't provide a mechanism for atomically increasing - stats like this, this functionality is added here as a convenience. - - - - - Set a stat value. This will automatically call StoreStats() after a successful call - unless you pass false as the last argument. - - - - - Set a stat value. This will automatically call StoreStats() after a successful call - unless you pass false as the last argument. - - - - - Get a Int stat value - - - - - Get a float stat value - - - - - Practically wipes the slate clean for this user. If includeAchievements is true, will wipe - any achievements too. - - - - - - Interface which provides access to a range of miscellaneous utility functions - - - - - The country of the user changed - - - - - Fired when running on a laptop and less than 10 minutes of battery is left, fires then every minute - The parameter is the number of minutes left - - - - - Called when Steam wants to shutdown - - - - - Big Picture gamepad text input has been closed. Parameter is true if text was submitted, false if - cancelled etc. - - - - - Returns the number of seconds since the application was active - - - - - Returns the number of seconds since the user last moved the mouse etc - - - - - Steam server time. Number of seconds since January 1, 1970, GMT (i.e unix time) - - - - - returns the 2 digit ISO 3166-1-alpha-2 format country code this client is running in (as looked up via - an IP-to-location database) - e.g "US" or "UK". - - - - - returns true if the image exists, and the buffer was successfully filled out - results are returned in RGBA format - the destination buffer size should be 4 * height * width * sizeof(char) - - - - - returns the image in RGBA format - - - - - Returns true if we're using a battery (ie, a laptop not plugged in) - - - - - Returns battery power [0-1] - - - - - Sets the position where the overlay instance for the currently calling game should show notifications. - This position is per-game and if this function is called from outside of a game context it will do - nothing. - - - - - Returns true if the overlay is running and the user can access it. The overlay process could take a few - seconds to - start and hook the game process, so this function will initially return false while the overlay is - loading. - - - - - Normally this call is unneeded if your game has a constantly running frame loop that calls the - D3D Present API, or OGL SwapBuffers API every frame. - - However, if you have a game that only refreshes the screen on an event driven basis then that can break - the overlay, as it uses your Present/SwapBuffers calls to drive it's internal frame loop and it may also - need to Present() to the screen any time an even needing a notification happens or when the overlay is - brought up over the game by a user. You can use this API to ask the overlay if it currently need a - present - in that case, and then you can check for this periodically (roughly 33hz is desirable) and make sure you - refresh the screen with Present or SwapBuffers to allow the overlay to do it's work. - - - - - Asynchronous call to check if an executable file has been signed using the public key set on the signing - tab - of the partner site, for example to refuse to load modified executable files. - - - - - Activates the Big Picture text input dialog which only supports gamepad input - - - - - Returns previously entered text - - - - - returns the language the steam client is running in, you probably want - Apps.CurrentGameLanguage instead, this is for very special usage cases - - - - - returns true if Steam itself is running in VR mode - - - - - Sets the inset of the overlay notification from the corner specified by SetOverlayNotificationPosition - - - - - returns true if Steam and the Steam Overlay are running in Big Picture mode - Games much be launched through the Steam client to enable the Big Picture overlay. During development, - a game can be added as a non-steam game to the developers library to test this feature - - - - - ask SteamUI to create and render its OpenVR dashboard - - - - - Set whether the HMD content will be streamed via Steam In-Home Streaming - If this is set to true, then the scene in the HMD headset will be streamed, and remote input will not be - allowed. - If this is set to false, then the application window will be streamed instead, and remote input will be - allowed. - The default is true unless "VRHeadsetStreaming" "0" is in the extended appinfo for a game. - (this is useful for games that have asymmetric multiplayer gameplay) - - - - - Returns whether this steam client is a Steam China specific client, vs the global client - - - - - Undocumented Parental Settings - - - - - Return true if currently using Steam's live broadcasting - - - - - If we're broadcasting, will return the number of live viewers - - - - - Reconfigure the controller to use the specified action set (ie 'Menu', 'Walk' or 'Drive') - This is cheap, and can be safely called repeatedly. It's often easier to repeatedly call it in - our state loops, instead of trying to place it in all of your state transitions. - - - - - Returns the current state of the supplied digital game action - - - - - Returns the current state of these supplied analog game action - - - - - Returns true if this is the local user - - - - - Return true if this is a friend - - - - - Returns true if you have this user blocked - - - - - Return true if this user is playing the game we're running - - - - - Returns true if this friend is online - - - - - Sometimes we don't know the user's name. This will wait until we have - downloaded the information on this user. - - - - - Returns true if this friend is marked as away - - - - - Returns true if this friend is marked as busy - - - - - Returns true if this friend is marked as snoozing - - - - - Invite this friend to the game that we are playing - - - - - Sends a message to a Steam friend. Returns true if success - - - - - Tries to get download the latest user stats - - True if successful, False if failure - - - - Gets a user stat. Must call RequestUserStats first. - - The name of the stat you want to get - Will return this value if not available - The value, or defult if not available - - - - Gets a user stat. Must call RequestUserStats first. - - The name of the stat you want to get - Will return this value if not available - The value, or defult if not available - - - - Gets a user achievement state. Must call RequestUserStats first. - - The name of the achievement you want to get - Will return this value if not available - The value, or defult if not available - - - - Gets a the time this achievement was unlocked. - - The name of the achievement you want to get - The time unlocked. If it wasn't unlocked, or you haven't downloaded the stats yet - will return - DateTime.MinValue - - - - - Shortcut to call GetProperty( "name" ) - - - - - Shortcut to call GetProperty( "description" ) - - - - - Shortcut to call GetProperty( "icon_url" ) - - - - - Shortcut to call GetProperty( "icon_url_large" ) - - - - - Shortcut to call GetProperty( "price_category" ) - - - - - Shortcut to call GetProperty( "type" ) - - - - - Returns true if this is an item that generates an item, rather - than something that is actual an item - - - - - Shortcut to call GetProperty( "exchange" ) - - - - - Get a list of exchanges that are available to make this item - - - - - Shortcut to call GetBoolProperty( "marketable" ) - - - - - Shortcut to call GetBoolProperty( "tradable" ) - - - - - Gets the property timestamp - - - - - Gets the property modified - - - - - Get a specific property by name - - - - - Read a raw property from the definition schema - - - - - Read a raw property from the definition schema - - - - - Gets a list of all properties on this item - - - - - Returns the price of this item in the local currency (SteamInventory.Currency) - - - - - If the price has been discounted, LocalPrice will differ from LocalBasePrice - (assumed, this isn't documented) - - - - - Return a list of recepies that contain this item - - - - - Only available if the result set was created with the getproperties - - - - - This item is account-locked and cannot be traded or given away. - This is an item status flag which is permanently attached to specific item instances - - - - - The item has been destroyed, traded away, expired, or otherwise invalidated. - This is an action confirmation flag which is only set one time, as part of a result set. - - - - - The item quantity has been decreased by 1 via ConsumeItem API. - This is an action confirmation flag which is only set one time, as part of a result set. - - - - - Consumes items from a user's inventory. If the quantity of the given item goes to zero, it is - permanently removed. - Once an item is removed it cannot be recovered.This is not for the faint of heart - if your game - implements item removal at all, - a high-friction UI confirmation process is highly recommended.ConsumeItem can be restricted to certain - item definitions or fully - blocked via the Steamworks website to minimize support/abuse issues such as the classic "my brother - borrowed my laptop and deleted all of my rare items". - - - - - Split stack into two items - - - - - Add x units of the target item to this item - - - - - Will try to return the date that this item was aquired. You need to have for the items - with their properties for this to work. - - - - - Tries to get the origin property. Need properties for this to work. - Will return a string like "market" - - - - - Small utility class to describe an item with a quantity - - - - - A structured description of an item exchange - - - - - The definition ID of the ingredient. - - - - - If we don't know about this item definition this might be null. - In which case, DefinitionId should still hold the correct id. - - - - - The amount of this item needed. Generally this will be 1. - - - - - The item that this will create. - - - - - The items, with quantity required to create this item. - - - - - Checks whether an inventory result handle belongs to the specified Steam ID. - This is important when using Deserialize, to verify that a remote player is not pretending to have a - different user's inventory - - - - - Serialized result sets contain a short signature which can't be forged or replayed across different game - sessions. - A result set can be serialized on the local client, transmitted to other players via your game - networking, and - deserialized by the remote players.This is a secure way of preventing hackers from lying about posessing - rare/high-value items. Serializes a result set with signature bytes to an output buffer.The size of a - serialized - result depends on the number items which are being serialized.When securely transmitting items to other - players, - it is recommended to use GetItemsByID first to create a minimal result set. - Results have a built-in timestamp which will be considered "expired" after an hour has elapsed.See - DeserializeResult - for expiration handling. - - - - - Creator of the beacon - - - - - Creator of the beacon - - - - - Will attempt to join the party. If successful will return a connection string. - If failed, will return null - - - - - When a user follows your beacon, Steam will reserve one of the open party slots for them, and send your - game a ReservationNotification callback. - When that user joins your party, call OnReservationCompleted to notify Steam that the user has joined - successfully - - - - - To cancel a reservation (due to timeout or user input), call this. - Steam will open a new reservation slot. - Note: The user may already be in-flight to your game, so it's possible they will still connect and try - to join your party. - - - - - Turn off the beacon - - - - - Used to set up the server. - The variables in here are all required to be set, and can't be changed once the server is created. - - - - - The version string is usually in the form x.x.x.x, and is used by the master server to detect when the - server is out of date. - If you go into the dedicated server tab on steamworks you'll be able to server the latest version. If - this version number is - less than that latest version then your server won't show. - - - - - This should be the same directory game where gets installed into. Just the folder name, not the whole - path. I.e. "Rust", "Garrysmod". - - - - - The game description. Setting this to the full name of your game is recommended. - - - - - Is a dedicated server - - - - - Set the Steam quert port - - - - - If you pass MASTERSERVERUPDATERPORT_USEGAMESOCKETSHARE into usQueryPort, then it causes the game server - API to use - "GameSocketShare" mode, which means that the game is responsible for sending and receiving UDP packets - for the master - server updater. - - More info about this here: https://partner.steamgames.com/doc/api/ISteamGameServer#HandleIncomingPacket - - - - - Create a Normal Workshop item that can be subscribed to - - - - - Workshop item that is meant to be voted on for the purpose of selling in-game - - - - - https://partner.steamgames.com/doc/features/workshop/implementation#Legal - - - - - The actual ID of this file - - - - - The given title of this item - - - - - The description of this item, in your local language if available - - - - - A list of tags for this item, all lowercase - - - - - App Id of the app that created this item - - - - - App Id of the app that will consume this item. - - - - - User who created this content - - - - - The bayesian average for up votes / total votes, between [0,1] - - - - - Time when the published item was created - - - - - Time when the published item was last updated - - - - - True if this is publically visible - - - - - True if this item is only visible by friends of the creator - - - - - True if this is only visible to the creator - - - - - True if this item has been banned - - - - - Whether the developer of this app has specifically flagged this item as accepted in the Workshop - - - - - The number of upvotes of this item - - - - - The number of downvotes of this item - - - - - Start downloading this item. - If this returns false the item isn't getting downloaded. - - - - - If we're downloading, how big the total download is - - - - - If we're downloading, how much we've downloaded - - - - - If we're installed, how big is the install - - - - - If we're downloading our current progress as a delta betwen 0-1 - - - - - A case insensitive check for tag - - - - - Allows the user to subscribe to this item - - - - - Allows the user to subscribe to download this item asyncronously - If CancellationToken is default then there is 60 seconds timeout - Progress will be set to 0-1 - - - - - Allows the user to unsubscribe from this item - - - - - Adds item to user favorite list - - - - - Removes item from user favorite list - - - - - Allows the user to rate a workshop item up or down. - - - - - Gets the current users vote on the item - - - - - Return a URL to view this item online - - - - - The URl to view this item's changelog - - - - - The URL to view the comments on this item - - - - - The URL to discuss this item - - - - - The URL to view this items stats online - - - - - The URL to the preview image for this item - - - - - Edit this item - - - - - Found items must have at least one of the defined tags - - - - - Found items must have all defined tags - - - - - Returns the current Unix Epoch - - - - - Convert an epoch to a datetime - - - - - Convert a DateTime to a unix time - - - - - Returns a buffer. This will get returned and reused later on. - - - - - Prevent unity from stripping shit we depend on - https://docs.unity3d.com/Manual/ManagedCodeStripping.html - - - - diff --git a/Assets/Packages/Facepunch/Facepunch.Steamworks.Posix.xml.meta b/Assets/Packages/Facepunch/Facepunch.Steamworks.Posix.xml.meta deleted file mode 100644 index 5e5f20c..0000000 --- a/Assets/Packages/Facepunch/Facepunch.Steamworks.Posix.xml.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: f13b7820b3a9b6145a8ea48a92291748 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Packages/Facepunch/Facepunch.Steamworks.Win32.dll b/Assets/Packages/Facepunch/Facepunch.Steamworks.Win32.dll deleted file mode 100644 index f7f75ea12d5ce6c9ccd0fb38521873de9f986e93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 546816 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 z]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 z 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 - - - Facepunch.Steamworks.Win32 - - - -

- An awaitable version of a SteamAPICall_t - - - - - This gets called if IsComplete returned false on the first call. - The Action "continues" the async call. We pass it to the Dispatch - to be called when the callback returns. - - - - - Gets the result. This is called internally by the async shit. - - - - - Return true if complete or failed - - - - - This is what makes this struct awaitable - - - - - Gives us a generic way to get the CallbackId of structs - - - - - Cancels a ticket. - You should cancel your ticket when you close the game or leave a server. - - - - - Responsible for all callback/callresult handling - - This manually pumps Steam's message queue and dispatches those - events to any waiting callbacks/callresults. - - - - - If set then we'll call this function every time a callback is generated. - - This is SLOW!! - it's for debugging - don't keep it on all the time. If you want to access a specific - callback then please create an issue on github and I'll add it! - - Params are : [Callback Type] [Callback Contents] [server] - - - - - - Called if an exception happens during a callback/callresult. - This is needed because the exception isn't always accessible when running - async.. and can fail silently. With this hooked you won't be stuck wondering - what happened. - - - - - This gets called from Client/Server Init - It's important to switch to the manual dispatcher - - - - - Make sure we don't call Frame in a callback - because that'll cause some issues for everyone. - - - - - Calls RunFrame and processes events from this Steam Pipe - - - - - To be safe we don't call the continuation functions while iterating - the Callback list. This is maybe overly safe because the only way this - could be an issue is if the callback list is modified in the continuation - which would only happen if starting or shutting down in the callback. - - - - - A callback is a general global message - - - - - Given a callback, try to turn it into a string - - - - - A result is a reply to a specific command - - - - - Pumps the queue in an async loop so we don't - have to think about it. This has the advantage that - you can call .Wait() on async shit and it still works. - - - - - Pumps the queue in an async loop so we don't - have to think about it. This has the advantage that - you can call .Wait() on async shit and it still works. - - - - - Watch for a steam api call - - - - - Install a global callback. The passed function will get called if it's all good. - - - - - The score is just a simple numerical value - - - - - The score represents a time, in seconds - - - - - The score represents a time, in milliseconds - - - - - The top-score is the lowest number - - - - - The top-score is the highest number - - - - - Send the message unreliably. Can be lost. Messages *can* be larger than a - single MTU (UDP packet), but there is no retransmission, so if any piece - of the message is lost, the entire message will be dropped. - - The sending API does have some knowledge of the underlying connection, so - if there is no NAT-traversal accomplished or there is a recognized adjustment - happening on the connection, the packet will be batched until the connection - is open again. - - - - - Disable Nagle's algorithm. - By default, Nagle's algorithm is applied to all outbound messages. This means - that the message will NOT be sent immediately, in case further messages are - sent soon after you send this, which can be grouped together. Any time there - is enough buffered data to fill a packet, the packets will be pushed out immediately, - but partially-full packets not be sent until the Nagle timer expires. - - - - - If the message cannot be sent very soon (because the connection is still doing some initial - handshaking, route negotiations, etc), then just drop it. This is only applicable for unreliable - messages. Using this flag on reliable messages is invalid. - - - - Reliable message send. Can send up to 0.5mb in a single message. - Does fragmentation/re-assembly of messages under the hood, as well as a sliding window for - efficient sends of large chunks of data. - - - - Return a NetIdentity that represents LocalHost - - - - - Return true if this identity is localhost - - - - - Convert to a SteamId - - - - - - Set the specified Address - - - - - Automatically convert to a SteamId - - - - - - Returns NULL if we're not a SteamId - - - - - Returns NULL if we're not a NetAddress - - - - - We override tostring to provide a sensible representation - - - - - The Port. This is redundant documentation. - - - - - Any IP, specific port - - - - - Localhost IP, specific port - - - - - Specific IP, specific port - - - - - Specific IP, specific port - - - - - Set everything to zero - - - - - Return true if the IP is ::0. (Doesn't check port.) - - - - - Return true if IP is mapped IPv4 - - - - - Return true if this identity is localhost. (Either IPv6 ::1, or IPv4 127.0.0.1) - - - - - Get the Address section - - - - - Used as a base to create your client connection. This creates a socket - to a single connection. - - You can override all the virtual functions to turn it into what you - want it to do. - - - - - Accept an incoming connection that has been received on a listen socket. - - - - - Disconnects from the remote host and invalidates the connection handle. Any unread data on the - connection is discarded.. - reasonCode is defined and used by you. - - - - - Get/Set connection user data - - - - - A name for the connection, used mostly for debugging - - - - - This is the best version to use. - - - - - Ideally should be using an IntPtr version unless you're being really careful with the byte[] array and - you're not creating a new one every frame (like using .ToArray()) - - - - - Ideally should be using an IntPtr version unless you're being really careful with the byte[] array and - you're not creating a new one every frame (like using .ToArray()) - - - - - This creates a ton of garbage - so don't do anything with this beyond testing! - - - - - Flush any messages waiting on the Nagle timer and send them at the next transmission - opportunity (often that means right now). - - - - - Returns detailed connection stats in text format. Useful - for dumping to a log, etc. - - Plain text connection info - - - - Describe the state of a connection - - - - - High level state of the connection - - - - - Remote address. Might be all 0's if we don't know it, or if this is N/A. - - - - - Who is on the other end? Depending on the connection type and phase of the connection, we might not know - - - - - Basic cause of the connection termination or problem. - - - - - - Object that describes a "location" on the Internet with sufficient - detail that we can reasonably estimate an upper bound on the ping between - the two hosts, even if a direct route between the hosts is not possible, - and the connection must be routed through the Steam Datagram Relay network. - This does not contain any information that identifies the host. Indeed, - if two hosts are in the same building or otherwise have nearly identical - networking characteristics, then it's valid to use the same location - object for both of them. - - NOTE: This object should only be used in the same process! Do not serialize it, - send it over the wire, or persist it in a file or database! If you need - to do that, convert it to a string representation using the methods in - ISteamNetworkingUtils(). - - - - - Estimate the round-trip latency between two arbitrary locations, in - milliseconds. This is a conservative estimate, based on routing through - the relay network. For most basic relayed connections, this ping time - will be pretty accurate, since it will be based on the route likely to - be actually used. - - If a direct IP route is used (perhaps via NAT traversal), then the route - will be different, and the ping time might be better. Or it might actually - be a bit worse! Standard IP routing is frequently suboptimal! - - But even in this case, the estimate obtained using this method is a - reasonable upper bound on the ping time. (Also it has the advantage - of returning immediately and not sending any packets.) - - In a few cases we might not able to estimate the route. In this case - a negative value is returned. k_nSteamNetworkingPing_Failed means - the reason was because of some networking difficulty. (Failure to - ping, etc) k_nSteamNetworkingPing_Unknown is returned if we cannot - currently answer the question for some other reason. - - Do you need to be able to do this from a backend/matchmaking server? - You are looking for the "ticketgen" library. - - - - Destroy a listen socket. All the connections that were accepting on the listen - socket are closed ungracefully. - - - - - True if unlocked - - - - - Should hold the unlock time if State is true - - - - - Gets the icon of the achievement. This can return a null image even though the image exists if the image - hasn't been downloaded by Steam yet. You can use GetIconAsync if you want to wait for the image to be - downloaded. - - - - - Gets the icon of the achievement, waits for it to load if we have to - - - - - Returns the fraction (0-1) of users who have unlocked the specified achievement, or -1 if no data - available. - - - - - Make this achievement earned - - - - - Reset this achievement to not achieved - - - - - Sent for games with enabled anti indulgence / duration control, for enabled users. - Lets the game know whether persistent rewards or XP should be granted at normal rate, half rate, or zero - rate. - - - - - appid generating playtime - - - - - is duration control applicable to user + game combination - - - - - playtime since most recent 5 hour gap in playtime, only counting up to regulatory limit of playtime, in - seconds - - - - - playtime on current calendar day - - - - - recommended progress - - - - - the name of a leaderboard - - - - - Submit your score and replace your old score even if it was better - - - - - Submit your new score, but won't replace your high score if it's lower - - - - - Attaches a piece of user generated content the user's entry on a leaderboard - - - - - Used to query for a sequential range of leaderboard entries by leaderboard Sort. - - - - - Used to retrieve leaderboard entries relative a user's entry. If there are not enough entries in the - leaderboard - before or after the user's entry, Steam will adjust the range to try to return the number of entries - requested. - For example, if the user is #1 on the leaderboard and start is set to -2, end is set to 2, Steam will - return the first - 5 entries in the leaderboard. If The current user has no entry, this will return null. - - - - - Used to retrieve all leaderboard entries for friends of the current user - - - - - Try to join this room. Will return RoomEnter.Success on success, - and anything else is a failure - - - - - Leave a lobby; this will take effect immediately on the client side - other users in the lobby will be notified by a LobbyChatUpdate_t callback - - - - - Invite another user to the lobby - will return true if the invite is successfully sent, whether or not the target responds - returns false if the local user is not connected to the Steam servers - - - - - returns the number of users in the specified lobby - - - - - Returns current members. Need to be in the lobby to see the users. - - - - - Get data associated with this lobby - - - - - Get data associated with this lobby - - - - - Removes a metadata key from the lobby - - - - - Get all data for this lobby - - - - - Gets per-user metadata for someone in this lobby - - - - - Sets per-user metadata (for the local user implicitly) - - - - - Sends a string to the chat room - - - - - Sends bytes the the chat room - this isn't exposed because there's no way to read raw bytes atm, - and I figure people can send json if they want something more advanced - - - - - Refreshes metadata for a lobby you're not necessarily in right now - you never do this for lobbies you're a member of, only if your - this will send down all the metadata associated with a lobby - this is an asynchronous call - returns false if the local user is not connected to the Steam servers - results will be returned by a LobbyDataUpdate_t callback - if the specified lobby doesn't exist, LobbyDataUpdate_t::m_bSuccess will be set to false - - - - - Max members able to join this lobby. Cannot be over 250. - Can only be set by the owner - - - - - [SteamID variant] - Allows the owner to set the game server associated with the lobby. Triggers the - Steammatchmaking.OnLobbyGameCreated event. - - - - - [IP/Port variant] - Allows the owner to set the game server associated with the lobby. Triggers the - Steammatchmaking.OnLobbyGameCreated event. - - - - - Gets the details of the lobby's game server, if set. Returns true if the lobby is - valid and has a server set, otherwise returns false. - - - - - You must be the lobby owner to set the owner - - - - - Check if the specified SteamId owns the lobby - - - - - only lobbies in the same immediate region will be returned - - - - - only lobbies in the same immediate region will be returned - - - - - only lobbies in the same immediate region will be returned - - - - - Filter by specified key/value pair; string parameters - - - - - Numerical filter where value is less than the value provided - - - - - Numerical filter where value is greater than the value provided - - - - - Numerical filter where value must be equal to the value provided - - - - - Numerical filter where value must not equal the value provided - - - - - Test key, initialize numerical filter list if necessary, then add new numerical filter - - - - - Order filtered results according to key/values nearest the provided key/value pair. - Can specify multiple near value filters; each successive filter is lower priority than the previous. - - - - - returns only lobbies with the specified number of slots available - - - - - sets how many results to return, the lower the count the faster it is to download the lobby results - - - - - Run the query, get the matching lobbies - - - - - A server query packet. - - - - - Target IP address - - - - - Target port - - - - - This data is pooled. Make a copy if you don't use it immediately. - This buffer is also quite large - so pay attention to Size. - - - - - Size of the data - - - - - Represents a RemotePlaySession from the SteamRemotePlay interface - - - - - Returns true if this session was valid when created. This will stay true even - after disconnection - so be sure to watch SteamRemotePlay.OnSessionDisconnected - - - - - Get the SteamID of the connected user - - - - - Get the name of the session client device - - - - - Get the name of the session client device - - - - - Tags a user as being visible in the screenshot - - - - - Tags a user as being visible in the screenshot - - - - - Tags a user as being visible in the screenshot - - - - - Gets the individual tags for this server - - - - - Add this server to our history list - If we're already in the history list, weill set the last played time to now - - - - - If this server responds to source engine style queries, we'll be able to get a list of rules here - - - - - Remove this server from our history list - - - - - Add this server to our favourite list - - - - - Remove this server from our favourite list - - - - - Find out the status of an asynchronous inventory result handle. - - - - - Copies the contents of a result set into a flat array. The specific contents of the result set depend on - which query which was used. - - - - - Returns the server time at which the result was generated. Compare against the value of - IClientUtils::GetServerRealTime() to determine age. - - - - - Returns true if the result belongs to the target steam ID or false if the result does not. This is - important when using DeserializeResult to verify that a remote player is not pretending to have a - different users inventory. - - - - - Destroys a result handle and frees all associated memory. - - - - - Captures the entire state of the current users Steam inventory. - - - - - Captures the state of a subset of the current users Steam inventory identified by an array of item - instance IDs. - - - - - GrantPromoItems() checks the list of promotional items for which the user may be eligible and grants the - items (one time only). - - - - - ConsumeItem() removes items from the inventory permanently. - - - - - Deprecated method. Playtime accounting is performed on the Steam servers. - - - - - Playtime credit must be consumed and turned into item drops by your game. - - - - - LoadItemDefinitions triggers the automatic load and refresh of item definitions. - - - - - Downloads leaderboard entries for an arbitrary set of users - ELeaderboardDataRequest is - k_ELeaderboardDataRequestUsers - - - - - An optional interface to use instead of deriving - - - - - The actual connection we're managing - - - - - The last received ConnectionInfo - - - - - We're trying to connect! - - - - - Client is connected. They move from connecting to Connections - - - - - The connection has been closed remotely or disconnected locally. Check data.State for details. - - - - - We started connecting to this guy - - - - - Called when the connection is fully connected and can start being communicated with - - - - - We got disconnected - - - - - Received a message - - - - - Must call Accept or Close on the connection within a second or so - - - - - Called when the connection is fully connected and can start being communicated with - - - - - Called when the connection leaves - - - - - Received a message from a connection - - - - - Used as a base to create your networking server. This creates a socket - and listens/communicates with multiple queries. - - You can override all the virtual functions to turn it into what you - want it to do. - - - - - Default behaviour is to accept every connection - - - - - Client is connected. They move from connecting to Connections - - - - - The connection has been closed remotely or disconnected locally. Check data.State for details. - - - - - Which app we're querying. Defaults to the current app. - - - - - When a new server is added, this function will get called - - - - - Called for every responsive server - - - - - A list of servers that responded. If you're only interested in servers that responded since you - last updated, then simply clear this list. - - - - - A list of servers that were in the master list but didn't respond. - - - - - Query the server list. Task result will be true when finished - - - - - - Exposes a wide range of information and actions for applications and Downloadable Content (DLC). - - - - - posted after the user gains ownership of DLC and that DLC is installed - - - - - posted after the user gains executes a Steam URL with command line or query parameters - such as steam://run/appid//-commandline/?param1=value1(and)param2=value2(and)param3=value3 etc - while the game is already running. The new params can be queried - with GetLaunchQueryParam and GetLaunchCommandLine - - - - - Checks if the active user is subscribed to the current App ID - - - - - Check if user borrowed this game via Family Sharing, If true, call GetAppOwner() to get the lender - SteamID - - - - - Checks if the license owned by the user provides low violence depots. - Low violence depots are useful for copies sold in countries that have content restrictions - - - - - Checks whether the current App ID license is for Cyber Cafes. - - - - - CChecks if the user has a VAC ban on their account - - - - - Gets the current language that the user has set. - This falls back to the Steam UI language if the user hasn't explicitly picked a language for the title. - - - - - Gets a list of the languages the current app supports. - - - - - Checks if the active user is subscribed to a specified AppId. - Only use this if you need to check ownership of another game related to yours, a demo for example. - - - - - Checks if the user owns a specific DLC and if the DLC is installed - - - - - Returns the time of the purchase of the app - - - - - Checks if the user is subscribed to the current app through a free weekend - This function will return false for users who have a retail or other type of license - Before using, please ask your Valve technical contact how to package and secure your free weekened - - - - - Returns metadata for all available DLC - - - - - Install/Uninstall control for optional DLC - - - - - Install/Uninstall control for optional DLC - - - - - Returns null if we're not on a beta branch, else the name of the branch - - - - - Allows you to force verify game content on next launch. - - If you detect the game is out-of-date(for example, by having the client detect a version mismatch with a - server), - you can call use MarkContentCorrupt to force a verify, show a message to the user, and then quit. - - - - - Gets a list of all installed depots for a given App ID in mount order - - - - - Gets the install folder for a specific AppID. - This works even if the application is not installed, based on where the game would be installed with the - default Steam library location. - - - - - The app may not actually be owned by the current user, they may have it left over from a free weekend, - etc. - - - - - Gets the Steam ID of the original owner of the current app. If it's different from the current user then - it is borrowed.. - - - - - Gets the associated launch parameter if the game is run via - steam://run/appid/?param1=value1;param2=value2;param3=value3 etc. - Parameter names starting with the character '@' are reserved for internal use and will always return an - empty string. - Parameter names starting with an underscore '_' are reserved for steam features -- they can be queried - by the game, - but it is advised that you not param names beginning with an underscore for your own features. - - - - - Gets the download progress for optional DLC. - - - - - Gets the buildid of this app, may change at any time based on backend updates to the game. - Defaults to 0 if you're not running a build downloaded from steam. - - - - - Asynchronously retrieves metadata details about a specific file in the depot manifest. - Currently provides: - - - - - Get command line if game was launched via Steam URL, e.g. steam://run/appid//command line/. - This method of passing a connect string (used when joining via rich presence, accepting an - invite, etc) is preferable to passing the connect string on the operating system command - line, which is a security risk. In order for rich presence joins to go through this - path and not be placed on the OS command line, you must set a value in your app's - configuration on Steam. Ask Valve for help with this. - - - - - Initialize the steam client. - If asyncCallbacks is false you need to call RunCallbacks manually every frame. - - - - - Checks if the current user's Steam client is connected to the Steam servers. - If it's not then no real-time services provided by the Steamworks API will be enabled. The Steam - client will automatically be trying to recreate the connection as often as possible. When the - connection is restored a SteamServersConnected_t callback will be posted. - You usually don't need to check for this yourself. All of the API calls that rely on this will - check internally. Forcefully disabling stuff when the player loses access is usually not a - very good experience for the player and you could be preventing them from accessing APIs that do not - need a live connection to Steam. - - - - - Gets the Steam ID of the account currently logged into the Steam client. This is - commonly called the 'current user', or 'local user'. - A Steam ID is a unique identifier for a Steam accounts, Steam groups, Lobbies and Chat - rooms, and used to differentiate users in all parts of the Steamworks API. - - - - - returns the local players name - guaranteed to not be NULL. - this is the same name as on the users community profile page - - - - - gets the status of the current user - - - - - returns the appID of the current process - - - - - Checks if your executable was launched through Steam and relaunches it through Steam if it wasn't - this returns true then it starts the Steam client if required and launches your game again through it, - and you should quit your process as soon as possible. This effectively runs steam://run/AppId so it - may not relaunch the exact executable that called it, as it will always relaunch from the version - installed in your Steam library folder/ - Note that during development, when not launching via Steam, this might always return true. - - - - - Called in interfaces that rely on this being initialized - - - - - Undocumented Parental Settings - - - - - Called when chat message has been received from a friend. You'll need to turn on - ListenForFriendsMessages to recieve this. (friend, msgtype, message) - - - - - called when a friends' status changes - - - - - Called when the user tries to join a game from their friends list - rich presence will have been set with the "connect" key which is set here - - - - - Posted when game overlay activates or deactivates - the game can use this to be pause or resume single player games - - - - - Called when the user tries to join a different game server from their friends list - game client should attempt to connect to specified server when this is received - - - - - Called when the user tries to join a lobby from their friends list - game client should attempt to connect to specified lobby when this is received - - - - - Callback indicating updated data about friends rich presence information - - - - - The dialog to open. Valid options are: - "friends", - "community", - "players", - "settings", - "officialgamegroup", - "stats", - "achievements". - - - - - "steamid" - Opens the overlay web browser to the specified user or groups profile. - "chat" - Opens a chat window to the specified user, or joins the group chat. - "jointrade" - Opens a window to a Steam Trading session that was started with the - ISteamEconomy/StartTrade Web API. - "stats" - Opens the overlay web browser to the specified user's stats. - "achievements" - Opens the overlay web browser to the specified user's achievements. - "friendadd" - Opens the overlay in minimal mode prompting the user to add the target user as a friend. - "friendremove" - Opens the overlay in minimal mode prompting the user to remove the target friend. - "friendrequestaccept" - Opens the overlay in minimal mode prompting the user to accept an incoming - friend invite. - "friendrequestignore" - Opens the overlay in minimal mode prompting the user to ignore an incoming - friend invite. - - - - - Activates the Steam Overlay to the Steam store page for the provided app. - - - - - Activates Steam Overlay web browser directly to the specified URL. - - - - - Activates the Steam Overlay to open the invite dialog. Invitations sent from this dialog will be for the - provided lobby. - - - - - Mark a target user as 'played with'. - NOTE: The current user must be in game with the other player for the association to work. - - - - - Requests the persona name and optionally the avatar of a specified user. - NOTE: It's a lot slower to download avatars and churns the local cache, so if you don't need avatars, - don't request them. - returns true if we're fetching the data, false if we already have it - - - - - Find a rich presence value by key for current user. Will be null if not found. - - - - - Sets a rich presence value by key for current user. - - - - - Clears all of the current user's rich presence data. - - - - - Listens for Steam friends chat messages. - You can then show these chats inline in the game. For example with a Blizzard style chat message system - or the chat system in Dota 2. - After enabling this you will receive callbacks when ever the user receives a chat message. - - - - - You shouldn't really need to call this because it get called by RunCallbacks on SteamClient - but Valve think it might be a nice idea if you call it right before you get input info - - just to make sure the info you're getting is 100% up to date. - - - - - Return a list of connected controllers. - - - - - Return an absolute path to the PNG image glyph for the provided digital action name. The current - action set in use for the controller will be used for the lookup. You should cache the result and - maintain your own list of loaded PNG assets. - - - - - - - - Undocumented Parental Settings - - - - - Call this if you're going to want to access definition information. You should be able to get - away with calling this once at the start if your game, assuming your items don't change all the time. - This will trigger OnDefinitionsUpdated at which point Definitions should be set. - - - - - Will call LoadItemDefinitions and wait until Definitions is not null - - - - - Try to find the definition that matches this definition ID. - Uses a dictionary so should be about as fast as possible. - - - - - We will try to keep this list of your items automatically up to date. - - - - - Update the list of Items[] - - - - - Get all items and return the InventoryResult - - - - - This is used to grant a specific item to the user. This should - only be used for development prototyping, from a trusted server, - or if you don't care about hacked clients granting arbitrary items. - This call can be disabled by a setting on Steamworks. - - - - - Crafting! Uses the passed items to buy the target item. - You need to have set up the appropriate exchange rules in your item - definitions. This assumes all the items passed in aren't stacked. - - - - - Crafting! Uses the passed items to buy the target item. - You need to have set up the appropriate exchange rules in your item - definitions. This assumes all the items passed in aren't stacked. - - - - - Deserializes a result set and verifies the signature bytes. - This call has a potential soft-failure mode where the Result is expired, it will - still succeed in this mode.The "expired" - result could indicate that the data may be out of date - not just due to timed - expiration( one hour ), but also because one of the items in the result set may - have been traded or consumed since the result set was generated.You could compare - the timestamp from GetResultTimestamp to ISteamUtils::GetServerRealTime to determine - how old the data is. You could simply ignore the "expired" result code and - continue as normal, or you could request the player with expired data to send - an updated result set. - You should call CheckResultSteamID on the result handle when it completes to verify - that a remote player is not pretending to have a different user's inventory. - - - - - Grant all promotional items the user is eligible for - - - - - Trigger an item drop for this user. This is for timed drops. - - - - - Trigger a promo item drop. You can call this at startup, it won't - give users multiple promo drops. - - - - - Start buying a cart load of items. This will return a positive result is the purchase has - begun. You should listen out for SteamUser.OnMicroTxnAuthorizationResponse for a success. - - - - - Functions for clients to access matchmaking services, favorites, and to operate on game lobbies - - - - - Maximum number of characters a lobby metadata key can be - - - - - Someone invited you to a lobby - - - - - You joined a lobby - - - - - You created a lobby - - - - - A game server has been associated with the lobby - - - - - The lobby metadata has changed - - - - - The lobby member metadata has changed - - - - - The lobby member joined - - - - - The lobby member left the room - - - - - The lobby member left the room - - - - - The lobby member was kicked. The 3rd param is the user that kicked them. - - - - - The lobby member was banned. The 3rd param is the user that banned them. - - - - - A chat message was recieved from a member of a lobby - - - - - Creates a new invisible lobby. Call lobby.SetPublic to take it online. - - - - - Attempts to directly join the specified lobby - - - - - Get a list of servers that are on your favorites list - - - - - Get a list of servers that you have added to your play history - - - - - Functions for clients to access matchmaking services, favorites, and to operate on game lobbies - - - - - Functions to control music playback in the steam client. - This gives games the opportunity to do things like pause the music or lower the volume, - when an important cut scene is shown, and start playing afterwards. - Nothing uses Steam Music though so this can probably get fucked - - - - - Playback status changed - - - - - Volume changed, parameter is new volume - - - - - Checks if Steam Music is enabled - - - - - true if a song is currently playing, paused, or queued up to play; otherwise false. - - - - - Gets the current status of the Steam Music player - - - - - Have the Steam Music player play the previous song. - - - - - Have the Steam Music player skip to the next song - - - - - Gets/Sets the current volume of the Steam Music player - - - - - This SteamId wants to send you a message. You should respond by calling AcceptP2PSessionWithUser - if you want to recieve their messages - - - - - Called when packets can't get through to the specified user. - All queued packets unsent at this point will be dropped, further attempts - to send will retry making the connection (but will be dropped if we fail again). - - - - - This should be called in response to a OnP2PSessionRequest - - - - - Allow or disallow P2P connects to fall back on Steam server relay if direct - connection or NAT traversal can't be established. Applies to connections - created after setting or old connections that need to reconnect. - - - - - This should be called when you're done communicating with a user, as this will - free up all of the resources allocated for the connection under-the-hood. - If the remote user tries to send data to you again, a new OnP2PSessionRequest - callback will be posted - - - - - Checks if a P2P packet is available to read, and gets the size of the message if there is one. - - - - - Reads in a packet that has been sent from another user via SendP2PPacket.. - - - - - Reads in a packet that has been sent from another user via SendP2PPacket.. - - - - - Reads in a packet that has been sent from another user via SendP2PPacket.. - - - - - Sends a P2P packet to the specified user. - This is a session-less API which automatically establishes NAT-traversing or Steam relay server - connections. - NOTE: The first packet send may be delayed as the NAT-traversal code runs. - - - - - Sends a P2P packet to the specified user. - This is a session-less API which automatically establishes NAT-traversing or Steam relay server - connections. - NOTE: The first packet send may be delayed as the NAT-traversal code runs. - - - - - Creates a "server" socket that listens for clients to connect to by calling - Connect, over ordinary UDP (IPv4 or IPv6) - - To use this derive a class from SocketManager and override as much as you want. - - - - - - Creates a "server" socket that listens for clients to connect to by calling - Connect, over ordinary UDP (IPv4 or IPv6). - - To use this you should pass a class that inherits ISocketManager. You can use - SocketManager to get connections and send messages, but the ISocketManager class - will received all the appropriate callbacks. - - - - - - Connect to a socket created via - CreateListenSocketIP - - - - - Connect to a socket created via - CreateListenSocketIP - - - - - Creates a server that will be relayed via Valve's network (hiding the IP and improving ping) - - - - - Connect to a relay server - - - - - Undocumented Parental Settings - - - - - A function to receive debug network information on. This will do nothing - unless you set DebugLevel to something other than None. - - You should set this to an appropriate level instead of setting it to the highest - and then filtering it by hand because a lot of energy is used by creating the strings - and your frame rate will tank and you won't know why. - - - - - The latest available status gathered from the SteamRelayNetworkStatus callback - - - - - If you know that you are going to be using the relay network (for example, - because you anticipate making P2P connections), call this to initialize the - relay network. If you do not call this, the initialization will - be delayed until the first time you use a feature that requires access - to the relay network, which will delay that first access. - - You can also call this to force a retry if the previous attempt has failed. - Performing any action that requires access to the relay network will also - trigger a retry, and so calling this function is never strictly necessary, - but it can be useful to call it a program launch time, if access to the - relay network is anticipated. - - Use GetRelayNetworkStatus or listen for SteamRelayNetworkStatus_t - callbacks to know when initialization has completed. - Typically initialization completes in a few seconds. - - Note: dedicated servers hosted in known data centers do *not* need - to call this, since they do not make routing decisions. However, if - the dedicated server will be using P2P functionality, it will act as - a "client" and this should be called. - - - - - Return location info for the current host. - - It takes a few seconds to initialize access to the relay network. If - you call this very soon after startup the data may not be available yet. - - This always return the most up-to-date information we have available - right now, even if we are in the middle of re-calculating ping times. - - - - - Same as PingLocation.EstimatePingTo, but assumes that one location is the local host. - This is a bit faster, especially if you need to calculate a bunch of - these in a loop to find the fastest one. - - - - - If you need ping information straight away, wait on this. It will return - immediately if you already have up to date ping data - - - - - [0 - 100] - Randomly discard N pct of packets - - - - - [0 - 100] - Randomly discard N pct of packets - - - - - Delay all packets by N ms - - - - - Delay all packets by N ms - - - - - Timeout value (in ms) to use when first connecting - - - - - Timeout value (in ms) to use after connection is established - - - - - Upper limit of buffered pending bytes to be sent. - If this is reached SendMessage will return LimitExceeded. - Default is 524288 bytes (512k) - - - - - Get Debug Information via OnDebugOutput event - - Except when debugging, you should only use NetDebugOutput.Msg - or NetDebugOutput.Warning. For best performance, do NOT - request a high detail level and then filter out messages in the callback. - - This incurs all of the expense of formatting the messages, which are then discarded. - Setting a high priority value (low numeric value) here allows the library to avoid - doing this work. - - - - - So we can remember and provide a Get for DebugLEvel - - - - - We need to keep the delegate around until it's not used anymore - - - - - This can be called from other threads - so we're going to queue these up and process them in a safe - place. - - - - - Called regularly from the Dispatch loop so we can provide a timely - stream of messages. - - - - - Undocumented Parental Settings - - - - - Parental Settings Changed - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This API can be used to selectively advertise your multiplayer game session in a Steam chat room group. - Tell Steam the number of player spots that are available for your party, and a join-game string, and it - will show a beacon in the selected group and allow that many users to “follow” the beacon to your party. - Adjust the number of open slots if other players join through alternate matchmaking methods. - - - - - The list of possible Party beacon locations has changed - - - - - The list of active beacons may have changed - - - - - Functions that provide information about Steam Remote Play sessions, streaming your game content to - another computer or to a Steam Link app or hardware. - - - - - Called when a session is connected - - - - - Called when a session becomes disconnected - - - - - Get the number of currently connected Steam Remote Play sessions - - - - - Get the currently connected Steam Remote Play session ID at the specified index. - IsValid will return false if it's out of bounds - - - - - Invite a friend to Remote Play Together - This returns false if the invite can't be sent - - - - - Undocumented Parental Settings - - - - - Creates a new file, writes the bytes to the file, and then closes the file. - If the target file already exists, it is overwritten - - - - - Opens a binary file, reads the contents of the file into a byte array, and then closes the file. - - - - - Checks whether the specified file exists. - - - - - Checks if a specific file is persisted in the steam cloud. - - - - - Gets the specified file's last modified date/time. - - - - - Gets the specified files size in bytes. 0 if not exists. - - - - - Deletes the file from remote storage, but leaves it on the local disk and remains accessible from the - API. - - - - - Deletes a file from the local disk, and propagates that delete to the cloud. - - - - - Number of bytes total - - - - - Number of bytes used - - - - - Number of bytes remaining until your quota is used - - - - - returns true if IsCloudEnabledForAccount AND IsCloudEnabledForApp - - - - - Checks if the account wide Steam Cloud setting is enabled for this user - or if they disabled it in the Settings->Cloud dialog. - - - - - Checks if the per game Steam Cloud setting is enabled for this user - or if they disabled it in the Game Properties->Update dialog. - - This must only ever be set as the direct result of the user explicitly - requesting that it's enabled or not. This is typically accomplished with - a checkbox within your in-game options - - - - - Gets the total number of local files synchronized by Steam Cloud. - - - - - Get a list of filenames synchronized by Steam Cloud - - - - - Undocumented Parental Settings - - - - - A screenshot has been requested by the user from the Steam screenshot hotkey. - This will only be called if Hooked is true, in which case Steam - will not take the screenshot itself. - - - - - A screenshot successfully written or otherwise added to the library and can now be tagged. - - - - - A screenshot attempt failed - - - - - Writes a screenshot to the user's screenshot library given the raw image data, which must be in RGB - format. - The return value is a handle that is valid for the duration of the game process and can be used to apply - tags. - - - - - Adds a screenshot to the user's screenshot library from disk. If a thumbnail is provided, it must be 200 - pixels wide and the same aspect ratio - as the screenshot, otherwise a thumbnail will be generated if the user uploads the screenshot. The - screenshots must be in either JPEG or TGA format. - The return value is a handle that is valid for the duration of the game process and can be used to apply - tags. - JPEG, TGA, and PNG formats are supported. - - - - - Causes the Steam overlay to take a screenshot. - If screenshots are being hooked by the game then a - ScreenshotRequested callback is sent back to the game instead. - - - - - Toggles whether the overlay handles screenshots when the user presses the screenshot hotkey, or if the - game handles them. - Hooking is disabled by default, and only ever enabled if you do so with this function. - If the hooking is enabled, then the ScreenshotRequested_t callback will be sent if the user presses the - hotkey or - when TriggerScreenshot is called, and then the game is expected to call WriteScreenshot or - AddScreenshotToLibrary in response. - - - - - Provides the core of the Steam Game Servers API - - - - - User has been authed or rejected - - - - - Called when a connections to the Steam back-end has been established. - This means the server now is logged on and has a working connection to the Steam master server. - - - - - This will occur periodically if the Steam client is not connected, and has failed when retrying to - establish a connection (result, stilltrying) - - - - - Disconnected from Steam - - - - - Initialize the steam server. - If asyncCallbacks is false you need to call RunCallbacks manually every frame. - - - - - Run the callbacks. This is also called in Async callbacks. - - - - - Sets whether this should be marked as a dedicated server. - If not, it is assumed to be a listen server. - - - - - Gets or sets the current MaxPlayers. - This doesn't enforce any kind of limit, it just updates the master server. - - - - - Gets or sets the current BotCount. - This doesn't enforce any kind of limit, it just updates the master server. - - - - - Gets or sets the current Map Name. - - - - - Gets or sets the current ModDir - - - - - Gets the current product - - - - - Gets or sets the current Product - - - - - Gets or sets the current ServerName - - - - - Set whether the server should report itself as passworded - - - - - Gets or sets the current GameTags. This is a comma seperated list of tags for this server. - When querying the server list you can filter by these tags. - - - - - Log onto Steam anonymously. - - - - - Log onto Steam anonymously. - - - - - Returns true if the server is connected and registered with the Steam master server - You should have called LogOnAnonymous etc on startup. - - - - - To the best of its ability this tries to get the server's - current public ip address. Be aware that this is likely to return - null for the first few seconds after initialization. - - - - - Enable or disable heartbeats, which are sent regularly to the master server. - Enabled by default. - - - - - Set heartbeat interval, if automatic heartbeats are enabled. - You can leave this at the default. - - - - - Force send a heartbeat to the master server instead of waiting - for the next automatic update (if you've left them enabled) - - - - - Update this connected player's information. You should really call this - any time a player's name or score changes. This keeps the information shown - to server queries up to date. - - - - - Sets a Key Value. These can be anything you like, and are accessible - when querying servers from the server list. - - Information describing gamemodes are common here. - - - - - Remove all key values - - - - - Start authorizing a ticket. This user isn't authorized yet. Wait for a call to OnAuthChange. - - - - - Forget this guy. They're no longer in the game. - - - - - If true, Steam wants to send a packet. You should respond by sending - this packet in an unconnected way to the returned Address and Port. - - Packet to send. The Data passed is pooled - so use it immediately. - True if we want to send a packet - - - - We have received a server query on our game port. Pass it to Steam to handle. - - - - - We have received a server query on our game port. Pass it to Steam to handle. - - - - - Does the user own this app (which could be DLC) - - - - - Downloads stats for the user - If the user has no stats will return fail - these stats will only be auto-updated for clients playing on the server - - - - - Set the named stat for this user. Setting stats should follow the rules - you defined in Steamworks. - - - - - Set the named stat for this user. Setting stats should follow the rules - you defined in Steamworks. - - - - - Get the named stat for this user. If getting the stat failed, will return - defaultValue. You should have called Refresh for this userid - which downloads - the stats from the backend. If you didn't call it this will always return defaultValue. - - - - - Get the named stat for this user. If getting the stat failed, will return - defaultValue. You should have called Refresh for this userid - which downloads - the stats from the backend. If you didn't call it this will always return defaultValue. - - - - - Unlocks the specified achievement for the specified user. Must have called Refresh on a steamid first. - Remember to use Commit after use. - - - - - Resets the unlock status of an achievement for the specified user. Must have called Refresh on a steamid - first. - Remember to use Commit after use. - - - - - Return true if available, exists and unlocked - - - - - Once you've set a stat change on a user you need to commit your changes. - You can do that using this function. The callback will let you know if - your action succeeded, but most of the time you can fire and forget. - - - - - Functions for accessing and manipulating Steam user information. - This is also where the APIs for Steam Voice are exposed. - - - - - Posted after Download call - - - - - Start downloading this item. You'll get notified of completion via OnDownloadItemResult. - - The ID of the file you want to download - If true this should go straight to the top of the download list - true if nothing went wrong and the download is started - - - - Will attempt to download this item asyncronously - allowing you to instantly react to its installation - - The ID of the file you want to download - An optional callback - Allows you to send a message to cancel the download anywhere during the process - How often to call the progress function - true if downloaded and installed correctly - - - - Utility function to fetch a single item. Internally this uses Ugc.FileQuery - - which you can use to query multiple items if you need to. - - - - - Functions for accessing and manipulating Steam user information. - This is also where the APIs for Steam Voice are exposed. - - - - - Called when a connections to the Steam back-end has been established. - This means the Steam client now has a working connection to the Steam servers. - Usually this will have occurred before the game has launched, and should only be seen if the - user has dropped connection due to a networking issue or a Steam server update. - - - - - Called when a connection attempt has failed. - This will occur periodically if the Steam client is not connected, - and has failed when retrying to establish a connection. - - - - - Called if the client has lost connection to the Steam servers. - Real-time services will be disabled until a matching OnSteamServersConnected has been posted. - - - - - Sent by the Steam server to the client telling it to disconnect from the specified game server, - which it may be in the process of or already connected to. - The game client should immediately disconnect upon receiving this message. - This can usually occur if the user doesn't have rights to play on the game server. - - - - - Called whenever the users licenses (owned packages) changes. - - - - - Called when an auth ticket has been validated. - The first parameter is the steamid of this user - The second is the Steam ID that owns the game, this will be different from the first - if the game is being borrowed via Steam Family Sharing - - - - - Used internally for GetAuthSessionTicketAsync - - - - - Called when a user has responded to a microtransaction authorization request. - ( appid, orderid, user authorized ) - - - - - Sent to your game in response to a steam://gamewebcallback/ command from a user clicking a link in the - Steam overlay browser. - You can use this to add support for external site signups where you want to pop back into the browser - after some web page - signup sequence, and optionally get back some detail about that. - - - - - Sent for games with enabled anti indulgence / duration control, for enabled users. - Lets the game know whether persistent rewards or XP should be granted at normal rate, - half rate, or zero rate. - - - - - Starts/Stops voice recording. - Once started, use GetAvailableVoice and GetVoice to get the data, and then call StopVoiceRecording - when the user has released their push-to-talk hotkey or the game session has completed. - - - - - Returns true if we have voice data waiting to be read - - - - - Reads the voice data and returns the number of bytes written. - The compressed data can be transmitted by your application and decoded back into raw audio data using - DecompressVoice on the other side. The compressed data provided is in an arbitrary format and is not - meant to be played directly. - This should be called once per frame, and at worst no more than four times a second to keep the - microphone input delay as low as - possible. Calling this any less may result in gaps in the returned stream. - - - - - Reads the voice data and returns the bytes. You should obviously ideally be using - ReadVoiceData because it won't be creating a new byte array every call. But this - makes it easier to get it working, so let the babies have their bottle. - - - - - Decodes the compressed voice data returned by GetVoice. - The output data is raw single-channel 16-bit PCM audio.The decoder supports any sample rate from 11025 - to 48000. - - - - - Retrieve a authentication ticket to be sent to the entity who wishes to authenticate you. - - - - - Retrieve a authentication ticket to be sent to the entity who wishes to authenticate you. - This waits for a positive response from the backend before returning the ticket. This means - the ticket is definitely ready to go as soon as it returns. Will return null if the callback - times out or returns negatively. - - - - - Checks if the current users looks like they are behind a NAT device. - This is only valid if the user is connected to the Steam servers and may not catch all forms of NAT. - - - - - Gets the Steam level of the user, as shown on their Steam community profile. - - - - - Requests a URL which authenticates an in-game browser for store check-out, and then redirects to the - specified URL. - As long as the in-game browser accepts and handles session cookies, Steam microtransaction checkout - pages will automatically recognize the user instead of presenting a login page. - NOTE: The URL has a very short lifetime to prevent history-snooping attacks, so you should only call - this API when you are about to launch the browser, or else immediately navigate to the result URL using - a hidden browser window. - NOTE: The resulting authorization cookie has an expiration time of one day, so it would be a good idea - to request and visit a new auth URL every 12 hours. - - - - - Checks whether the current user has verified their phone number. - - - - - Checks whether the current user has Steam Guard two factor authentication enabled on their account. - - - - - Checks whether the user's phone number is used to uniquely identify them. - - - - - Checks whether the current user's phone number is awaiting (re)verification. - - - - - Requests an application ticket encrypted with the secret "encrypted app ticket key". - The encryption key can be obtained from the Encrypted App Ticket Key page on the App Admin for your app. - There can only be one call pending, and this call is subject to a 60 second rate limit. - If you get a null result from this it's probably because you're calling it too often. - This can fail if you don't have an encrypted ticket set for your app here - https://partner.steamgames.com/apps/sdkauth/ - - - - - Requests an application ticket encrypted with the secret "encrypted app ticket key". - The encryption key can be obtained from the Encrypted App Ticket Key page on the App Admin for your app. - There can only be one call pending, and this call is subject to a 60 second rate limit. - This can fail if you don't have an encrypted ticket set for your app here - https://partner.steamgames.com/apps/sdkauth/ - - - - - Get anti indulgence / duration control - - - - - called when the achivement icon is loaded - - - - - called when the latests stats and achievements have been received - from the server - - - - - result of a request to store the user stats for a game - - - - - result of a request to store the achievements for a game, or an - "indicate progress" call. If both m_nCurProgress and m_nMaxProgress - are zero, that means the achievement has been fully unlocked - - - - - Callback indicating that a user's stats have been unloaded - - - - - Get the available achievements - - - - - Show the user a pop-up notification with the current progress toward an achievement. - Will return false if RequestCurrentStats has not completed and successfully returned - its callback, if the achievement doesn't exist/has unpublished changes in the app's - Steamworks Admin page, or if the achievement is unlocked. - - - - - Tries to get the number of players currently playing this game. - Or -1 if failed. - - - - - Send the changed stats and achievements data to the server for permanent storage. - If this fails then nothing is sent to the server. It's advisable to keep trying until the call is - successful. - This call can be rate limited. Call frequency should be on the order of minutes, rather than seconds.You - should only be calling this during major state changes such as the end of a round, the map changing, or - the user leaving a server. This call is required to display the achievement unlock notification dialog - though, so if you have called SetAchievement then it's advisable to call this soon after that. - If you have stats or achievements that you have saved locally but haven't uploaded with this function - when your application process ends then this function will automatically be called. - You can find additional debug information written to the %steam_install%\logs\stats_log.txt file. - This function returns true upon success if : - RequestCurrentStats has completed and successfully returned its callback AND - the current game has stats associated with it in the Steamworks Partner backend, and those stats are - published. - - - - - Asynchronously request the user's current stats and achievements from the server. - You must always call this first to get the initial status of stats and achievements. - Only after the resulting callback comes back can you start calling the rest of the stats - and achievement functions for the current user. - - - - - Asynchronously fetches global stats data, which is available for stats marked as - "aggregated" in the App Admin panel of the Steamworks website. - You must have called RequestCurrentStats and it needs to return successfully via - its callback prior to calling this. - - How many days of day-by-day history to retrieve in addition to the overall totals. The - limit is 60. - - OK indicates success, InvalidState means you need to call RequestCurrentStats first, Fail means the - remote call failed - - - - - Gets a leaderboard by name, it will create it if it's not yet created. - Leaderboards created with this function will not automatically show up in the Steam Community. - You must manually set the Community Name field in the App Admin panel of the Steamworks website. - As such it's generally recommended to prefer creating the leaderboards in the App Admin panel on - the Steamworks website and using FindLeaderboard unless you're expected to have a large amount of - dynamically created leaderboards. - - - - - Adds this amount to the named stat. Internally this calls Get() and adds - to that value. Steam doesn't provide a mechanism for atomically increasing - stats like this, this functionality is added here as a convenience. - - - - - Adds this amount to the named stat. Internally this calls Get() and adds - to that value. Steam doesn't provide a mechanism for atomically increasing - stats like this, this functionality is added here as a convenience. - - - - - Set a stat value. This will automatically call StoreStats() after a successful call - unless you pass false as the last argument. - - - - - Set a stat value. This will automatically call StoreStats() after a successful call - unless you pass false as the last argument. - - - - - Get a Int stat value - - - - - Get a float stat value - - - - - Practically wipes the slate clean for this user. If includeAchievements is true, will wipe - any achievements too. - - - - - - Interface which provides access to a range of miscellaneous utility functions - - - - - The country of the user changed - - - - - Fired when running on a laptop and less than 10 minutes of battery is left, fires then every minute - The parameter is the number of minutes left - - - - - Called when Steam wants to shutdown - - - - - Big Picture gamepad text input has been closed. Parameter is true if text was submitted, false if - cancelled etc. - - - - - Returns the number of seconds since the application was active - - - - - Returns the number of seconds since the user last moved the mouse etc - - - - - Steam server time. Number of seconds since January 1, 1970, GMT (i.e unix time) - - - - - returns the 2 digit ISO 3166-1-alpha-2 format country code this client is running in (as looked up via - an IP-to-location database) - e.g "US" or "UK". - - - - - returns true if the image exists, and the buffer was successfully filled out - results are returned in RGBA format - the destination buffer size should be 4 * height * width * sizeof(char) - - - - - returns the image in RGBA format - - - - - Returns true if we're using a battery (ie, a laptop not plugged in) - - - - - Returns battery power [0-1] - - - - - Sets the position where the overlay instance for the currently calling game should show notifications. - This position is per-game and if this function is called from outside of a game context it will do - nothing. - - - - - Returns true if the overlay is running and the user can access it. The overlay process could take a few - seconds to - start and hook the game process, so this function will initially return false while the overlay is - loading. - - - - - Normally this call is unneeded if your game has a constantly running frame loop that calls the - D3D Present API, or OGL SwapBuffers API every frame. - - However, if you have a game that only refreshes the screen on an event driven basis then that can break - the overlay, as it uses your Present/SwapBuffers calls to drive it's internal frame loop and it may also - need to Present() to the screen any time an even needing a notification happens or when the overlay is - brought up over the game by a user. You can use this API to ask the overlay if it currently need a - present - in that case, and then you can check for this periodically (roughly 33hz is desirable) and make sure you - refresh the screen with Present or SwapBuffers to allow the overlay to do it's work. - - - - - Asynchronous call to check if an executable file has been signed using the public key set on the signing - tab - of the partner site, for example to refuse to load modified executable files. - - - - - Activates the Big Picture text input dialog which only supports gamepad input - - - - - Returns previously entered text - - - - - returns the language the steam client is running in, you probably want - Apps.CurrentGameLanguage instead, this is for very special usage cases - - - - - returns true if Steam itself is running in VR mode - - - - - Sets the inset of the overlay notification from the corner specified by SetOverlayNotificationPosition - - - - - returns true if Steam and the Steam Overlay are running in Big Picture mode - Games much be launched through the Steam client to enable the Big Picture overlay. During development, - a game can be added as a non-steam game to the developers library to test this feature - - - - - ask SteamUI to create and render its OpenVR dashboard - - - - - Set whether the HMD content will be streamed via Steam In-Home Streaming - If this is set to true, then the scene in the HMD headset will be streamed, and remote input will not be - allowed. - If this is set to false, then the application window will be streamed instead, and remote input will be - allowed. - The default is true unless "VRHeadsetStreaming" "0" is in the extended appinfo for a game. - (this is useful for games that have asymmetric multiplayer gameplay) - - - - - Returns whether this steam client is a Steam China specific client, vs the global client - - - - - Undocumented Parental Settings - - - - - Return true if currently using Steam's live broadcasting - - - - - If we're broadcasting, will return the number of live viewers - - - - - Reconfigure the controller to use the specified action set (ie 'Menu', 'Walk' or 'Drive') - This is cheap, and can be safely called repeatedly. It's often easier to repeatedly call it in - our state loops, instead of trying to place it in all of your state transitions. - - - - - Returns the current state of the supplied digital game action - - - - - Returns the current state of these supplied analog game action - - - - - Returns true if this is the local user - - - - - Return true if this is a friend - - - - - Returns true if you have this user blocked - - - - - Return true if this user is playing the game we're running - - - - - Returns true if this friend is online - - - - - Sometimes we don't know the user's name. This will wait until we have - downloaded the information on this user. - - - - - Returns true if this friend is marked as away - - - - - Returns true if this friend is marked as busy - - - - - Returns true if this friend is marked as snoozing - - - - - Invite this friend to the game that we are playing - - - - - Sends a message to a Steam friend. Returns true if success - - - - - Tries to get download the latest user stats - - True if successful, False if failure - - - - Gets a user stat. Must call RequestUserStats first. - - The name of the stat you want to get - Will return this value if not available - The value, or defult if not available - - - - Gets a user stat. Must call RequestUserStats first. - - The name of the stat you want to get - Will return this value if not available - The value, or defult if not available - - - - Gets a user achievement state. Must call RequestUserStats first. - - The name of the achievement you want to get - Will return this value if not available - The value, or defult if not available - - - - Gets a the time this achievement was unlocked. - - The name of the achievement you want to get - The time unlocked. If it wasn't unlocked, or you haven't downloaded the stats yet - will return - DateTime.MinValue - - - - - Shortcut to call GetProperty( "name" ) - - - - - Shortcut to call GetProperty( "description" ) - - - - - Shortcut to call GetProperty( "icon_url" ) - - - - - Shortcut to call GetProperty( "icon_url_large" ) - - - - - Shortcut to call GetProperty( "price_category" ) - - - - - Shortcut to call GetProperty( "type" ) - - - - - Returns true if this is an item that generates an item, rather - than something that is actual an item - - - - - Shortcut to call GetProperty( "exchange" ) - - - - - Get a list of exchanges that are available to make this item - - - - - Shortcut to call GetBoolProperty( "marketable" ) - - - - - Shortcut to call GetBoolProperty( "tradable" ) - - - - - Gets the property timestamp - - - - - Gets the property modified - - - - - Get a specific property by name - - - - - Read a raw property from the definition schema - - - - - Read a raw property from the definition schema - - - - - Gets a list of all properties on this item - - - - - Returns the price of this item in the local currency (SteamInventory.Currency) - - - - - If the price has been discounted, LocalPrice will differ from LocalBasePrice - (assumed, this isn't documented) - - - - - Return a list of recepies that contain this item - - - - - Only available if the result set was created with the getproperties - - - - - This item is account-locked and cannot be traded or given away. - This is an item status flag which is permanently attached to specific item instances - - - - - The item has been destroyed, traded away, expired, or otherwise invalidated. - This is an action confirmation flag which is only set one time, as part of a result set. - - - - - The item quantity has been decreased by 1 via ConsumeItem API. - This is an action confirmation flag which is only set one time, as part of a result set. - - - - - Consumes items from a user's inventory. If the quantity of the given item goes to zero, it is - permanently removed. - Once an item is removed it cannot be recovered.This is not for the faint of heart - if your game - implements item removal at all, - a high-friction UI confirmation process is highly recommended.ConsumeItem can be restricted to certain - item definitions or fully - blocked via the Steamworks website to minimize support/abuse issues such as the classic "my brother - borrowed my laptop and deleted all of my rare items". - - - - - Split stack into two items - - - - - Add x units of the target item to this item - - - - - Will try to return the date that this item was aquired. You need to have for the items - with their properties for this to work. - - - - - Tries to get the origin property. Need properties for this to work. - Will return a string like "market" - - - - - Small utility class to describe an item with a quantity - - - - - A structured description of an item exchange - - - - - The definition ID of the ingredient. - - - - - If we don't know about this item definition this might be null. - In which case, DefinitionId should still hold the correct id. - - - - - The amount of this item needed. Generally this will be 1. - - - - - The item that this will create. - - - - - The items, with quantity required to create this item. - - - - - Checks whether an inventory result handle belongs to the specified Steam ID. - This is important when using Deserialize, to verify that a remote player is not pretending to have a - different user's inventory - - - - - Serialized result sets contain a short signature which can't be forged or replayed across different game - sessions. - A result set can be serialized on the local client, transmitted to other players via your game - networking, and - deserialized by the remote players.This is a secure way of preventing hackers from lying about posessing - rare/high-value items. Serializes a result set with signature bytes to an output buffer.The size of a - serialized - result depends on the number items which are being serialized.When securely transmitting items to other - players, - it is recommended to use GetItemsByID first to create a minimal result set. - Results have a built-in timestamp which will be considered "expired" after an hour has elapsed.See - DeserializeResult - for expiration handling. - - - - - Creator of the beacon - - - - - Creator of the beacon - - - - - Will attempt to join the party. If successful will return a connection string. - If failed, will return null - - - - - When a user follows your beacon, Steam will reserve one of the open party slots for them, and send your - game a ReservationNotification callback. - When that user joins your party, call OnReservationCompleted to notify Steam that the user has joined - successfully - - - - - To cancel a reservation (due to timeout or user input), call this. - Steam will open a new reservation slot. - Note: The user may already be in-flight to your game, so it's possible they will still connect and try - to join your party. - - - - - Turn off the beacon - - - - - Used to set up the server. - The variables in here are all required to be set, and can't be changed once the server is created. - - - - - The version string is usually in the form x.x.x.x, and is used by the master server to detect when the - server is out of date. - If you go into the dedicated server tab on steamworks you'll be able to server the latest version. If - this version number is - less than that latest version then your server won't show. - - - - - This should be the same directory game where gets installed into. Just the folder name, not the whole - path. I.e. "Rust", "Garrysmod". - - - - - The game description. Setting this to the full name of your game is recommended. - - - - - Is a dedicated server - - - - - Set the Steam quert port - - - - - If you pass MASTERSERVERUPDATERPORT_USEGAMESOCKETSHARE into usQueryPort, then it causes the game server - API to use - "GameSocketShare" mode, which means that the game is responsible for sending and receiving UDP packets - for the master - server updater. - - More info about this here: https://partner.steamgames.com/doc/api/ISteamGameServer#HandleIncomingPacket - - - - - Create a Normal Workshop item that can be subscribed to - - - - - Workshop item that is meant to be voted on for the purpose of selling in-game - - - - - https://partner.steamgames.com/doc/features/workshop/implementation#Legal - - - - - The actual ID of this file - - - - - The given title of this item - - - - - The description of this item, in your local language if available - - - - - A list of tags for this item, all lowercase - - - - - App Id of the app that created this item - - - - - App Id of the app that will consume this item. - - - - - User who created this content - - - - - The bayesian average for up votes / total votes, between [0,1] - - - - - Time when the published item was created - - - - - Time when the published item was last updated - - - - - True if this is publically visible - - - - - True if this item is only visible by friends of the creator - - - - - True if this is only visible to the creator - - - - - True if this item has been banned - - - - - Whether the developer of this app has specifically flagged this item as accepted in the Workshop - - - - - The number of upvotes of this item - - - - - The number of downvotes of this item - - - - - Start downloading this item. - If this returns false the item isn't getting downloaded. - - - - - If we're downloading, how big the total download is - - - - - If we're downloading, how much we've downloaded - - - - - If we're installed, how big is the install - - - - - If we're downloading our current progress as a delta betwen 0-1 - - - - - A case insensitive check for tag - - - - - Allows the user to subscribe to this item - - - - - Allows the user to subscribe to download this item asyncronously - If CancellationToken is default then there is 60 seconds timeout - Progress will be set to 0-1 - - - - - Allows the user to unsubscribe from this item - - - - - Adds item to user favorite list - - - - - Removes item from user favorite list - - - - - Allows the user to rate a workshop item up or down. - - - - - Gets the current users vote on the item - - - - - Return a URL to view this item online - - - - - The URl to view this item's changelog - - - - - The URL to view the comments on this item - - - - - The URL to discuss this item - - - - - The URL to view this items stats online - - - - - The URL to the preview image for this item - - - - - Edit this item - - - - - Found items must have at least one of the defined tags - - - - - Found items must have all defined tags - - - - - Returns the current Unix Epoch - - - - - Convert an epoch to a datetime - - - - - Convert a DateTime to a unix time - - - - - Returns a buffer. This will get returned and reused later on. - - - - - Prevent unity from stripping shit we depend on - https://docs.unity3d.com/Manual/ManagedCodeStripping.html - - - - diff --git a/Assets/Packages/Facepunch/Facepunch.Steamworks.Win32.xml.meta b/Assets/Packages/Facepunch/Facepunch.Steamworks.Win32.xml.meta deleted file mode 100644 index 4b60cf0..0000000 --- a/Assets/Packages/Facepunch/Facepunch.Steamworks.Win32.xml.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 1c9eb7c3219a16948b7520dc7026cf20 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Packages/Facepunch/Facepunch.Steamworks.Win64.dll b/Assets/Packages/Facepunch/Facepunch.Steamworks.Win64.dll deleted file mode 100644 index bceb91035379865b6908e4f646072a3b6717e69d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 546816 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 - - - Facepunch.Steamworks.Win64 - - - - - An awaitable version of a SteamAPICall_t - - - - - This gets called if IsComplete returned false on the first call. - The Action "continues" the async call. We pass it to the Dispatch - to be called when the callback returns. - - - - - Gets the result. This is called internally by the async shit. - - - - - Return true if complete or failed - - - - - This is what makes this struct awaitable - - - - - Gives us a generic way to get the CallbackId of structs - - - - - Cancels a ticket. - You should cancel your ticket when you close the game or leave a server. - - - - - Responsible for all callback/callresult handling - - This manually pumps Steam's message queue and dispatches those - events to any waiting callbacks/callresults. - - - - - If set then we'll call this function every time a callback is generated. - - This is SLOW!! - it's for debugging - don't keep it on all the time. If you want to access a specific - callback then please create an issue on github and I'll add it! - - Params are : [Callback Type] [Callback Contents] [server] - - - - - - Called if an exception happens during a callback/callresult. - This is needed because the exception isn't always accessible when running - async.. and can fail silently. With this hooked you won't be stuck wondering - what happened. - - - - - This gets called from Client/Server Init - It's important to switch to the manual dispatcher - - - - - Make sure we don't call Frame in a callback - because that'll cause some issues for everyone. - - - - - Calls RunFrame and processes events from this Steam Pipe - - - - - To be safe we don't call the continuation functions while iterating - the Callback list. This is maybe overly safe because the only way this - could be an issue is if the callback list is modified in the continuation - which would only happen if starting or shutting down in the callback. - - - - - A callback is a general global message - - - - - Given a callback, try to turn it into a string - - - - - A result is a reply to a specific command - - - - - Pumps the queue in an async loop so we don't - have to think about it. This has the advantage that - you can call .Wait() on async shit and it still works. - - - - - Pumps the queue in an async loop so we don't - have to think about it. This has the advantage that - you can call .Wait() on async shit and it still works. - - - - - Watch for a steam api call - - - - - Install a global callback. The passed function will get called if it's all good. - - - - - The score is just a simple numerical value - - - - - The score represents a time, in seconds - - - - - The score represents a time, in milliseconds - - - - - The top-score is the lowest number - - - - - The top-score is the highest number - - - - - Send the message unreliably. Can be lost. Messages *can* be larger than a - single MTU (UDP packet), but there is no retransmission, so if any piece - of the message is lost, the entire message will be dropped. - - The sending API does have some knowledge of the underlying connection, so - if there is no NAT-traversal accomplished or there is a recognized adjustment - happening on the connection, the packet will be batched until the connection - is open again. - - - - - Disable Nagle's algorithm. - By default, Nagle's algorithm is applied to all outbound messages. This means - that the message will NOT be sent immediately, in case further messages are - sent soon after you send this, which can be grouped together. Any time there - is enough buffered data to fill a packet, the packets will be pushed out immediately, - but partially-full packets not be sent until the Nagle timer expires. - - - - - If the message cannot be sent very soon (because the connection is still doing some initial - handshaking, route negotiations, etc), then just drop it. This is only applicable for unreliable - messages. Using this flag on reliable messages is invalid. - - - - Reliable message send. Can send up to 0.5mb in a single message. - Does fragmentation/re-assembly of messages under the hood, as well as a sliding window for - efficient sends of large chunks of data. - - - - Return a NetIdentity that represents LocalHost - - - - - Return true if this identity is localhost - - - - - Convert to a SteamId - - - - - - Set the specified Address - - - - - Automatically convert to a SteamId - - - - - - Returns NULL if we're not a SteamId - - - - - Returns NULL if we're not a NetAddress - - - - - We override tostring to provide a sensible representation - - - - - The Port. This is redundant documentation. - - - - - Any IP, specific port - - - - - Localhost IP, specific port - - - - - Specific IP, specific port - - - - - Specific IP, specific port - - - - - Set everything to zero - - - - - Return true if the IP is ::0. (Doesn't check port.) - - - - - Return true if IP is mapped IPv4 - - - - - Return true if this identity is localhost. (Either IPv6 ::1, or IPv4 127.0.0.1) - - - - - Get the Address section - - - - - Used as a base to create your client connection. This creates a socket - to a single connection. - - You can override all the virtual functions to turn it into what you - want it to do. - - - - - Accept an incoming connection that has been received on a listen socket. - - - - - Disconnects from the remote host and invalidates the connection handle. Any unread data on the - connection is discarded.. - reasonCode is defined and used by you. - - - - - Get/Set connection user data - - - - - A name for the connection, used mostly for debugging - - - - - This is the best version to use. - - - - - Ideally should be using an IntPtr version unless you're being really careful with the byte[] array and - you're not creating a new one every frame (like using .ToArray()) - - - - - Ideally should be using an IntPtr version unless you're being really careful with the byte[] array and - you're not creating a new one every frame (like using .ToArray()) - - - - - This creates a ton of garbage - so don't do anything with this beyond testing! - - - - - Flush any messages waiting on the Nagle timer and send them at the next transmission - opportunity (often that means right now). - - - - - Returns detailed connection stats in text format. Useful - for dumping to a log, etc. - - Plain text connection info - - - - Describe the state of a connection - - - - - High level state of the connection - - - - - Remote address. Might be all 0's if we don't know it, or if this is N/A. - - - - - Who is on the other end? Depending on the connection type and phase of the connection, we might not know - - - - - Basic cause of the connection termination or problem. - - - - - - Object that describes a "location" on the Internet with sufficient - detail that we can reasonably estimate an upper bound on the ping between - the two hosts, even if a direct route between the hosts is not possible, - and the connection must be routed through the Steam Datagram Relay network. - This does not contain any information that identifies the host. Indeed, - if two hosts are in the same building or otherwise have nearly identical - networking characteristics, then it's valid to use the same location - object for both of them. - - NOTE: This object should only be used in the same process! Do not serialize it, - send it over the wire, or persist it in a file or database! If you need - to do that, convert it to a string representation using the methods in - ISteamNetworkingUtils(). - - - - - Estimate the round-trip latency between two arbitrary locations, in - milliseconds. This is a conservative estimate, based on routing through - the relay network. For most basic relayed connections, this ping time - will be pretty accurate, since it will be based on the route likely to - be actually used. - - If a direct IP route is used (perhaps via NAT traversal), then the route - will be different, and the ping time might be better. Or it might actually - be a bit worse! Standard IP routing is frequently suboptimal! - - But even in this case, the estimate obtained using this method is a - reasonable upper bound on the ping time. (Also it has the advantage - of returning immediately and not sending any packets.) - - In a few cases we might not able to estimate the route. In this case - a negative value is returned. k_nSteamNetworkingPing_Failed means - the reason was because of some networking difficulty. (Failure to - ping, etc) k_nSteamNetworkingPing_Unknown is returned if we cannot - currently answer the question for some other reason. - - Do you need to be able to do this from a backend/matchmaking server? - You are looking for the "ticketgen" library. - - - - Destroy a listen socket. All the connections that were accepting on the listen - socket are closed ungracefully. - - - - - True if unlocked - - - - - Should hold the unlock time if State is true - - - - - Gets the icon of the achievement. This can return a null image even though the image exists if the image - hasn't been downloaded by Steam yet. You can use GetIconAsync if you want to wait for the image to be - downloaded. - - - - - Gets the icon of the achievement, waits for it to load if we have to - - - - - Returns the fraction (0-1) of users who have unlocked the specified achievement, or -1 if no data - available. - - - - - Make this achievement earned - - - - - Reset this achievement to not achieved - - - - - Sent for games with enabled anti indulgence / duration control, for enabled users. - Lets the game know whether persistent rewards or XP should be granted at normal rate, half rate, or zero - rate. - - - - - appid generating playtime - - - - - is duration control applicable to user + game combination - - - - - playtime since most recent 5 hour gap in playtime, only counting up to regulatory limit of playtime, in - seconds - - - - - playtime on current calendar day - - - - - recommended progress - - - - - the name of a leaderboard - - - - - Submit your score and replace your old score even if it was better - - - - - Submit your new score, but won't replace your high score if it's lower - - - - - Attaches a piece of user generated content the user's entry on a leaderboard - - - - - Used to query for a sequential range of leaderboard entries by leaderboard Sort. - - - - - Used to retrieve leaderboard entries relative a user's entry. If there are not enough entries in the - leaderboard - before or after the user's entry, Steam will adjust the range to try to return the number of entries - requested. - For example, if the user is #1 on the leaderboard and start is set to -2, end is set to 2, Steam will - return the first - 5 entries in the leaderboard. If The current user has no entry, this will return null. - - - - - Used to retrieve all leaderboard entries for friends of the current user - - - - - Try to join this room. Will return RoomEnter.Success on success, - and anything else is a failure - - - - - Leave a lobby; this will take effect immediately on the client side - other users in the lobby will be notified by a LobbyChatUpdate_t callback - - - - - Invite another user to the lobby - will return true if the invite is successfully sent, whether or not the target responds - returns false if the local user is not connected to the Steam servers - - - - - returns the number of users in the specified lobby - - - - - Returns current members. Need to be in the lobby to see the users. - - - - - Get data associated with this lobby - - - - - Get data associated with this lobby - - - - - Removes a metadata key from the lobby - - - - - Get all data for this lobby - - - - - Gets per-user metadata for someone in this lobby - - - - - Sets per-user metadata (for the local user implicitly) - - - - - Sends a string to the chat room - - - - - Sends bytes the the chat room - this isn't exposed because there's no way to read raw bytes atm, - and I figure people can send json if they want something more advanced - - - - - Refreshes metadata for a lobby you're not necessarily in right now - you never do this for lobbies you're a member of, only if your - this will send down all the metadata associated with a lobby - this is an asynchronous call - returns false if the local user is not connected to the Steam servers - results will be returned by a LobbyDataUpdate_t callback - if the specified lobby doesn't exist, LobbyDataUpdate_t::m_bSuccess will be set to false - - - - - Max members able to join this lobby. Cannot be over 250. - Can only be set by the owner - - - - - [SteamID variant] - Allows the owner to set the game server associated with the lobby. Triggers the - Steammatchmaking.OnLobbyGameCreated event. - - - - - [IP/Port variant] - Allows the owner to set the game server associated with the lobby. Triggers the - Steammatchmaking.OnLobbyGameCreated event. - - - - - Gets the details of the lobby's game server, if set. Returns true if the lobby is - valid and has a server set, otherwise returns false. - - - - - You must be the lobby owner to set the owner - - - - - Check if the specified SteamId owns the lobby - - - - - only lobbies in the same immediate region will be returned - - - - - only lobbies in the same immediate region will be returned - - - - - only lobbies in the same immediate region will be returned - - - - - Filter by specified key/value pair; string parameters - - - - - Numerical filter where value is less than the value provided - - - - - Numerical filter where value is greater than the value provided - - - - - Numerical filter where value must be equal to the value provided - - - - - Numerical filter where value must not equal the value provided - - - - - Test key, initialize numerical filter list if necessary, then add new numerical filter - - - - - Order filtered results according to key/values nearest the provided key/value pair. - Can specify multiple near value filters; each successive filter is lower priority than the previous. - - - - - returns only lobbies with the specified number of slots available - - - - - sets how many results to return, the lower the count the faster it is to download the lobby results - - - - - Run the query, get the matching lobbies - - - - - A server query packet. - - - - - Target IP address - - - - - Target port - - - - - This data is pooled. Make a copy if you don't use it immediately. - This buffer is also quite large - so pay attention to Size. - - - - - Size of the data - - - - - Represents a RemotePlaySession from the SteamRemotePlay interface - - - - - Returns true if this session was valid when created. This will stay true even - after disconnection - so be sure to watch SteamRemotePlay.OnSessionDisconnected - - - - - Get the SteamID of the connected user - - - - - Get the name of the session client device - - - - - Get the name of the session client device - - - - - Tags a user as being visible in the screenshot - - - - - Tags a user as being visible in the screenshot - - - - - Tags a user as being visible in the screenshot - - - - - Gets the individual tags for this server - - - - - Add this server to our history list - If we're already in the history list, weill set the last played time to now - - - - - If this server responds to source engine style queries, we'll be able to get a list of rules here - - - - - Remove this server from our history list - - - - - Add this server to our favourite list - - - - - Remove this server from our favourite list - - - - - Find out the status of an asynchronous inventory result handle. - - - - - Copies the contents of a result set into a flat array. The specific contents of the result set depend on - which query which was used. - - - - - Returns the server time at which the result was generated. Compare against the value of - IClientUtils::GetServerRealTime() to determine age. - - - - - Returns true if the result belongs to the target steam ID or false if the result does not. This is - important when using DeserializeResult to verify that a remote player is not pretending to have a - different users inventory. - - - - - Destroys a result handle and frees all associated memory. - - - - - Captures the entire state of the current users Steam inventory. - - - - - Captures the state of a subset of the current users Steam inventory identified by an array of item - instance IDs. - - - - - GrantPromoItems() checks the list of promotional items for which the user may be eligible and grants the - items (one time only). - - - - - ConsumeItem() removes items from the inventory permanently. - - - - - Deprecated method. Playtime accounting is performed on the Steam servers. - - - - - Playtime credit must be consumed and turned into item drops by your game. - - - - - LoadItemDefinitions triggers the automatic load and refresh of item definitions. - - - - - Downloads leaderboard entries for an arbitrary set of users - ELeaderboardDataRequest is - k_ELeaderboardDataRequestUsers - - - - - An optional interface to use instead of deriving - - - - - The actual connection we're managing - - - - - The last received ConnectionInfo - - - - - We're trying to connect! - - - - - Client is connected. They move from connecting to Connections - - - - - The connection has been closed remotely or disconnected locally. Check data.State for details. - - - - - We started connecting to this guy - - - - - Called when the connection is fully connected and can start being communicated with - - - - - We got disconnected - - - - - Received a message - - - - - Must call Accept or Close on the connection within a second or so - - - - - Called when the connection is fully connected and can start being communicated with - - - - - Called when the connection leaves - - - - - Received a message from a connection - - - - - Used as a base to create your networking server. This creates a socket - and listens/communicates with multiple queries. - - You can override all the virtual functions to turn it into what you - want it to do. - - - - - Default behaviour is to accept every connection - - - - - Client is connected. They move from connecting to Connections - - - - - The connection has been closed remotely or disconnected locally. Check data.State for details. - - - - - Which app we're querying. Defaults to the current app. - - - - - When a new server is added, this function will get called - - - - - Called for every responsive server - - - - - A list of servers that responded. If you're only interested in servers that responded since you - last updated, then simply clear this list. - - - - - A list of servers that were in the master list but didn't respond. - - - - - Query the server list. Task result will be true when finished - - - - - - Exposes a wide range of information and actions for applications and Downloadable Content (DLC). - - - - - posted after the user gains ownership of DLC and that DLC is installed - - - - - posted after the user gains executes a Steam URL with command line or query parameters - such as steam://run/appid//-commandline/?param1=value1(and)param2=value2(and)param3=value3 etc - while the game is already running. The new params can be queried - with GetLaunchQueryParam and GetLaunchCommandLine - - - - - Checks if the active user is subscribed to the current App ID - - - - - Check if user borrowed this game via Family Sharing, If true, call GetAppOwner() to get the lender - SteamID - - - - - Checks if the license owned by the user provides low violence depots. - Low violence depots are useful for copies sold in countries that have content restrictions - - - - - Checks whether the current App ID license is for Cyber Cafes. - - - - - CChecks if the user has a VAC ban on their account - - - - - Gets the current language that the user has set. - This falls back to the Steam UI language if the user hasn't explicitly picked a language for the title. - - - - - Gets a list of the languages the current app supports. - - - - - Checks if the active user is subscribed to a specified AppId. - Only use this if you need to check ownership of another game related to yours, a demo for example. - - - - - Checks if the user owns a specific DLC and if the DLC is installed - - - - - Returns the time of the purchase of the app - - - - - Checks if the user is subscribed to the current app through a free weekend - This function will return false for users who have a retail or other type of license - Before using, please ask your Valve technical contact how to package and secure your free weekened - - - - - Returns metadata for all available DLC - - - - - Install/Uninstall control for optional DLC - - - - - Install/Uninstall control for optional DLC - - - - - Returns null if we're not on a beta branch, else the name of the branch - - - - - Allows you to force verify game content on next launch. - - If you detect the game is out-of-date(for example, by having the client detect a version mismatch with a - server), - you can call use MarkContentCorrupt to force a verify, show a message to the user, and then quit. - - - - - Gets a list of all installed depots for a given App ID in mount order - - - - - Gets the install folder for a specific AppID. - This works even if the application is not installed, based on where the game would be installed with the - default Steam library location. - - - - - The app may not actually be owned by the current user, they may have it left over from a free weekend, - etc. - - - - - Gets the Steam ID of the original owner of the current app. If it's different from the current user then - it is borrowed.. - - - - - Gets the associated launch parameter if the game is run via - steam://run/appid/?param1=value1;param2=value2;param3=value3 etc. - Parameter names starting with the character '@' are reserved for internal use and will always return an - empty string. - Parameter names starting with an underscore '_' are reserved for steam features -- they can be queried - by the game, - but it is advised that you not param names beginning with an underscore for your own features. - - - - - Gets the download progress for optional DLC. - - - - - Gets the buildid of this app, may change at any time based on backend updates to the game. - Defaults to 0 if you're not running a build downloaded from steam. - - - - - Asynchronously retrieves metadata details about a specific file in the depot manifest. - Currently provides: - - - - - Get command line if game was launched via Steam URL, e.g. steam://run/appid//command line/. - This method of passing a connect string (used when joining via rich presence, accepting an - invite, etc) is preferable to passing the connect string on the operating system command - line, which is a security risk. In order for rich presence joins to go through this - path and not be placed on the OS command line, you must set a value in your app's - configuration on Steam. Ask Valve for help with this. - - - - - Initialize the steam client. - If asyncCallbacks is false you need to call RunCallbacks manually every frame. - - - - - Checks if the current user's Steam client is connected to the Steam servers. - If it's not then no real-time services provided by the Steamworks API will be enabled. The Steam - client will automatically be trying to recreate the connection as often as possible. When the - connection is restored a SteamServersConnected_t callback will be posted. - You usually don't need to check for this yourself. All of the API calls that rely on this will - check internally. Forcefully disabling stuff when the player loses access is usually not a - very good experience for the player and you could be preventing them from accessing APIs that do not - need a live connection to Steam. - - - - - Gets the Steam ID of the account currently logged into the Steam client. This is - commonly called the 'current user', or 'local user'. - A Steam ID is a unique identifier for a Steam accounts, Steam groups, Lobbies and Chat - rooms, and used to differentiate users in all parts of the Steamworks API. - - - - - returns the local players name - guaranteed to not be NULL. - this is the same name as on the users community profile page - - - - - gets the status of the current user - - - - - returns the appID of the current process - - - - - Checks if your executable was launched through Steam and relaunches it through Steam if it wasn't - this returns true then it starts the Steam client if required and launches your game again through it, - and you should quit your process as soon as possible. This effectively runs steam://run/AppId so it - may not relaunch the exact executable that called it, as it will always relaunch from the version - installed in your Steam library folder/ - Note that during development, when not launching via Steam, this might always return true. - - - - - Called in interfaces that rely on this being initialized - - - - - Undocumented Parental Settings - - - - - Called when chat message has been received from a friend. You'll need to turn on - ListenForFriendsMessages to recieve this. (friend, msgtype, message) - - - - - called when a friends' status changes - - - - - Called when the user tries to join a game from their friends list - rich presence will have been set with the "connect" key which is set here - - - - - Posted when game overlay activates or deactivates - the game can use this to be pause or resume single player games - - - - - Called when the user tries to join a different game server from their friends list - game client should attempt to connect to specified server when this is received - - - - - Called when the user tries to join a lobby from their friends list - game client should attempt to connect to specified lobby when this is received - - - - - Callback indicating updated data about friends rich presence information - - - - - The dialog to open. Valid options are: - "friends", - "community", - "players", - "settings", - "officialgamegroup", - "stats", - "achievements". - - - - - "steamid" - Opens the overlay web browser to the specified user or groups profile. - "chat" - Opens a chat window to the specified user, or joins the group chat. - "jointrade" - Opens a window to a Steam Trading session that was started with the - ISteamEconomy/StartTrade Web API. - "stats" - Opens the overlay web browser to the specified user's stats. - "achievements" - Opens the overlay web browser to the specified user's achievements. - "friendadd" - Opens the overlay in minimal mode prompting the user to add the target user as a friend. - "friendremove" - Opens the overlay in minimal mode prompting the user to remove the target friend. - "friendrequestaccept" - Opens the overlay in minimal mode prompting the user to accept an incoming - friend invite. - "friendrequestignore" - Opens the overlay in minimal mode prompting the user to ignore an incoming - friend invite. - - - - - Activates the Steam Overlay to the Steam store page for the provided app. - - - - - Activates Steam Overlay web browser directly to the specified URL. - - - - - Activates the Steam Overlay to open the invite dialog. Invitations sent from this dialog will be for the - provided lobby. - - - - - Mark a target user as 'played with'. - NOTE: The current user must be in game with the other player for the association to work. - - - - - Requests the persona name and optionally the avatar of a specified user. - NOTE: It's a lot slower to download avatars and churns the local cache, so if you don't need avatars, - don't request them. - returns true if we're fetching the data, false if we already have it - - - - - Find a rich presence value by key for current user. Will be null if not found. - - - - - Sets a rich presence value by key for current user. - - - - - Clears all of the current user's rich presence data. - - - - - Listens for Steam friends chat messages. - You can then show these chats inline in the game. For example with a Blizzard style chat message system - or the chat system in Dota 2. - After enabling this you will receive callbacks when ever the user receives a chat message. - - - - - You shouldn't really need to call this because it get called by RunCallbacks on SteamClient - but Valve think it might be a nice idea if you call it right before you get input info - - just to make sure the info you're getting is 100% up to date. - - - - - Return a list of connected controllers. - - - - - Return an absolute path to the PNG image glyph for the provided digital action name. The current - action set in use for the controller will be used for the lookup. You should cache the result and - maintain your own list of loaded PNG assets. - - - - - - - - Undocumented Parental Settings - - - - - Call this if you're going to want to access definition information. You should be able to get - away with calling this once at the start if your game, assuming your items don't change all the time. - This will trigger OnDefinitionsUpdated at which point Definitions should be set. - - - - - Will call LoadItemDefinitions and wait until Definitions is not null - - - - - Try to find the definition that matches this definition ID. - Uses a dictionary so should be about as fast as possible. - - - - - We will try to keep this list of your items automatically up to date. - - - - - Update the list of Items[] - - - - - Get all items and return the InventoryResult - - - - - This is used to grant a specific item to the user. This should - only be used for development prototyping, from a trusted server, - or if you don't care about hacked clients granting arbitrary items. - This call can be disabled by a setting on Steamworks. - - - - - Crafting! Uses the passed items to buy the target item. - You need to have set up the appropriate exchange rules in your item - definitions. This assumes all the items passed in aren't stacked. - - - - - Crafting! Uses the passed items to buy the target item. - You need to have set up the appropriate exchange rules in your item - definitions. This assumes all the items passed in aren't stacked. - - - - - Deserializes a result set and verifies the signature bytes. - This call has a potential soft-failure mode where the Result is expired, it will - still succeed in this mode.The "expired" - result could indicate that the data may be out of date - not just due to timed - expiration( one hour ), but also because one of the items in the result set may - have been traded or consumed since the result set was generated.You could compare - the timestamp from GetResultTimestamp to ISteamUtils::GetServerRealTime to determine - how old the data is. You could simply ignore the "expired" result code and - continue as normal, or you could request the player with expired data to send - an updated result set. - You should call CheckResultSteamID on the result handle when it completes to verify - that a remote player is not pretending to have a different user's inventory. - - - - - Grant all promotional items the user is eligible for - - - - - Trigger an item drop for this user. This is for timed drops. - - - - - Trigger a promo item drop. You can call this at startup, it won't - give users multiple promo drops. - - - - - Start buying a cart load of items. This will return a positive result is the purchase has - begun. You should listen out for SteamUser.OnMicroTxnAuthorizationResponse for a success. - - - - - Functions for clients to access matchmaking services, favorites, and to operate on game lobbies - - - - - Maximum number of characters a lobby metadata key can be - - - - - Someone invited you to a lobby - - - - - You joined a lobby - - - - - You created a lobby - - - - - A game server has been associated with the lobby - - - - - The lobby metadata has changed - - - - - The lobby member metadata has changed - - - - - The lobby member joined - - - - - The lobby member left the room - - - - - The lobby member left the room - - - - - The lobby member was kicked. The 3rd param is the user that kicked them. - - - - - The lobby member was banned. The 3rd param is the user that banned them. - - - - - A chat message was recieved from a member of a lobby - - - - - Creates a new invisible lobby. Call lobby.SetPublic to take it online. - - - - - Attempts to directly join the specified lobby - - - - - Get a list of servers that are on your favorites list - - - - - Get a list of servers that you have added to your play history - - - - - Functions for clients to access matchmaking services, favorites, and to operate on game lobbies - - - - - Functions to control music playback in the steam client. - This gives games the opportunity to do things like pause the music or lower the volume, - when an important cut scene is shown, and start playing afterwards. - Nothing uses Steam Music though so this can probably get fucked - - - - - Playback status changed - - - - - Volume changed, parameter is new volume - - - - - Checks if Steam Music is enabled - - - - - true if a song is currently playing, paused, or queued up to play; otherwise false. - - - - - Gets the current status of the Steam Music player - - - - - Have the Steam Music player play the previous song. - - - - - Have the Steam Music player skip to the next song - - - - - Gets/Sets the current volume of the Steam Music player - - - - - This SteamId wants to send you a message. You should respond by calling AcceptP2PSessionWithUser - if you want to recieve their messages - - - - - Called when packets can't get through to the specified user. - All queued packets unsent at this point will be dropped, further attempts - to send will retry making the connection (but will be dropped if we fail again). - - - - - This should be called in response to a OnP2PSessionRequest - - - - - Allow or disallow P2P connects to fall back on Steam server relay if direct - connection or NAT traversal can't be established. Applies to connections - created after setting or old connections that need to reconnect. - - - - - This should be called when you're done communicating with a user, as this will - free up all of the resources allocated for the connection under-the-hood. - If the remote user tries to send data to you again, a new OnP2PSessionRequest - callback will be posted - - - - - Checks if a P2P packet is available to read, and gets the size of the message if there is one. - - - - - Reads in a packet that has been sent from another user via SendP2PPacket.. - - - - - Reads in a packet that has been sent from another user via SendP2PPacket.. - - - - - Reads in a packet that has been sent from another user via SendP2PPacket.. - - - - - Sends a P2P packet to the specified user. - This is a session-less API which automatically establishes NAT-traversing or Steam relay server - connections. - NOTE: The first packet send may be delayed as the NAT-traversal code runs. - - - - - Sends a P2P packet to the specified user. - This is a session-less API which automatically establishes NAT-traversing or Steam relay server - connections. - NOTE: The first packet send may be delayed as the NAT-traversal code runs. - - - - - Creates a "server" socket that listens for clients to connect to by calling - Connect, over ordinary UDP (IPv4 or IPv6) - - To use this derive a class from SocketManager and override as much as you want. - - - - - - Creates a "server" socket that listens for clients to connect to by calling - Connect, over ordinary UDP (IPv4 or IPv6). - - To use this you should pass a class that inherits ISocketManager. You can use - SocketManager to get connections and send messages, but the ISocketManager class - will received all the appropriate callbacks. - - - - - - Connect to a socket created via - CreateListenSocketIP - - - - - Connect to a socket created via - CreateListenSocketIP - - - - - Creates a server that will be relayed via Valve's network (hiding the IP and improving ping) - - - - - Connect to a relay server - - - - - Undocumented Parental Settings - - - - - A function to receive debug network information on. This will do nothing - unless you set DebugLevel to something other than None. - - You should set this to an appropriate level instead of setting it to the highest - and then filtering it by hand because a lot of energy is used by creating the strings - and your frame rate will tank and you won't know why. - - - - - The latest available status gathered from the SteamRelayNetworkStatus callback - - - - - If you know that you are going to be using the relay network (for example, - because you anticipate making P2P connections), call this to initialize the - relay network. If you do not call this, the initialization will - be delayed until the first time you use a feature that requires access - to the relay network, which will delay that first access. - - You can also call this to force a retry if the previous attempt has failed. - Performing any action that requires access to the relay network will also - trigger a retry, and so calling this function is never strictly necessary, - but it can be useful to call it a program launch time, if access to the - relay network is anticipated. - - Use GetRelayNetworkStatus or listen for SteamRelayNetworkStatus_t - callbacks to know when initialization has completed. - Typically initialization completes in a few seconds. - - Note: dedicated servers hosted in known data centers do *not* need - to call this, since they do not make routing decisions. However, if - the dedicated server will be using P2P functionality, it will act as - a "client" and this should be called. - - - - - Return location info for the current host. - - It takes a few seconds to initialize access to the relay network. If - you call this very soon after startup the data may not be available yet. - - This always return the most up-to-date information we have available - right now, even if we are in the middle of re-calculating ping times. - - - - - Same as PingLocation.EstimatePingTo, but assumes that one location is the local host. - This is a bit faster, especially if you need to calculate a bunch of - these in a loop to find the fastest one. - - - - - If you need ping information straight away, wait on this. It will return - immediately if you already have up to date ping data - - - - - [0 - 100] - Randomly discard N pct of packets - - - - - [0 - 100] - Randomly discard N pct of packets - - - - - Delay all packets by N ms - - - - - Delay all packets by N ms - - - - - Timeout value (in ms) to use when first connecting - - - - - Timeout value (in ms) to use after connection is established - - - - - Upper limit of buffered pending bytes to be sent. - If this is reached SendMessage will return LimitExceeded. - Default is 524288 bytes (512k) - - - - - Get Debug Information via OnDebugOutput event - - Except when debugging, you should only use NetDebugOutput.Msg - or NetDebugOutput.Warning. For best performance, do NOT - request a high detail level and then filter out messages in the callback. - - This incurs all of the expense of formatting the messages, which are then discarded. - Setting a high priority value (low numeric value) here allows the library to avoid - doing this work. - - - - - So we can remember and provide a Get for DebugLEvel - - - - - We need to keep the delegate around until it's not used anymore - - - - - This can be called from other threads - so we're going to queue these up and process them in a safe - place. - - - - - Called regularly from the Dispatch loop so we can provide a timely - stream of messages. - - - - - Undocumented Parental Settings - - - - - Parental Settings Changed - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This API can be used to selectively advertise your multiplayer game session in a Steam chat room group. - Tell Steam the number of player spots that are available for your party, and a join-game string, and it - will show a beacon in the selected group and allow that many users to “follow” the beacon to your party. - Adjust the number of open slots if other players join through alternate matchmaking methods. - - - - - The list of possible Party beacon locations has changed - - - - - The list of active beacons may have changed - - - - - Functions that provide information about Steam Remote Play sessions, streaming your game content to - another computer or to a Steam Link app or hardware. - - - - - Called when a session is connected - - - - - Called when a session becomes disconnected - - - - - Get the number of currently connected Steam Remote Play sessions - - - - - Get the currently connected Steam Remote Play session ID at the specified index. - IsValid will return false if it's out of bounds - - - - - Invite a friend to Remote Play Together - This returns false if the invite can't be sent - - - - - Undocumented Parental Settings - - - - - Creates a new file, writes the bytes to the file, and then closes the file. - If the target file already exists, it is overwritten - - - - - Opens a binary file, reads the contents of the file into a byte array, and then closes the file. - - - - - Checks whether the specified file exists. - - - - - Checks if a specific file is persisted in the steam cloud. - - - - - Gets the specified file's last modified date/time. - - - - - Gets the specified files size in bytes. 0 if not exists. - - - - - Deletes the file from remote storage, but leaves it on the local disk and remains accessible from the - API. - - - - - Deletes a file from the local disk, and propagates that delete to the cloud. - - - - - Number of bytes total - - - - - Number of bytes used - - - - - Number of bytes remaining until your quota is used - - - - - returns true if IsCloudEnabledForAccount AND IsCloudEnabledForApp - - - - - Checks if the account wide Steam Cloud setting is enabled for this user - or if they disabled it in the Settings->Cloud dialog. - - - - - Checks if the per game Steam Cloud setting is enabled for this user - or if they disabled it in the Game Properties->Update dialog. - - This must only ever be set as the direct result of the user explicitly - requesting that it's enabled or not. This is typically accomplished with - a checkbox within your in-game options - - - - - Gets the total number of local files synchronized by Steam Cloud. - - - - - Get a list of filenames synchronized by Steam Cloud - - - - - Undocumented Parental Settings - - - - - A screenshot has been requested by the user from the Steam screenshot hotkey. - This will only be called if Hooked is true, in which case Steam - will not take the screenshot itself. - - - - - A screenshot successfully written or otherwise added to the library and can now be tagged. - - - - - A screenshot attempt failed - - - - - Writes a screenshot to the user's screenshot library given the raw image data, which must be in RGB - format. - The return value is a handle that is valid for the duration of the game process and can be used to apply - tags. - - - - - Adds a screenshot to the user's screenshot library from disk. If a thumbnail is provided, it must be 200 - pixels wide and the same aspect ratio - as the screenshot, otherwise a thumbnail will be generated if the user uploads the screenshot. The - screenshots must be in either JPEG or TGA format. - The return value is a handle that is valid for the duration of the game process and can be used to apply - tags. - JPEG, TGA, and PNG formats are supported. - - - - - Causes the Steam overlay to take a screenshot. - If screenshots are being hooked by the game then a - ScreenshotRequested callback is sent back to the game instead. - - - - - Toggles whether the overlay handles screenshots when the user presses the screenshot hotkey, or if the - game handles them. - Hooking is disabled by default, and only ever enabled if you do so with this function. - If the hooking is enabled, then the ScreenshotRequested_t callback will be sent if the user presses the - hotkey or - when TriggerScreenshot is called, and then the game is expected to call WriteScreenshot or - AddScreenshotToLibrary in response. - - - - - Provides the core of the Steam Game Servers API - - - - - User has been authed or rejected - - - - - Called when a connections to the Steam back-end has been established. - This means the server now is logged on and has a working connection to the Steam master server. - - - - - This will occur periodically if the Steam client is not connected, and has failed when retrying to - establish a connection (result, stilltrying) - - - - - Disconnected from Steam - - - - - Initialize the steam server. - If asyncCallbacks is false you need to call RunCallbacks manually every frame. - - - - - Run the callbacks. This is also called in Async callbacks. - - - - - Sets whether this should be marked as a dedicated server. - If not, it is assumed to be a listen server. - - - - - Gets or sets the current MaxPlayers. - This doesn't enforce any kind of limit, it just updates the master server. - - - - - Gets or sets the current BotCount. - This doesn't enforce any kind of limit, it just updates the master server. - - - - - Gets or sets the current Map Name. - - - - - Gets or sets the current ModDir - - - - - Gets the current product - - - - - Gets or sets the current Product - - - - - Gets or sets the current ServerName - - - - - Set whether the server should report itself as passworded - - - - - Gets or sets the current GameTags. This is a comma seperated list of tags for this server. - When querying the server list you can filter by these tags. - - - - - Log onto Steam anonymously. - - - - - Log onto Steam anonymously. - - - - - Returns true if the server is connected and registered with the Steam master server - You should have called LogOnAnonymous etc on startup. - - - - - To the best of its ability this tries to get the server's - current public ip address. Be aware that this is likely to return - null for the first few seconds after initialization. - - - - - Enable or disable heartbeats, which are sent regularly to the master server. - Enabled by default. - - - - - Set heartbeat interval, if automatic heartbeats are enabled. - You can leave this at the default. - - - - - Force send a heartbeat to the master server instead of waiting - for the next automatic update (if you've left them enabled) - - - - - Update this connected player's information. You should really call this - any time a player's name or score changes. This keeps the information shown - to server queries up to date. - - - - - Sets a Key Value. These can be anything you like, and are accessible - when querying servers from the server list. - - Information describing gamemodes are common here. - - - - - Remove all key values - - - - - Start authorizing a ticket. This user isn't authorized yet. Wait for a call to OnAuthChange. - - - - - Forget this guy. They're no longer in the game. - - - - - If true, Steam wants to send a packet. You should respond by sending - this packet in an unconnected way to the returned Address and Port. - - Packet to send. The Data passed is pooled - so use it immediately. - True if we want to send a packet - - - - We have received a server query on our game port. Pass it to Steam to handle. - - - - - We have received a server query on our game port. Pass it to Steam to handle. - - - - - Does the user own this app (which could be DLC) - - - - - Downloads stats for the user - If the user has no stats will return fail - these stats will only be auto-updated for clients playing on the server - - - - - Set the named stat for this user. Setting stats should follow the rules - you defined in Steamworks. - - - - - Set the named stat for this user. Setting stats should follow the rules - you defined in Steamworks. - - - - - Get the named stat for this user. If getting the stat failed, will return - defaultValue. You should have called Refresh for this userid - which downloads - the stats from the backend. If you didn't call it this will always return defaultValue. - - - - - Get the named stat for this user. If getting the stat failed, will return - defaultValue. You should have called Refresh for this userid - which downloads - the stats from the backend. If you didn't call it this will always return defaultValue. - - - - - Unlocks the specified achievement for the specified user. Must have called Refresh on a steamid first. - Remember to use Commit after use. - - - - - Resets the unlock status of an achievement for the specified user. Must have called Refresh on a steamid - first. - Remember to use Commit after use. - - - - - Return true if available, exists and unlocked - - - - - Once you've set a stat change on a user you need to commit your changes. - You can do that using this function. The callback will let you know if - your action succeeded, but most of the time you can fire and forget. - - - - - Functions for accessing and manipulating Steam user information. - This is also where the APIs for Steam Voice are exposed. - - - - - Posted after Download call - - - - - Start downloading this item. You'll get notified of completion via OnDownloadItemResult. - - The ID of the file you want to download - If true this should go straight to the top of the download list - true if nothing went wrong and the download is started - - - - Will attempt to download this item asyncronously - allowing you to instantly react to its installation - - The ID of the file you want to download - An optional callback - Allows you to send a message to cancel the download anywhere during the process - How often to call the progress function - true if downloaded and installed correctly - - - - Utility function to fetch a single item. Internally this uses Ugc.FileQuery - - which you can use to query multiple items if you need to. - - - - - Functions for accessing and manipulating Steam user information. - This is also where the APIs for Steam Voice are exposed. - - - - - Called when a connections to the Steam back-end has been established. - This means the Steam client now has a working connection to the Steam servers. - Usually this will have occurred before the game has launched, and should only be seen if the - user has dropped connection due to a networking issue or a Steam server update. - - - - - Called when a connection attempt has failed. - This will occur periodically if the Steam client is not connected, - and has failed when retrying to establish a connection. - - - - - Called if the client has lost connection to the Steam servers. - Real-time services will be disabled until a matching OnSteamServersConnected has been posted. - - - - - Sent by the Steam server to the client telling it to disconnect from the specified game server, - which it may be in the process of or already connected to. - The game client should immediately disconnect upon receiving this message. - This can usually occur if the user doesn't have rights to play on the game server. - - - - - Called whenever the users licenses (owned packages) changes. - - - - - Called when an auth ticket has been validated. - The first parameter is the steamid of this user - The second is the Steam ID that owns the game, this will be different from the first - if the game is being borrowed via Steam Family Sharing - - - - - Used internally for GetAuthSessionTicketAsync - - - - - Called when a user has responded to a microtransaction authorization request. - ( appid, orderid, user authorized ) - - - - - Sent to your game in response to a steam://gamewebcallback/ command from a user clicking a link in the - Steam overlay browser. - You can use this to add support for external site signups where you want to pop back into the browser - after some web page - signup sequence, and optionally get back some detail about that. - - - - - Sent for games with enabled anti indulgence / duration control, for enabled users. - Lets the game know whether persistent rewards or XP should be granted at normal rate, - half rate, or zero rate. - - - - - Starts/Stops voice recording. - Once started, use GetAvailableVoice and GetVoice to get the data, and then call StopVoiceRecording - when the user has released their push-to-talk hotkey or the game session has completed. - - - - - Returns true if we have voice data waiting to be read - - - - - Reads the voice data and returns the number of bytes written. - The compressed data can be transmitted by your application and decoded back into raw audio data using - DecompressVoice on the other side. The compressed data provided is in an arbitrary format and is not - meant to be played directly. - This should be called once per frame, and at worst no more than four times a second to keep the - microphone input delay as low as - possible. Calling this any less may result in gaps in the returned stream. - - - - - Reads the voice data and returns the bytes. You should obviously ideally be using - ReadVoiceData because it won't be creating a new byte array every call. But this - makes it easier to get it working, so let the babies have their bottle. - - - - - Decodes the compressed voice data returned by GetVoice. - The output data is raw single-channel 16-bit PCM audio.The decoder supports any sample rate from 11025 - to 48000. - - - - - Retrieve a authentication ticket to be sent to the entity who wishes to authenticate you. - - - - - Retrieve a authentication ticket to be sent to the entity who wishes to authenticate you. - This waits for a positive response from the backend before returning the ticket. This means - the ticket is definitely ready to go as soon as it returns. Will return null if the callback - times out or returns negatively. - - - - - Checks if the current users looks like they are behind a NAT device. - This is only valid if the user is connected to the Steam servers and may not catch all forms of NAT. - - - - - Gets the Steam level of the user, as shown on their Steam community profile. - - - - - Requests a URL which authenticates an in-game browser for store check-out, and then redirects to the - specified URL. - As long as the in-game browser accepts and handles session cookies, Steam microtransaction checkout - pages will automatically recognize the user instead of presenting a login page. - NOTE: The URL has a very short lifetime to prevent history-snooping attacks, so you should only call - this API when you are about to launch the browser, or else immediately navigate to the result URL using - a hidden browser window. - NOTE: The resulting authorization cookie has an expiration time of one day, so it would be a good idea - to request and visit a new auth URL every 12 hours. - - - - - Checks whether the current user has verified their phone number. - - - - - Checks whether the current user has Steam Guard two factor authentication enabled on their account. - - - - - Checks whether the user's phone number is used to uniquely identify them. - - - - - Checks whether the current user's phone number is awaiting (re)verification. - - - - - Requests an application ticket encrypted with the secret "encrypted app ticket key". - The encryption key can be obtained from the Encrypted App Ticket Key page on the App Admin for your app. - There can only be one call pending, and this call is subject to a 60 second rate limit. - If you get a null result from this it's probably because you're calling it too often. - This can fail if you don't have an encrypted ticket set for your app here - https://partner.steamgames.com/apps/sdkauth/ - - - - - Requests an application ticket encrypted with the secret "encrypted app ticket key". - The encryption key can be obtained from the Encrypted App Ticket Key page on the App Admin for your app. - There can only be one call pending, and this call is subject to a 60 second rate limit. - This can fail if you don't have an encrypted ticket set for your app here - https://partner.steamgames.com/apps/sdkauth/ - - - - - Get anti indulgence / duration control - - - - - called when the achivement icon is loaded - - - - - called when the latests stats and achievements have been received - from the server - - - - - result of a request to store the user stats for a game - - - - - result of a request to store the achievements for a game, or an - "indicate progress" call. If both m_nCurProgress and m_nMaxProgress - are zero, that means the achievement has been fully unlocked - - - - - Callback indicating that a user's stats have been unloaded - - - - - Get the available achievements - - - - - Show the user a pop-up notification with the current progress toward an achievement. - Will return false if RequestCurrentStats has not completed and successfully returned - its callback, if the achievement doesn't exist/has unpublished changes in the app's - Steamworks Admin page, or if the achievement is unlocked. - - - - - Tries to get the number of players currently playing this game. - Or -1 if failed. - - - - - Send the changed stats and achievements data to the server for permanent storage. - If this fails then nothing is sent to the server. It's advisable to keep trying until the call is - successful. - This call can be rate limited. Call frequency should be on the order of minutes, rather than seconds.You - should only be calling this during major state changes such as the end of a round, the map changing, or - the user leaving a server. This call is required to display the achievement unlock notification dialog - though, so if you have called SetAchievement then it's advisable to call this soon after that. - If you have stats or achievements that you have saved locally but haven't uploaded with this function - when your application process ends then this function will automatically be called. - You can find additional debug information written to the %steam_install%\logs\stats_log.txt file. - This function returns true upon success if : - RequestCurrentStats has completed and successfully returned its callback AND - the current game has stats associated with it in the Steamworks Partner backend, and those stats are - published. - - - - - Asynchronously request the user's current stats and achievements from the server. - You must always call this first to get the initial status of stats and achievements. - Only after the resulting callback comes back can you start calling the rest of the stats - and achievement functions for the current user. - - - - - Asynchronously fetches global stats data, which is available for stats marked as - "aggregated" in the App Admin panel of the Steamworks website. - You must have called RequestCurrentStats and it needs to return successfully via - its callback prior to calling this. - - How many days of day-by-day history to retrieve in addition to the overall totals. The - limit is 60. - - OK indicates success, InvalidState means you need to call RequestCurrentStats first, Fail means the - remote call failed - - - - - Gets a leaderboard by name, it will create it if it's not yet created. - Leaderboards created with this function will not automatically show up in the Steam Community. - You must manually set the Community Name field in the App Admin panel of the Steamworks website. - As such it's generally recommended to prefer creating the leaderboards in the App Admin panel on - the Steamworks website and using FindLeaderboard unless you're expected to have a large amount of - dynamically created leaderboards. - - - - - Adds this amount to the named stat. Internally this calls Get() and adds - to that value. Steam doesn't provide a mechanism for atomically increasing - stats like this, this functionality is added here as a convenience. - - - - - Adds this amount to the named stat. Internally this calls Get() and adds - to that value. Steam doesn't provide a mechanism for atomically increasing - stats like this, this functionality is added here as a convenience. - - - - - Set a stat value. This will automatically call StoreStats() after a successful call - unless you pass false as the last argument. - - - - - Set a stat value. This will automatically call StoreStats() after a successful call - unless you pass false as the last argument. - - - - - Get a Int stat value - - - - - Get a float stat value - - - - - Practically wipes the slate clean for this user. If includeAchievements is true, will wipe - any achievements too. - - - - - - Interface which provides access to a range of miscellaneous utility functions - - - - - The country of the user changed - - - - - Fired when running on a laptop and less than 10 minutes of battery is left, fires then every minute - The parameter is the number of minutes left - - - - - Called when Steam wants to shutdown - - - - - Big Picture gamepad text input has been closed. Parameter is true if text was submitted, false if - cancelled etc. - - - - - Returns the number of seconds since the application was active - - - - - Returns the number of seconds since the user last moved the mouse etc - - - - - Steam server time. Number of seconds since January 1, 1970, GMT (i.e unix time) - - - - - returns the 2 digit ISO 3166-1-alpha-2 format country code this client is running in (as looked up via - an IP-to-location database) - e.g "US" or "UK". - - - - - returns true if the image exists, and the buffer was successfully filled out - results are returned in RGBA format - the destination buffer size should be 4 * height * width * sizeof(char) - - - - - returns the image in RGBA format - - - - - Returns true if we're using a battery (ie, a laptop not plugged in) - - - - - Returns battery power [0-1] - - - - - Sets the position where the overlay instance for the currently calling game should show notifications. - This position is per-game and if this function is called from outside of a game context it will do - nothing. - - - - - Returns true if the overlay is running and the user can access it. The overlay process could take a few - seconds to - start and hook the game process, so this function will initially return false while the overlay is - loading. - - - - - Normally this call is unneeded if your game has a constantly running frame loop that calls the - D3D Present API, or OGL SwapBuffers API every frame. - - However, if you have a game that only refreshes the screen on an event driven basis then that can break - the overlay, as it uses your Present/SwapBuffers calls to drive it's internal frame loop and it may also - need to Present() to the screen any time an even needing a notification happens or when the overlay is - brought up over the game by a user. You can use this API to ask the overlay if it currently need a - present - in that case, and then you can check for this periodically (roughly 33hz is desirable) and make sure you - refresh the screen with Present or SwapBuffers to allow the overlay to do it's work. - - - - - Asynchronous call to check if an executable file has been signed using the public key set on the signing - tab - of the partner site, for example to refuse to load modified executable files. - - - - - Activates the Big Picture text input dialog which only supports gamepad input - - - - - Returns previously entered text - - - - - returns the language the steam client is running in, you probably want - Apps.CurrentGameLanguage instead, this is for very special usage cases - - - - - returns true if Steam itself is running in VR mode - - - - - Sets the inset of the overlay notification from the corner specified by SetOverlayNotificationPosition - - - - - returns true if Steam and the Steam Overlay are running in Big Picture mode - Games much be launched through the Steam client to enable the Big Picture overlay. During development, - a game can be added as a non-steam game to the developers library to test this feature - - - - - ask SteamUI to create and render its OpenVR dashboard - - - - - Set whether the HMD content will be streamed via Steam In-Home Streaming - If this is set to true, then the scene in the HMD headset will be streamed, and remote input will not be - allowed. - If this is set to false, then the application window will be streamed instead, and remote input will be - allowed. - The default is true unless "VRHeadsetStreaming" "0" is in the extended appinfo for a game. - (this is useful for games that have asymmetric multiplayer gameplay) - - - - - Returns whether this steam client is a Steam China specific client, vs the global client - - - - - Undocumented Parental Settings - - - - - Return true if currently using Steam's live broadcasting - - - - - If we're broadcasting, will return the number of live viewers - - - - - Reconfigure the controller to use the specified action set (ie 'Menu', 'Walk' or 'Drive') - This is cheap, and can be safely called repeatedly. It's often easier to repeatedly call it in - our state loops, instead of trying to place it in all of your state transitions. - - - - - Returns the current state of the supplied digital game action - - - - - Returns the current state of these supplied analog game action - - - - - Returns true if this is the local user - - - - - Return true if this is a friend - - - - - Returns true if you have this user blocked - - - - - Return true if this user is playing the game we're running - - - - - Returns true if this friend is online - - - - - Sometimes we don't know the user's name. This will wait until we have - downloaded the information on this user. - - - - - Returns true if this friend is marked as away - - - - - Returns true if this friend is marked as busy - - - - - Returns true if this friend is marked as snoozing - - - - - Invite this friend to the game that we are playing - - - - - Sends a message to a Steam friend. Returns true if success - - - - - Tries to get download the latest user stats - - True if successful, False if failure - - - - Gets a user stat. Must call RequestUserStats first. - - The name of the stat you want to get - Will return this value if not available - The value, or defult if not available - - - - Gets a user stat. Must call RequestUserStats first. - - The name of the stat you want to get - Will return this value if not available - The value, or defult if not available - - - - Gets a user achievement state. Must call RequestUserStats first. - - The name of the achievement you want to get - Will return this value if not available - The value, or defult if not available - - - - Gets a the time this achievement was unlocked. - - The name of the achievement you want to get - The time unlocked. If it wasn't unlocked, or you haven't downloaded the stats yet - will return - DateTime.MinValue - - - - - Shortcut to call GetProperty( "name" ) - - - - - Shortcut to call GetProperty( "description" ) - - - - - Shortcut to call GetProperty( "icon_url" ) - - - - - Shortcut to call GetProperty( "icon_url_large" ) - - - - - Shortcut to call GetProperty( "price_category" ) - - - - - Shortcut to call GetProperty( "type" ) - - - - - Returns true if this is an item that generates an item, rather - than something that is actual an item - - - - - Shortcut to call GetProperty( "exchange" ) - - - - - Get a list of exchanges that are available to make this item - - - - - Shortcut to call GetBoolProperty( "marketable" ) - - - - - Shortcut to call GetBoolProperty( "tradable" ) - - - - - Gets the property timestamp - - - - - Gets the property modified - - - - - Get a specific property by name - - - - - Read a raw property from the definition schema - - - - - Read a raw property from the definition schema - - - - - Gets a list of all properties on this item - - - - - Returns the price of this item in the local currency (SteamInventory.Currency) - - - - - If the price has been discounted, LocalPrice will differ from LocalBasePrice - (assumed, this isn't documented) - - - - - Return a list of recepies that contain this item - - - - - Only available if the result set was created with the getproperties - - - - - This item is account-locked and cannot be traded or given away. - This is an item status flag which is permanently attached to specific item instances - - - - - The item has been destroyed, traded away, expired, or otherwise invalidated. - This is an action confirmation flag which is only set one time, as part of a result set. - - - - - The item quantity has been decreased by 1 via ConsumeItem API. - This is an action confirmation flag which is only set one time, as part of a result set. - - - - - Consumes items from a user's inventory. If the quantity of the given item goes to zero, it is - permanently removed. - Once an item is removed it cannot be recovered.This is not for the faint of heart - if your game - implements item removal at all, - a high-friction UI confirmation process is highly recommended.ConsumeItem can be restricted to certain - item definitions or fully - blocked via the Steamworks website to minimize support/abuse issues such as the classic "my brother - borrowed my laptop and deleted all of my rare items". - - - - - Split stack into two items - - - - - Add x units of the target item to this item - - - - - Will try to return the date that this item was aquired. You need to have for the items - with their properties for this to work. - - - - - Tries to get the origin property. Need properties for this to work. - Will return a string like "market" - - - - - Small utility class to describe an item with a quantity - - - - - A structured description of an item exchange - - - - - The definition ID of the ingredient. - - - - - If we don't know about this item definition this might be null. - In which case, DefinitionId should still hold the correct id. - - - - - The amount of this item needed. Generally this will be 1. - - - - - The item that this will create. - - - - - The items, with quantity required to create this item. - - - - - Checks whether an inventory result handle belongs to the specified Steam ID. - This is important when using Deserialize, to verify that a remote player is not pretending to have a - different user's inventory - - - - - Serialized result sets contain a short signature which can't be forged or replayed across different game - sessions. - A result set can be serialized on the local client, transmitted to other players via your game - networking, and - deserialized by the remote players.This is a secure way of preventing hackers from lying about posessing - rare/high-value items. Serializes a result set with signature bytes to an output buffer.The size of a - serialized - result depends on the number items which are being serialized.When securely transmitting items to other - players, - it is recommended to use GetItemsByID first to create a minimal result set. - Results have a built-in timestamp which will be considered "expired" after an hour has elapsed.See - DeserializeResult - for expiration handling. - - - - - Creator of the beacon - - - - - Creator of the beacon - - - - - Will attempt to join the party. If successful will return a connection string. - If failed, will return null - - - - - When a user follows your beacon, Steam will reserve one of the open party slots for them, and send your - game a ReservationNotification callback. - When that user joins your party, call OnReservationCompleted to notify Steam that the user has joined - successfully - - - - - To cancel a reservation (due to timeout or user input), call this. - Steam will open a new reservation slot. - Note: The user may already be in-flight to your game, so it's possible they will still connect and try - to join your party. - - - - - Turn off the beacon - - - - - Used to set up the server. - The variables in here are all required to be set, and can't be changed once the server is created. - - - - - The version string is usually in the form x.x.x.x, and is used by the master server to detect when the - server is out of date. - If you go into the dedicated server tab on steamworks you'll be able to server the latest version. If - this version number is - less than that latest version then your server won't show. - - - - - This should be the same directory game where gets installed into. Just the folder name, not the whole - path. I.e. "Rust", "Garrysmod". - - - - - The game description. Setting this to the full name of your game is recommended. - - - - - Is a dedicated server - - - - - Set the Steam quert port - - - - - If you pass MASTERSERVERUPDATERPORT_USEGAMESOCKETSHARE into usQueryPort, then it causes the game server - API to use - "GameSocketShare" mode, which means that the game is responsible for sending and receiving UDP packets - for the master - server updater. - - More info about this here: https://partner.steamgames.com/doc/api/ISteamGameServer#HandleIncomingPacket - - - - - Create a Normal Workshop item that can be subscribed to - - - - - Workshop item that is meant to be voted on for the purpose of selling in-game - - - - - https://partner.steamgames.com/doc/features/workshop/implementation#Legal - - - - - The actual ID of this file - - - - - The given title of this item - - - - - The description of this item, in your local language if available - - - - - A list of tags for this item, all lowercase - - - - - App Id of the app that created this item - - - - - App Id of the app that will consume this item. - - - - - User who created this content - - - - - The bayesian average for up votes / total votes, between [0,1] - - - - - Time when the published item was created - - - - - Time when the published item was last updated - - - - - True if this is publically visible - - - - - True if this item is only visible by friends of the creator - - - - - True if this is only visible to the creator - - - - - True if this item has been banned - - - - - Whether the developer of this app has specifically flagged this item as accepted in the Workshop - - - - - The number of upvotes of this item - - - - - The number of downvotes of this item - - - - - Start downloading this item. - If this returns false the item isn't getting downloaded. - - - - - If we're downloading, how big the total download is - - - - - If we're downloading, how much we've downloaded - - - - - If we're installed, how big is the install - - - - - If we're downloading our current progress as a delta betwen 0-1 - - - - - A case insensitive check for tag - - - - - Allows the user to subscribe to this item - - - - - Allows the user to subscribe to download this item asyncronously - If CancellationToken is default then there is 60 seconds timeout - Progress will be set to 0-1 - - - - - Allows the user to unsubscribe from this item - - - - - Adds item to user favorite list - - - - - Removes item from user favorite list - - - - - Allows the user to rate a workshop item up or down. - - - - - Gets the current users vote on the item - - - - - Return a URL to view this item online - - - - - The URl to view this item's changelog - - - - - The URL to view the comments on this item - - - - - The URL to discuss this item - - - - - The URL to view this items stats online - - - - - The URL to the preview image for this item - - - - - Edit this item - - - - - Found items must have at least one of the defined tags - - - - - Found items must have all defined tags - - - - - Returns the current Unix Epoch - - - - - Convert an epoch to a datetime - - - - - Convert a DateTime to a unix time - - - - - Returns a buffer. This will get returned and reused later on. - - - - - Prevent unity from stripping shit we depend on - https://docs.unity3d.com/Manual/ManagedCodeStripping.html - - - - diff --git a/Assets/Packages/Facepunch/Facepunch.Steamworks.Win64.xml.meta b/Assets/Packages/Facepunch/Facepunch.Steamworks.Win64.xml.meta deleted file mode 100644 index bf80f5b..0000000 --- a/Assets/Packages/Facepunch/Facepunch.Steamworks.Win64.xml.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: ea452b431085aed499c01339e89fce8b -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Packages/Facepunch/redistributable_bin.meta b/Assets/Packages/Facepunch/redistributable_bin.meta deleted file mode 100644 index c544672..0000000 --- a/Assets/Packages/Facepunch/redistributable_bin.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 9eb418beccc204946862a1a8f099ec39 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Packages/Facepunch/redistributable_bin/linux32.meta b/Assets/Packages/Facepunch/redistributable_bin/linux32.meta deleted file mode 100644 index de7c76e..0000000 --- a/Assets/Packages/Facepunch/redistributable_bin/linux32.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: ce9561d2de976e74684ab44c5fec0813 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Packages/Facepunch/redistributable_bin/linux32/libsteam_api.so b/Assets/Packages/Facepunch/redistributable_bin/linux32/libsteam_api.so deleted file mode 100644 index 7c42e1675f9754b44c516ce97db0fea7d6da0f5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 403896 zcmbSU2V4_L7hggVd+b;*_O96LX(*y7NCfN!0tAQ#5)-Ot3HC1buGqU`*Rx?cJx}k% zUeCkNvp3Z9&hGc0%?z`IQ115kd(6(xn>TM>o7tJ!Fs6%-mz|xRz%F~iULZMzyPePy zX{}n0Vo^&$Avg>5@VBa1&hSa9a�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%0Ag8`O3XCS%HX`hP+la=gaE+ddPOQY6g)Yv!N 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%0DX{P-2-YRs=s@&kS)9=nwK4P8G{a?> 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 diff --git a/Assets/Packages/Facepunch/redistributable_bin/linux32/libsteam_api.so.meta b/Assets/Packages/Facepunch/redistributable_bin/linux32/libsteam_api.so.meta deleted file mode 100644 index 7760b89..0000000 --- a/Assets/Packages/Facepunch/redistributable_bin/linux32/libsteam_api.so.meta +++ /dev/null @@ -1,89 +0,0 @@ -fileFormatVersion: 2 -guid: fd99b19e202e95a44ace17e10bac2feb -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 0 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - '': Any - second: - enabled: 0 - settings: - Exclude Editor: 1 - Exclude Linux: 1 - Exclude Linux64: 1 - Exclude LinuxUniversal: 1 - Exclude OSXUniversal: 1 - Exclude Win: 1 - Exclude Win64: 1 - - first: - Any: - second: - enabled: 0 - settings: {} - - first: - Editor: Editor - second: - enabled: 0 - settings: - CPU: AnyCPU - DefaultValueInitialized: true - OS: AnyOS - - first: - Facebook: Win - second: - enabled: 0 - settings: - CPU: AnyCPU - - first: - Facebook: Win64 - second: - enabled: 0 - settings: - CPU: AnyCPU - - first: - Standalone: Linux - second: - enabled: 0 - settings: - CPU: None - - first: - Standalone: Linux64 - second: - enabled: 0 - settings: - CPU: None - - first: - Standalone: LinuxUniversal - second: - enabled: 0 - settings: - CPU: None - - first: - Standalone: OSXUniversal - second: - enabled: 0 - settings: - CPU: None - - first: - Standalone: Win - second: - enabled: 0 - settings: - CPU: AnyCPU - - first: - Standalone: Win64 - second: - enabled: 0 - settings: - CPU: AnyCPU - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Packages/Facepunch/redistributable_bin/linux64.meta b/Assets/Packages/Facepunch/redistributable_bin/linux64.meta deleted file mode 100644 index 2c7346c..0000000 --- a/Assets/Packages/Facepunch/redistributable_bin/linux64.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 2b478e6d3d1ef9848b43453c8e68cd0d -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Packages/Facepunch/redistributable_bin/linux64/libsteam_api.so b/Assets/Packages/Facepunch/redistributable_bin/linux64/libsteam_api.so deleted file mode 100644 index 33762a726e93c776de33f892ffa85e00a9fc7289..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 398662 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⊥qb(yM!= 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

mYym}_Kx4_#}r3itdPFK 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 z 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Ð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 diff --git a/Assets/Packages/Facepunch/redistributable_bin/osx/libsteam_api.bundle.meta b/Assets/Packages/Facepunch/redistributable_bin/osx/libsteam_api.bundle.meta deleted file mode 100644 index c0be5c9..0000000 --- a/Assets/Packages/Facepunch/redistributable_bin/osx/libsteam_api.bundle.meta +++ /dev/null @@ -1,32 +0,0 @@ -fileFormatVersion: 2 -guid: 7d6647fb9d80f5b4f9b2ff1378756bee -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 0 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - Any: - second: - enabled: 0 - settings: {} - - first: - Editor: Editor - second: - enabled: 1 - settings: - DefaultValueInitialized: true - - first: - Standalone: OSXUniversal - second: - enabled: 1 - settings: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Packages/Facepunch/redistributable_bin/steam_api.dll b/Assets/Packages/Facepunch/redistributable_bin/steam_api.dll deleted file mode 100644 index 6e0f4401b150b532be3928426c030d2fe178d5f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 237856 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

Jd9okGLqN9x=RMJtAJq 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%0A@lp= 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

_K*<56_RDN+TDEFi?Z;3VSv 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 diff --git a/Assets/Packages/Facepunch/redistributable_bin/win64/steam_api64.dll.meta b/Assets/Packages/Facepunch/redistributable_bin/win64/steam_api64.dll.meta deleted file mode 100644 index d371fcd..0000000 --- a/Assets/Packages/Facepunch/redistributable_bin/win64/steam_api64.dll.meta +++ /dev/null @@ -1,89 +0,0 @@ -fileFormatVersion: 2 -guid: cf5718c4ee1c31e458f8a58a77f4eef0 -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 0 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - '': Any - second: - enabled: 0 - settings: - Exclude Editor: 0 - Exclude Linux: 0 - Exclude Linux64: 0 - Exclude LinuxUniversal: 0 - Exclude OSXUniversal: 0 - Exclude Win: 1 - Exclude Win64: 0 - - first: - Any: - second: - enabled: 1 - settings: {} - - first: - Editor: Editor - second: - enabled: 1 - settings: - CPU: x86_64 - DefaultValueInitialized: true - OS: AnyOS - - first: - Facebook: Win - second: - enabled: 0 - settings: - CPU: None - - first: - Facebook: Win64 - second: - enabled: 0 - settings: - CPU: AnyCPU - - first: - Standalone: Linux - second: - enabled: 1 - settings: - CPU: x86 - - first: - Standalone: Linux64 - second: - enabled: 1 - settings: - CPU: x86_64 - - first: - Standalone: LinuxUniversal - second: - enabled: 1 - settings: - CPU: AnyCPU - - first: - Standalone: OSXUniversal - second: - enabled: 1 - settings: - CPU: AnyCPU - - first: - Standalone: Win - second: - enabled: 0 - settings: - CPU: None - - first: - Standalone: Win64 - second: - enabled: 1 - settings: - CPU: AnyCPU - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Packages/Facepunch/redistributable_bin/win64/steam_api64.lib b/Assets/Packages/Facepunch/redistributable_bin/win64/steam_api64.lib deleted file mode 100644 index 9be697b67bb6596913bb73dc3cac4a26e59e7c6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 341696 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 R^rKN(X{yDoM)!hY{s+c(umJ!7 diff --git a/Assets/Packages/Facepunch/redistributable_bin/win64/steam_api64.lib.meta b/Assets/Packages/Facepunch/redistributable_bin/win64/steam_api64.lib.meta deleted file mode 100644 index 235d424..0000000 --- a/Assets/Packages/Facepunch/redistributable_bin/win64/steam_api64.lib.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: b7f47a56d1502a54aac85b9fadc6741e -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scenes/StartScreen2.unity b/Assets/Scenes/StartScreen2.unity index f50e34f..609e0a8 100644 --- a/Assets/Scenes/StartScreen2.unity +++ b/Assets/Scenes/StartScreen2.unity @@ -1014,7 +1014,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!4 &105139637 Transform: m_ObjectHideFlags: 0 @@ -3862,7 +3862,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!224 &404534655 RectTransform: m_ObjectHideFlags: 0 @@ -5863,7 +5863,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!224 &648688240 RectTransform: m_ObjectHideFlags: 0 @@ -8072,7 +8072,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!224 &900110726 RectTransform: m_ObjectHideFlags: 0 @@ -11009,6 +11009,50 @@ Transform: m_Father: {fileID: 2141027230} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1331087056 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1331087057} + - component: {fileID: 1331087058} + m_Layer: 0 + m_Name: SteamManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1331087057 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1331087056} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 4.618815, y: 2.1867852, z: 9.360118} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 27 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1331087058 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1331087056} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ef4bffeda13d7a748973ff9204401c07, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &1338643376 GameObject: m_ObjectHideFlags: 0 @@ -12330,7 +12374,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!224 &1507036078 RectTransform: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/MainMenu/MainMenuManager.cs b/Assets/Scripts/MainMenu/MainMenuManager.cs index a65b128..857688e 100644 --- a/Assets/Scripts/MainMenu/MainMenuManager.cs +++ b/Assets/Scripts/MainMenu/MainMenuManager.cs @@ -4,6 +4,7 @@ using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; +using Steamworks; public class MainMenuManager : MonoBehaviour { @@ -37,6 +38,9 @@ private void Start() textList[0].GetComponent