com.unity.netcode.gameobjects@1.0.0-pre.2

# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com).

## [1.0.0-pre.2] - 2020-12-20

### Added

- Associated Known Issues for the 1.0.0-pre.1 release in the changelog

### Changed

- Updated label for `1.0.0-pre.1` changelog section

## [1.0.0-pre.1] - 2020-12-20

### Added

- Added `ClientNetworkTransform` sample to the SDK package (#1168)
- Added `Bootstrap` sample to the SDK package (#1140)
- Enhanced `NetworkSceneManager` implementation with additive scene loading capabilities (#1080, #955, #913)
  - `NetworkSceneManager.OnSceneEvent` provides improved scene event notificaitons
- Enhanced `NetworkTransform` implementation with per axis/component based and threshold based state replication (#1042, #1055, #1061, #1084, #1101)
- Added a jitter-resistent `BufferedLinearInterpolator<T>` for `NetworkTransform` (#1060)
- Implemented `NetworkPrefabHandler` that provides support for object pooling and `NetworkPrefab` overrides (#1073, #1004, #977, #905,#749, #727)
- Implemented auto `NetworkObject` transform parent synchronization at runtime over the network (#855)
- Adopted Unity C# Coding Standards in the codebase with `.editorconfig` ruleset (#666, #670)
- When a client tries to spawn a `NetworkObject` an exception is thrown to indicate unsupported behavior. (#981)
- Added a `NetworkTime` and `NetworkTickSystem` which allows for improved control over time and ticks. (#845)
- Added a `OnNetworkDespawn` function to `NetworkObject` which gets called when a `NetworkObject` gets despawned and can be overriden. (#865)
- Added `SnapshotSystem` that would allow variables and spawn/despawn messages to be sent in blocks (#805, #852, #862, #963, #1012, #1013, #1021, #1040, #1062, #1064, #1083, #1091, #1111, #1129, #1166, #1192)
  - Disabled by default for now, except spawn/despawn messages
  - Will leverage unreliable messages with eventual consistency
- `NetworkBehaviour` and `NetworkObject`'s `NetworkManager` instances can now be overriden (#762)
- Added metrics reporting for the new network profiler if the Multiplayer Tools package is present (#1104, #1089, #1096, #1086, #1072, #1058, #960, #897, #891, #878)
- `NetworkBehaviour.IsSpawned` a quick (and stable) way to determine if the associated NetworkObject is spawned (#1190)
- Added `NetworkRigidbody` and `NetworkRigidbody2D` components to support networking `Rigidbody` and `Rigidbody2D` components (#1202, #1175)
- Added `NetworkObjectReference` and `NetworkBehaviourReference` structs which allow to sending `NetworkObject/Behaviours` over RPCs/`NetworkVariable`s (#1173)
- Added `NetworkAnimator` component to support networking `Animator` component (#1281, #872)

### Changed

- Bumped minimum Unity version, renamed package as "Unity Netcode for GameObjects", replaced `MLAPI` namespace and its variants with `Unity.Netcode` namespace and per asm-def variants (#1007, #1009, #1015, #1017, #1019, #1025, #1026, #1065)
  - Minimum Unity version:
    - 2019.4 → 2020.3+
  - Package rename:
    - Display name: `MLAPI Networking Library` → `Netcode for GameObjects`
    - Name: `com.unity.multiplayer.mlapi` → `com.unity.netcode.gameobjects`
    - Updated package description
  - All `MLAPI.x` namespaces are replaced with `Unity.Netcode`
    - `MLAPI.Messaging` → `Unity.Netcode`
    - `MLAPI.Connection` → `Unity.Netcode`
    - `MLAPI.Logging` → `Unity.Netcode`
    - `MLAPI.SceneManagement` → `Unity.Netcode`
    - and other `MLAPI.x` variants to `Unity.Netcode`
  - All assembly definitions are renamed with `Unity.Netcode.x` variants
    - `Unity.Multiplayer.MLAPI.Runtime` → `Unity.Netcode.Runtime`
    - `Unity.Multiplayer.MLAPI.Editor` → `Unity.Netcode.Editor`
    - and other `Unity.Multiplayer.MLAPI.x` variants to `Unity.Netcode.x` variants
- Renamed `Prototyping` namespace and assembly definition to `Components` (#1145)
- Changed `NetworkObject.Despawn(bool destroy)` API to default to `destroy = true` for better usability (#1217)
- Scene registration in `NetworkManager` is now replaced by Build Setttings → Scenes in Build List (#1080)
- `NetworkSceneManager.SwitchScene` has been replaced by `NetworkSceneManager.LoadScene` (#955)
- `NetworkManager, NetworkConfig, and NetworkSceneManager` scene registration replaced with scenes in build list (#1080)
- `GlobalObjectIdHash` replaced `PrefabHash` and `PrefabHashGenerator` for stability and consistency (#698)
- `NetworkStart` has been renamed to `OnNetworkSpawn`. (#865)
- Network variable cleanup - eliminated shared mode, variables are server-authoritative (#1059, #1074)
- `NetworkManager` and other systems are no longer singletons/statics (#696, #705, #706, #737, #738, #739, #746, #747, #763, #765, #766, #783, #784, #785, #786, #787, #788)
- Changed `INetworkSerializable.NetworkSerialize` method signature to use `BufferSerializer<T>` instead of `NetworkSerializer` (#1187)
- Changed `CustomMessagingManager`'s methods to use `FastBufferWriter` and `FastBufferReader` instead of `Stream` (#1187)
- Reduced internal runtime allocations by removing LINQ calls and replacing managed lists/arrays with native collections (#1196)

### Removed

- Removed `NetworkNavMeshAgent` (#1150)
- Removed `NetworkDictionary`, `NetworkSet` (#1149)
- Removed `NetworkVariableSettings` (#1097)
- Removed predefined `NetworkVariable<T>` types (#1093)
    - Removed `NetworkVariableBool`, `NetworkVariableByte`, `NetworkVariableSByte`, `NetworkVariableUShort`, `NetworkVariableShort`, `NetworkVariableUInt`, `NetworkVariableInt`, `NetworkVariableULong`, `NetworkVariableLong`, `NetworkVariableFloat`, `NetworkVariableDouble`, `NetworkVariableVector2`, `NetworkVariableVector3`, `NetworkVariableVector4`, `NetworkVariableColor`, `NetworkVariableColor32`, `NetworkVariableRay`, `NetworkVariableQuaternion`
- Removed `NetworkChannel` and `MultiplexTransportAdapter` (#1133)
- Removed ILPP backend for 2019.4, minimum required version is 2020.3+ (#895)
- `NetworkManager.NetworkConfig` had the following properties removed: (#1080)
  - Scene Registrations no longer exists
  - Allow Runtime Scene Changes was no longer needed and was removed
- Removed the NetworkObject.Spawn payload parameter (#1005)
- Removed `ProfilerCounter`, the original MLAPI network profiler, and the built-in network profiler module (2020.3). A replacement can now be found in the Multiplayer Tools package. (#1048)
- Removed UNet RelayTransport and related relay functionality in UNetTransport (#1081)
- Removed `UpdateStage` parameter from `ServerRpcSendParams` and `ClientRpcSendParams` (#1187)
- Removed `NetworkBuffer`, `NetworkWriter`, `NetworkReader`, `NetworkSerializer`, `PooledNetworkBuffer`, `PooledNetworkWriter`, and `PooledNetworkReader` (#1187)
- Removed `EnableNetworkVariable` in `NetworkConfig`, it is always enabled now (#1179)
- Removed `NetworkTransform`'s FixedSendsPerSecond, AssumeSyncedSends, InterpolateServer, ExtrapolatePosition, MaxSendsToExtrapolate, Channel, EnableNonProvokedResendChecks, DistanceSendrate (#1060) (#826) (#1042, #1055, #1061, #1084, #1101)
- Removed `NetworkManager`'s `StopServer()`, `StopClient()` and `StopHost()` methods and replaced with single `NetworkManager.Shutdown()` method for all (#1108)

### Fixed

- Fixed ServerRpc ownership check to `Debug.LogError` instead of `Debug.LogWarning` (#1126)
- Fixed `NetworkObject.OwnerClientId` property changing before `NetworkBehaviour.OnGainedOwnership()` callback (#1092)
- Fixed `NetworkBehaviourILPP` to iterate over all types in an assembly (#803)
- Fixed cross-asmdef RPC ILPP by importing types into external assemblies (#678)
- Fixed `NetworkManager` shutdown when quitting the application or switching scenes (#1011)
  - Now `NetworkManager` shutdowns correctly and despawns existing `NetworkObject`s
- Fixed Only one `PlayerPrefab` can be selected on `NetworkManager` inspector UI in the editor (#676)
- Fixed connection approval not being triggered for host (#675)
- Fixed various situations where messages could be processed in an invalid order, resulting in errors (#948, #1187, #1218)
- Fixed `NetworkVariable`s being default-initialized on the client instead of being initialized with the desired value (#1266)
- Improved runtime performance and reduced GC pressure (#1187)
- Fixed #915 - clients are receiving data from objects not visible to them (#1099)
- Fixed `NetworkTransform`'s "late join" issues, `NetworkTransform` now uses `NetworkVariable`s instead of RPCs (#826)
- Throw an exception for silent failure when a client tries to get another player's `PlayerObject`, it is now only allowed on the server-side (#844)

### Known Issues

- `NetworkVariable` does not serialize `INetworkSerializable` types through their `NetworkSerialize` implementation
- `NetworkObjects` marked as `DontDestroyOnLoad` are disabled during some network scene transitions
- `NetworkTransform` interpolates from the origin when switching Local Space synchronization
- Exceptions thrown in `OnNetworkSpawn` user code for an object will prevent the callback in other objects
- Cannot send an array of `INetworkSerializable` in RPCs
- ILPP generation fails with special characters in project path

## [0.2.0] - 2021-06-03

WIP version increment to pass package validation checks. Changelog & final version number TBD.

## [0.1.1] - 2021-06-01

This is hotfix v0.1.1 for the initial experimental Unity MLAPI Package.

### Changed

- Fixed issue with the Unity Registry package version missing some fixes from the v0.1.0 release.

## [0.1.0] - 2021-03-23

This is the initial experimental Unity MLAPI Package, v0.1.0.

### Added

- Refactored a new standard for Remote Procedure Call (RPC) in MLAPI which provides increased performance, significantly reduced boilerplate code, and extensibility for future-proofed code. MLAPI RPC includes `ServerRpc` and `ClientRpc` to execute logic on the server and client-side. This provides a single performant unified RPC solution, replacing MLAPI Convenience and Performance RPC (see [here](#removed-features)).
- Added standarized serialization types, including built-in and custom serialization flows. See [RFC #2](https://github.com/Unity-Technologies/com.unity.multiplayer.rfcs/blob/master/text/0002-serializable-types.md) for details.
- `INetworkSerializable` interface replaces `IBitWritable`.
- Added `NetworkSerializer`..., which is the main aggregator that implements serialization code for built-in supported types and holds `NetworkReader` and `NetworkWriter` instances internally.
- Added a Network Update Loop infrastructure that aids Netcode systems to update (such as RPC queue and transport) outside of the standard `MonoBehaviour` event cycle. See [RFC #8](https://github.com/Unity-Technologies/com.unity.multiplayer.rfcs/blob/master/text/0008-network-update-loop.md) and the following details:
  - It uses Unity's [low-level Player Loop API](https://docs.unity3d.com/ScriptReference/LowLevel.PlayerLoop.html) and allows for registering `INetworkUpdateSystem`s with `NetworkUpdate` methods to be executed at specific `NetworkUpdateStage`s, which may also be before or after `MonoBehaviour`-driven game logic execution.
  - You will typically interact with `NetworkUpdateLoop` for registration and `INetworkUpdateSystem` for implementation.
  - `NetworkVariable`s are now tick-based using the `NetworkTickSystem`, tracking time through network interactions and syncs.
- Added message batching to handle consecutive RPC requests sent to the same client. `RpcBatcher` sends batches based on requests from the `RpcQueueProcessing`, by batch size threshold or immediately.
- [GitHub 494](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/494): Added a constraint to allow one `NetworkObject` per `GameObject`, set through the `DisallowMultipleComponent` attribute.
- Integrated MLAPI with the Unity Profiler for versions 2020.2 and later:
  - Added new profiler modules for MLAPI that report important network data.
  - Attached the profiler to a remote player to view network data over the wire.
- A test project is available for building and experimenting with MLAPI features. This project is available in the MLAPI GitHub [testproject folder](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/tree/release/0.1.0/testproject).
- Added a [MLAPI Community Contributions](https://github.com/Unity-Technologies/mlapi-community-contributions/tree/master/com.mlapi.contrib.extensions) new GitHub repository to accept extensions from the MLAPI community. Current extensions include moved MLAPI features for lag compensation (useful for Server Authoritative actions) and `TrackedObject`.

### Changed

- [GitHub 520](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/520): MLAPI now uses the Unity Package Manager for installation management.
- Added functionality and usability to `NetworkVariable`, previously called `NetworkVar`. Updates enhance options and fully replace the need for `SyncedVar`s.
- [GitHub 507](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/507): Reimplemented `NetworkAnimator`, which synchronizes animation states for networked objects.
- GitHub [444](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/444) and [455](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/455): Channels are now represented as bytes instead of strings.

For users of previous versions of MLAPI, this release renames APIs due to refactoring. All obsolete marked APIs have been removed as per [GitHub 513](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/513) and [GitHub 514](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/514).

| Previous MLAPI Versions | V 0.1.0 Name |
| -- | -- |
| `NetworkingManager` | `NetworkManager` |
| `NetworkedObject` | `NetworkObject` |
| `NetworkedBehaviour` | `NetworkBehaviour` |
| `NetworkedClient` | `NetworkClient` |
| `NetworkedPrefab` | `NetworkPrefab` |
| `NetworkedVar` | `NetworkVariable` |
| `NetworkedTransform` | `NetworkTransform` |
| `NetworkedAnimator` | `NetworkAnimator` |
| `NetworkedAnimatorEditor` | `NetworkAnimatorEditor` |
| `NetworkedNavMeshAgent` | `NetworkNavMeshAgent` |
| `SpawnManager` | `NetworkSpawnManager` |
| `BitStream` | `NetworkBuffer` |
| `BitReader` | `NetworkReader` |
| `BitWriter` | `NetworkWriter` |
| `NetEventType` | `NetworkEventType` |
| `ChannelType` | `NetworkDelivery` |
| `Channel` | `NetworkChannel` |
| `Transport` | `NetworkTransport` |
| `NetworkedDictionary` | `NetworkDictionary` |
| `NetworkedList` | `NetworkList` |
| `NetworkedSet` | `NetworkSet` |
| `MLAPIConstants` | `NetworkConstants` |
| `UnetTransport` | `UNetTransport` |

### Fixed

- [GitHub 460](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/460): Fixed an issue for RPC where the host-server was not receiving RPCs from the host-client and vice versa without the loopback flag set in `NetworkingManager`.
- Fixed an issue where data in the Profiler was incorrectly aggregated and drawn, which caused the profiler data to increment indefinitely instead of resetting each frame.
- Fixed an issue the client soft-synced causing PlayMode client-only scene transition issues, caused when running the client in the editor and the host as a release build. Users may have encountered a soft sync of `NetworkedInstanceId` issues in the `SpawnManager.ClientCollectSoftSyncSceneObjectSweep` method.
- [GitHub 458](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/458): Fixed serialization issues in `NetworkList` and `NetworkDictionary` when running in Server mode.
- [GitHub 498](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/498): Fixed numerical precision issues to prevent not a number (NaN) quaternions.
- [GitHub 438](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/438): Fixed booleans by reaching or writing bytes instead of bits.
- [GitHub 519](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/519): Fixed an issue where calling `Shutdown()` before making `NetworkManager.Singleton = null` is null on `NetworkManager.OnDestroy()`.

### Removed

With a new release of MLAPI in Unity, some features have been removed:

- SyncVars have been removed from MLAPI. Use `NetworkVariable`s in place of this functionality. <!-- MTT54 -->
- [GitHub 527](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/527): Lag compensation systems and `TrackedObject` have moved to the new [MLAPI Community Contributions](https://github.com/Unity-Technologies/mlapi-community-contributions/tree/master/com.mlapi.contrib.extensions) repo.
- [GitHub 509](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/509): Encryption has been removed from MLAPI. The `Encryption` option in `NetworkConfig` on the `NetworkingManager` is not available in this release. This change will not block game creation or running. A current replacement for this functionality is not available, and may be developed in future releases. See the following changes:
    - Removed `SecuritySendFlags` from all APIs.
    - Removed encryption, cryptography, and certificate configurations from APIs including `NetworkManager` and `NetworkConfig`.
    - Removed "hail handshake", including `NetworkManager` implementation and `NetworkConstants` entries.
    - Modified `RpcQueue` and `RpcBatcher` internals to remove encryption and authentication from reading and writing.
- Removed the previous MLAPI Profiler editor window from Unity versions 2020.2 and later.
- Removed previous MLAPI Convenience and Performance RPC APIs with the new standard RPC API. See [RFC #1](https://github.com/Unity-Technologies/com.unity.multiplayer.rfcs/blob/master/text/0001-std-rpc-api.md) for details.
- [GitHub 520](https://github.com/Unity-Technologies/com.unity.multiplayer.mlapi/pull/520): Removed the MLAPI Installer.

### Known Issues

- `NetworkNavMeshAgent` does not synchronize mesh data, Agent Size, Steering, Obstacle Avoidance, or Path Finding settings. It only synchronizes the destination and velocity, not the path to the destination.
- For `RPC`, methods with a `ClientRpc` or `ServerRpc` suffix which are not marked with [ServerRpc] or [ClientRpc] will cause a compiler error.
- For `NetworkAnimator`, Animator Overrides are not supported. Triggers do not work.
- For `NetworkVariable`, the `NetworkDictionary` `List` and `Set` must use the `reliableSequenced` channel.
- `NetworkObjects`s are supported but when spawning a prefab with nested child network objects you have to manually call spawn on them
- `NetworkTransform` have the following issues:
  - Replicated objects may have jitter.
  - The owner is always authoritative about the object's position.
  - Scale is not synchronized.
- Connection Approval is not called on the host client.
- For `NamedMessages`, always use `NetworkBuffer` as the underlying stream for sending named and unnamed messages.
- For `NetworkManager`, connection management is limited. Use `IsServer`, `IsClient`, `IsConnectedClient`, or other code to check if MLAPI connected correctly.

## [0.0.1-preview.1] - 2020-12-20

This was an internally-only-used version of the Unity MLAPI Package
This commit is contained in:
Unity Technologies
2020-12-20 00:00:00 +00:00
commit 22d877d1b2
489 changed files with 43246 additions and 0 deletions

View File

@@ -0,0 +1,326 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
using Unity.CompilationPipeline.Common.Diagnostics;
using Unity.CompilationPipeline.Common.ILPostProcessing;
using UnityEngine;
namespace Unity.Netcode.Editor.CodeGen
{
internal static class CodeGenHelpers
{
public const string RuntimeAssemblyName = "Unity.Netcode.Runtime";
public static readonly string NetworkBehaviour_FullName = typeof(NetworkBehaviour).FullName;
public static readonly string INetworkMessage_FullName = typeof(INetworkMessage).FullName;
public static readonly string ServerRpcAttribute_FullName = typeof(ServerRpcAttribute).FullName;
public static readonly string ClientRpcAttribute_FullName = typeof(ClientRpcAttribute).FullName;
public static readonly string ServerRpcParams_FullName = typeof(ServerRpcParams).FullName;
public static readonly string ClientRpcParams_FullName = typeof(ClientRpcParams).FullName;
public static readonly string INetworkSerializable_FullName = typeof(INetworkSerializable).FullName;
public static readonly string UnityColor_FullName = typeof(Color).FullName;
public static readonly string UnityColor32_FullName = typeof(Color32).FullName;
public static readonly string UnityVector2_FullName = typeof(Vector2).FullName;
public static readonly string UnityVector3_FullName = typeof(Vector3).FullName;
public static readonly string UnityVector4_FullName = typeof(Vector4).FullName;
public static readonly string UnityQuaternion_FullName = typeof(Quaternion).FullName;
public static readonly string UnityRay_FullName = typeof(Ray).FullName;
public static readonly string UnityRay2D_FullName = typeof(Ray2D).FullName;
public static uint Hash(this MethodDefinition methodDefinition)
{
var sigArr = Encoding.UTF8.GetBytes($"{methodDefinition.Module.Name} / {methodDefinition.FullName}");
var sigLen = sigArr.Length;
unsafe
{
fixed (byte* sigPtr = sigArr)
{
return XXHash.Hash32(sigPtr, sigLen);
}
}
}
public static bool IsSubclassOf(this TypeDefinition typeDefinition, string classTypeFullName)
{
if (!typeDefinition.IsClass)
{
return false;
}
var baseTypeRef = typeDefinition.BaseType;
while (baseTypeRef != null)
{
if (baseTypeRef.FullName == classTypeFullName)
{
return true;
}
try
{
baseTypeRef = baseTypeRef.Resolve().BaseType;
}
catch
{
return false;
}
}
return false;
}
public static bool HasInterface(this TypeReference typeReference, string interfaceTypeFullName)
{
if (typeReference.IsArray)
{
return false;
}
try
{
var typeDef = typeReference.Resolve();
var typeFaces = typeDef.Interfaces;
return typeFaces.Any(iface => iface.InterfaceType.FullName == interfaceTypeFullName);
}
catch
{
return false;
}
}
public static bool IsSerializable(this TypeReference typeReference)
{
var typeSystem = typeReference.Module.TypeSystem;
// C# primitives
if (typeReference == typeSystem.Boolean)
{
return true;
}
if (typeReference == typeSystem.Char)
{
return true;
}
if (typeReference == typeSystem.SByte)
{
return true;
}
if (typeReference == typeSystem.Byte)
{
return true;
}
if (typeReference == typeSystem.Int16)
{
return true;
}
if (typeReference == typeSystem.UInt16)
{
return true;
}
if (typeReference == typeSystem.Int32)
{
return true;
}
if (typeReference == typeSystem.UInt32)
{
return true;
}
if (typeReference == typeSystem.Int64)
{
return true;
}
if (typeReference == typeSystem.UInt64)
{
return true;
}
if (typeReference == typeSystem.Single)
{
return true;
}
if (typeReference == typeSystem.Double)
{
return true;
}
if (typeReference == typeSystem.String)
{
return true;
}
// Unity primitives
if (typeReference.FullName == UnityColor_FullName)
{
return true;
}
if (typeReference.FullName == UnityColor32_FullName)
{
return true;
}
if (typeReference.FullName == UnityVector2_FullName)
{
return true;
}
if (typeReference.FullName == UnityVector3_FullName)
{
return true;
}
if (typeReference.FullName == UnityVector4_FullName)
{
return true;
}
if (typeReference.FullName == UnityQuaternion_FullName)
{
return true;
}
if (typeReference.FullName == UnityRay_FullName)
{
return true;
}
if (typeReference.FullName == UnityRay2D_FullName)
{
return true;
}
// Enum
if (typeReference.GetEnumAsInt() != null)
{
return true;
}
// INetworkSerializable
if (typeReference.HasInterface(INetworkSerializable_FullName))
{
return true;
}
// Static array
if (typeReference.IsArray)
{
return typeReference.GetElementType().IsSerializable();
}
return false;
}
public static TypeReference GetEnumAsInt(this TypeReference typeReference)
{
if (typeReference.IsArray)
{
return null;
}
try
{
var typeDef = typeReference.Resolve();
return typeDef.IsEnum ? typeDef.GetEnumUnderlyingType() : null;
}
catch
{
return null;
}
}
public static void AddError(this List<DiagnosticMessage> diagnostics, string message)
{
diagnostics.AddError((SequencePoint)null, message);
}
public static void AddError(this List<DiagnosticMessage> diagnostics, MethodDefinition methodDefinition, string message)
{
diagnostics.AddError(methodDefinition.DebugInformation.SequencePoints.FirstOrDefault(), message);
}
public static void AddError(this List<DiagnosticMessage> diagnostics, SequencePoint sequencePoint, string message)
{
diagnostics.Add(new DiagnosticMessage
{
DiagnosticType = DiagnosticType.Error,
File = sequencePoint?.Document.Url.Replace($"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}", ""),
Line = sequencePoint?.StartLine ?? 0,
Column = sequencePoint?.StartColumn ?? 0,
MessageData = $" - {message}"
});
}
public static void RemoveRecursiveReferences(this ModuleDefinition moduleDefinition)
{
// Weird behavior from Cecil: When importing a reference to a specific implementation of a generic
// method, it's importing the main module as a reference into itself. This causes Unity to have issues
// when attempting to iterate the assemblies to discover unit tests, as it goes into infinite recursion
// and eventually hits a stack overflow. I wasn't able to find any way to stop Cecil from importing the module
// into itself, so at the end of it all, we're just going to go back and remove it again.
var moduleName = moduleDefinition.Name;
if (moduleName.EndsWith(".dll") || moduleName.EndsWith(".exe"))
{
moduleName = moduleName.Substring(0, moduleName.Length - 4);
}
foreach (var reference in moduleDefinition.AssemblyReferences)
{
var referenceName = reference.Name.Split(',')[0];
if (referenceName.EndsWith(".dll") || referenceName.EndsWith(".exe"))
{
referenceName = referenceName.Substring(0, referenceName.Length - 4);
}
if (moduleName == referenceName)
{
try
{
moduleDefinition.AssemblyReferences.Remove(reference);
break;
}
catch (Exception)
{
//
}
}
}
}
public static AssemblyDefinition AssemblyDefinitionFor(ICompiledAssembly compiledAssembly, out PostProcessorAssemblyResolver assemblyResolver)
{
assemblyResolver = new PostProcessorAssemblyResolver(compiledAssembly);
var readerParameters = new ReaderParameters
{
SymbolStream = new MemoryStream(compiledAssembly.InMemoryAssembly.PdbData),
SymbolReaderProvider = new PortablePdbReaderProvider(),
AssemblyResolver = assemblyResolver,
ReflectionImporterProvider = new PostProcessorReflectionImporterProvider(),
ReadingMode = ReadingMode.Immediate
};
var assemblyDefinition = AssemblyDefinition.ReadAssembly(new MemoryStream(compiledAssembly.InMemoryAssembly.PeData), readerParameters);
//apparently, it will happen that when we ask to resolve a type that lives inside Unity.Netcode.Runtime, and we
//are also postprocessing Unity.Netcode.Runtime, type resolving will fail, because we do not actually try to resolve
//inside the assembly we are processing. Let's make sure we do that, so that we can use postprocessor features inside
//Unity.Netcode.Runtime itself as well.
assemblyResolver.AddAssemblyDefinitionBeingOperatedOn(assemblyDefinition);
return assemblyDefinition;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0e5541b3bca0e43b48c2e694fffef5b3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,281 @@
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
using Unity.CompilationPipeline.Common.Diagnostics;
using Unity.CompilationPipeline.Common.ILPostProcessing;
using ILPPInterface = Unity.CompilationPipeline.Common.ILPostProcessing.ILPostProcessor;
using MethodAttributes = Mono.Cecil.MethodAttributes;
namespace Unity.Netcode.Editor.CodeGen
{
internal sealed class INetworkMessageILPP : ILPPInterface
{
public override ILPPInterface GetInstance() => this;
public override bool WillProcess(ICompiledAssembly compiledAssembly) =>
compiledAssembly.Name == CodeGenHelpers.RuntimeAssemblyName ||
compiledAssembly.References.Any(filePath => Path.GetFileNameWithoutExtension(filePath) == CodeGenHelpers.RuntimeAssemblyName);
private readonly List<DiagnosticMessage> m_Diagnostics = new List<DiagnosticMessage>();
public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly)
{
if (!WillProcess(compiledAssembly))
{
return null;
}
m_Diagnostics.Clear();
// read
var assemblyDefinition = CodeGenHelpers.AssemblyDefinitionFor(compiledAssembly, out var resolver);
if (assemblyDefinition == null)
{
m_Diagnostics.AddError($"Cannot read assembly definition: {compiledAssembly.Name}");
return null;
}
// process
var mainModule = assemblyDefinition.MainModule;
if (mainModule != null)
{
if (ImportReferences(mainModule))
{
var types = mainModule.GetTypes()
.Where(t => t.Resolve().HasInterface(CodeGenHelpers.INetworkMessage_FullName) && !t.Resolve().IsAbstract)
.ToList();
// process `INetworkMessage` types
if (types.Count == 0)
{
return null;
}
try
{
CreateModuleInitializer(assemblyDefinition, types);
}
catch (Exception e)
{
m_Diagnostics.AddError((e.ToString() + e.StackTrace.ToString()).Replace("\n", "|").Replace("\r", "|"));
}
}
else
{
m_Diagnostics.AddError($"Cannot import references into main module: {mainModule.Name}");
}
}
else
{
m_Diagnostics.AddError($"Cannot get main module from assembly definition: {compiledAssembly.Name}");
}
mainModule.RemoveRecursiveReferences();
// write
var pe = new MemoryStream();
var pdb = new MemoryStream();
var writerParameters = new WriterParameters
{
SymbolWriterProvider = new PortablePdbWriterProvider(),
SymbolStream = pdb,
WriteSymbols = true
};
assemblyDefinition.Write(pe, writerParameters);
return new ILPostProcessResult(new InMemoryAssembly(pe.ToArray(), pdb.ToArray()), m_Diagnostics);
}
private TypeReference m_FastBufferReader_TypeRef;
private TypeReference m_NetworkContext_TypeRef;
private TypeReference m_MessagingSystem_MessageWithHandler_TypeRef;
private MethodReference m_MessagingSystem_MessageHandler_Constructor_TypeRef;
private FieldReference m_ILPPMessageProvider___network_message_types_FieldRef;
private FieldReference m_MessagingSystem_MessageWithHandler_MessageType_FieldRef;
private FieldReference m_MessagingSystem_MessageWithHandler_Handler_FieldRef;
private MethodReference m_Type_GetTypeFromHandle_MethodRef;
private MethodReference m_List_Add_MethodRef;
private bool ImportReferences(ModuleDefinition moduleDefinition)
{
m_FastBufferReader_TypeRef = moduleDefinition.ImportReference(typeof(FastBufferReader));
m_NetworkContext_TypeRef = moduleDefinition.ImportReference(typeof(NetworkContext));
m_MessagingSystem_MessageHandler_Constructor_TypeRef =
moduleDefinition.ImportReference(typeof(MessagingSystem.MessageHandler).GetConstructors()[0]);
var messageWithHandlerType = typeof(MessagingSystem.MessageWithHandler);
m_MessagingSystem_MessageWithHandler_TypeRef =
moduleDefinition.ImportReference(messageWithHandlerType);
foreach (var fieldInfo in messageWithHandlerType.GetFields())
{
switch (fieldInfo.Name)
{
case nameof(MessagingSystem.MessageWithHandler.MessageType):
m_MessagingSystem_MessageWithHandler_MessageType_FieldRef = moduleDefinition.ImportReference(fieldInfo);
break;
case nameof(MessagingSystem.MessageWithHandler.Handler):
m_MessagingSystem_MessageWithHandler_Handler_FieldRef = moduleDefinition.ImportReference(fieldInfo);
break;
}
}
var typeType = typeof(Type);
foreach (var methodInfo in typeType.GetMethods())
{
switch (methodInfo.Name)
{
case nameof(Type.GetTypeFromHandle):
m_Type_GetTypeFromHandle_MethodRef = moduleDefinition.ImportReference(methodInfo);
break;
}
}
var ilppMessageProviderType = typeof(ILPPMessageProvider);
foreach (var fieldInfo in ilppMessageProviderType.GetFields(BindingFlags.Static | BindingFlags.NonPublic))
{
switch (fieldInfo.Name)
{
case nameof(ILPPMessageProvider.__network_message_types):
m_ILPPMessageProvider___network_message_types_FieldRef = moduleDefinition.ImportReference(fieldInfo);
break;
}
}
var listType = typeof(List<MessagingSystem.MessageWithHandler>);
foreach (var methodInfo in listType.GetMethods())
{
switch (methodInfo.Name)
{
case nameof(List<MessagingSystem.MessageWithHandler>.Add):
m_List_Add_MethodRef = moduleDefinition.ImportReference(methodInfo);
break;
}
}
return true;
}
private MethodReference GetNetworkMessageRecieveHandler(TypeDefinition typeDefinition)
{
SequencePoint typeSequence = null;
foreach (var method in typeDefinition.Methods)
{
var resolved = method.Resolve();
var methodSequence = resolved.DebugInformation.SequencePoints.FirstOrDefault();
if (typeSequence == null || methodSequence.StartLine < typeSequence.StartLine)
{
typeSequence = methodSequence;
}
if (resolved.IsStatic && resolved.IsPublic && resolved.Name == "Receive" && resolved.Parameters.Count == 2
&& !resolved.Parameters[0].IsIn
&& !resolved.Parameters[0].ParameterType.IsByReference
&& resolved.Parameters[0].ParameterType.Resolve() ==
m_FastBufferReader_TypeRef.Resolve()
&& resolved.Parameters[1].IsIn
&& resolved.Parameters[1].ParameterType.IsByReference
&& resolved.Parameters[1].ParameterType.GetElementType().Resolve() == m_NetworkContext_TypeRef.Resolve()
&& resolved.ReturnType == resolved.Module.TypeSystem.Void)
{
return method;
}
}
m_Diagnostics.AddError(typeSequence, $"Class {typeDefinition.FullName} does not implement required method: `public static void Receive(FastBufferReader, in NetworkContext)`");
return null;
}
private MethodDefinition GetOrCreateStaticConstructor(TypeDefinition typeDefinition)
{
var staticCtorMethodDef = typeDefinition.GetStaticConstructor();
if (staticCtorMethodDef == null)
{
staticCtorMethodDef = new MethodDefinition(
".cctor", // Static Constructor (constant-constructor)
MethodAttributes.HideBySig |
MethodAttributes.SpecialName |
MethodAttributes.RTSpecialName |
MethodAttributes.Static,
typeDefinition.Module.TypeSystem.Void);
staticCtorMethodDef.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
typeDefinition.Methods.Add(staticCtorMethodDef);
}
return staticCtorMethodDef;
}
private void CreateInstructionsToRegisterType(ILProcessor processor, List<Instruction> instructions, TypeReference type, MethodReference receiveMethod)
{
// MessagingSystem.__network_message_types.Add(new MessagingSystem.MessageWithHandler{MessageType=typeof(type), Handler=type.Receive});
processor.Body.Variables.Add(new VariableDefinition(m_MessagingSystem_MessageWithHandler_TypeRef));
int messageWithHandlerLocIdx = processor.Body.Variables.Count - 1;
instructions.Add(processor.Create(OpCodes.Ldsfld, m_ILPPMessageProvider___network_message_types_FieldRef));
instructions.Add(processor.Create(OpCodes.Ldloca, messageWithHandlerLocIdx));
instructions.Add(processor.Create(OpCodes.Initobj, m_MessagingSystem_MessageWithHandler_TypeRef));
// tmp.MessageType = typeof(type);
instructions.Add(processor.Create(OpCodes.Ldloca, messageWithHandlerLocIdx));
instructions.Add(processor.Create(OpCodes.Ldtoken, type));
instructions.Add(processor.Create(OpCodes.Call, m_Type_GetTypeFromHandle_MethodRef));
instructions.Add(processor.Create(OpCodes.Stfld, m_MessagingSystem_MessageWithHandler_MessageType_FieldRef));
// tmp.Handler = type.Receive
instructions.Add(processor.Create(OpCodes.Ldloca, messageWithHandlerLocIdx));
instructions.Add(processor.Create(OpCodes.Ldnull));
instructions.Add(processor.Create(OpCodes.Ldftn, receiveMethod));
instructions.Add(processor.Create(OpCodes.Newobj, m_MessagingSystem_MessageHandler_Constructor_TypeRef));
instructions.Add(processor.Create(OpCodes.Stfld, m_MessagingSystem_MessageWithHandler_Handler_FieldRef));
// ILPPMessageProvider.__network_message_types.Add(tmp);
instructions.Add(processor.Create(OpCodes.Ldloc, messageWithHandlerLocIdx));
instructions.Add(processor.Create(OpCodes.Callvirt, m_List_Add_MethodRef));
}
// Creates a static module constructor (which is executed when the module is loaded) that registers all the
// message types in the assembly with MessagingSystem.
// This is the same behavior as annotating a static method with [ModuleInitializer] in standardized
// C# (that attribute doesn't exist in Unity, but the static module constructor still works)
// https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.moduleinitializerattribute?view=net-5.0
// https://web.archive.org/web/20100212140402/http://blogs.msdn.com/junfeng/archive/2005/11/19/494914.aspx
private void CreateModuleInitializer(AssemblyDefinition assembly, List<TypeDefinition> networkMessageTypes)
{
foreach (var typeDefinition in assembly.MainModule.Types)
{
if (typeDefinition.FullName == "<Module>")
{
var staticCtorMethodDef = GetOrCreateStaticConstructor(typeDefinition);
var processor = staticCtorMethodDef.Body.GetILProcessor();
var instructions = new List<Instruction>();
foreach (var type in networkMessageTypes)
{
var receiveMethod = GetNetworkMessageRecieveHandler(type);
if (receiveMethod == null)
{
continue;
}
CreateInstructionsToRegisterType(processor, instructions, type, receiveMethod);
}
instructions.ForEach(instruction => processor.Body.Instructions.Insert(processor.Body.Instructions.Count - 1, instruction));
break;
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a754504752d649bb8131df8756bd764e
timeCreated: 1631666359

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cf1c8b78182704372820a586c1c91d97
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using Mono.Cecil;
using Unity.CompilationPipeline.Common.ILPostProcessing;
namespace Unity.Netcode.Editor.CodeGen
{
internal class PostProcessorAssemblyResolver : IAssemblyResolver
{
private readonly string[] m_AssemblyReferences;
private readonly Dictionary<string, AssemblyDefinition> m_AssemblyCache = new Dictionary<string, AssemblyDefinition>();
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 fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
byteArray = new byte[fileStream.Length];
var readLength = fileStream.Read(byteArray, 0, (int)fileStream.Length);
if (readLength != fileStream.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<MemoryStream> 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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2c247f4266b2864eb96e6a9ae6557d31
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
using System.Linq;
using System.Reflection;
using Mono.Cecil;
namespace Unity.Netcode.Editor.CodeGen
{
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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 484e8ad8c4dde382ea67036b32935ef1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
using Mono.Cecil;
namespace Unity.Netcode.Editor.CodeGen
{
internal class PostProcessorReflectionImporterProvider : IReflectionImporterProvider
{
public IReflectionImporter GetReflectionImporter(ModuleDefinition moduleDefinition)
{
return new PostProcessorReflectionImporter(moduleDefinition);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f9273a5dad109ab0783891e36c983080
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,131 @@
using System.Collections.Generic;
using System.IO;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Unity.CompilationPipeline.Common.Diagnostics;
using Unity.CompilationPipeline.Common.ILPostProcessing;
using ILPPInterface = Unity.CompilationPipeline.Common.ILPostProcessing.ILPostProcessor;
namespace Unity.Netcode.Editor.CodeGen
{
internal sealed class RuntimeAccessModifiersILPP : ILPPInterface
{
public override ILPPInterface GetInstance() => this;
public override bool WillProcess(ICompiledAssembly compiledAssembly) => compiledAssembly.Name == CodeGenHelpers.RuntimeAssemblyName;
private readonly List<DiagnosticMessage> m_Diagnostics = new List<DiagnosticMessage>();
public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly)
{
if (!WillProcess(compiledAssembly))
{
return null;
}
m_Diagnostics.Clear();
// read
var assemblyDefinition = CodeGenHelpers.AssemblyDefinitionFor(compiledAssembly, out var unused);
if (assemblyDefinition == null)
{
m_Diagnostics.AddError($"Cannot read Netcode Runtime assembly definition: {compiledAssembly.Name}");
return null;
}
// process
var mainModule = assemblyDefinition.MainModule;
if (mainModule != null)
{
foreach (var typeDefinition in mainModule.Types)
{
if (!typeDefinition.IsClass)
{
continue;
}
switch (typeDefinition.Name)
{
case nameof(NetworkManager):
ProcessNetworkManager(typeDefinition, compiledAssembly.Defines);
break;
case nameof(NetworkBehaviour):
ProcessNetworkBehaviour(typeDefinition);
break;
case nameof(__RpcParams):
typeDefinition.IsPublic = true;
break;
}
}
}
else
{
m_Diagnostics.AddError($"Cannot get main module from Netcode Runtime assembly definition: {compiledAssembly.Name}");
}
// write
var pe = new MemoryStream();
var pdb = new MemoryStream();
var writerParameters = new WriterParameters
{
SymbolWriterProvider = new PortablePdbWriterProvider(),
SymbolStream = pdb,
WriteSymbols = true
};
assemblyDefinition.Write(pe, writerParameters);
return new ILPostProcessResult(new InMemoryAssembly(pe.ToArray(), pdb.ToArray()), m_Diagnostics);
}
private void ProcessNetworkManager(TypeDefinition typeDefinition, string[] assemblyDefines)
{
foreach (var fieldDefinition in typeDefinition.Fields)
{
if (fieldDefinition.Name == nameof(NetworkManager.__rpc_func_table))
{
fieldDefinition.IsPublic = true;
}
if (fieldDefinition.Name == nameof(NetworkManager.RpcReceiveHandler))
{
fieldDefinition.IsPublic = true;
}
if (fieldDefinition.Name == nameof(NetworkManager.__rpc_name_table))
{
fieldDefinition.IsPublic = true;
}
}
}
private void ProcessNetworkBehaviour(TypeDefinition typeDefinition)
{
foreach (var nestedType in typeDefinition.NestedTypes)
{
if (nestedType.Name == nameof(NetworkBehaviour.__RpcExecStage))
{
nestedType.IsNestedFamily = true;
}
}
foreach (var fieldDefinition in typeDefinition.Fields)
{
if (fieldDefinition.Name == nameof(NetworkBehaviour.__rpc_exec_stage))
{
fieldDefinition.IsFamily = true;
}
}
foreach (var methodDefinition in typeDefinition.Methods)
{
if (methodDefinition.Name == nameof(NetworkBehaviour.__sendServerRpc)
|| methodDefinition.Name == nameof(NetworkBehaviour.__sendClientRpc))
{
methodDefinition.IsFamily = true;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2c9f2f4b03d774432be69d4c2f53bd2d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
{
"name": "Unity.Netcode.Editor.CodeGen",
"rootNamespace": "Unity.Netcode.Editor.CodeGen",
"references": [
"Unity.Netcode.Runtime"
],
"includePlatforms": [
"Editor"
],
"allowUnsafeCode": true,
"overrideReferences": true,
"precompiledReferences": [
"Mono.Cecil.dll",
"Mono.Cecil.Mdb.dll",
"Mono.Cecil.Pdb.dll",
"Mono.Cecil.Rocks.dll"
],
"autoReferenced": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: fe4fa159f4a96442ba22af67ddf20c65
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: