This repository has been archived on 2023-09-13. You can view files and clone it, but cannot push or open issues or pull requests.
station_obscurum_unity/Assets/FishNet/CodeGenerating/Processing/QOLAttributeProcessor.cs

165 lines
6.5 KiB
C#
Raw Normal View History

2023-05-31 17:32:21 +02:00
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<MethodDefinition> methods = typeDef.Methods.ToList();
foreach (MethodDefinition md in methods)
{
//Has RPC attribute, doesn't quality for a quality of life attribute.
if (base.GetClass<RpcProcessor>().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;
}
/// <summary>
/// Returns the RPC attribute on a method, if one exist. Otherwise returns null.
/// </summary>
/// <param name="methodDef"></param>
/// <param name="rpcType"></param>
/// <returns></returns>
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<AttributeHelper>().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;
}
/// <summary>
/// Modifies the specified method to use QolType.
/// </summary>
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<NetworkBehaviourHelper>().CreateLocalClientIsOwnerCheck(methodDef, logging, true, false, true);
//Otherwise normal IsClient check.
else
base.GetClass<NetworkBehaviourHelper>().CreateIsClientCheck(methodDef, logging, useStatic, true);
}
}
else if (qolType == QolAttributeType.Server)
{
if (!StripMethod(methodDef))
{
LoggingType logging = qolAttribute.GetField("Logging", LoggingType.Warning);
base.GetClass<NetworkBehaviourHelper>().CreateIsServerCheck(methodDef, logging, useStatic, true);
}
}
bool StripMethod(MethodDefinition md)
{
//Fall through.
return false;
}
}
}
}