1. 程式人生 > >關於最近網上謠言傳的很凶的 “太吾繪卷” 遊戲原始碼的問題。

關於最近網上謠言傳的很凶的 “太吾繪卷” 遊戲原始碼的問題。

    這兩天吵的挺厲害的,我本人覺得喜歡這類題材的人們也可以去支援一下這個遊戲,但是有一點惡意的抨擊別人的程式碼寫得亂,我感到真的沒必要,先想想你自己寫的怎麼樣再來說吧。

   當然我這不是為 “太吾繪卷” 洗白,這跟我沒關係(不是一起的),但是我說過我很厭惡裝逼俠,它們都令我都有一點點語言歧視,我可以說我把 “太吾繪卷” 的 .net dlllib 提取出來了(相當於程式碼出來了)但是本人想說,雖然 “太吾” 的程式碼寫得很一般,一些地方也有不少設計不合理的地方,當然這個在不同專案裡面都無法避免,只能說會逐步的進行修復程式碼重構調整,但不至於被網路上瘋傳的那麼差勁,我覺得我們是不是應該尊重一個客觀的事實。

   國內能把程式碼到一般水平的人也需要好好碼幾年沉澱一下,追求程式碼 “行雲流水”、“一氣呵成” 那是玩程式碼藝術(質量 >= 90分,>= 95分很難寫,一行程式碼扣腦袋得扣半天),都是一幫牛魔王的人才寫的出來,一般人想想就好了,

  當然本人貼出的一部分東西,真偽你們可以找 “太吾繪卷”  的技術團隊論證程式碼的真偽,我覺得這個沒有什麼好裝逼的,雖然搞掉這個東西也沒花到太久的時間,但是這也說明了 “太吾繪卷” 在這塊做的安全性不是很好,當然提高安全的辦法有不少,但這不是我在本人要談到的,我說過跟我一點關係沒有。本人只是單純的看不慣裝逼犯,要裝逼去 java 那邊去,你們一起裝,可勁的裝不要停,停了是罪,停了是惡!

  另外本人不會提供程式碼,也不會破解這個遊戲,它跟我沒有任何衝突,另外我本人實在找不到破解這遊戲的一個理由在哪裡,秀技術?算了這東西又不難,對於比我 “高或同層次” 的工程師來說,我這可能是要自己打自己的打臉的節奏~呀(裝逼,秀技術不是這麼秀的);第二我現在一直又氪又肝 “楚留香” 這個遊戲,第三我現在是混 “醫療千秋行業” 的。。。當然玩一個幾十塊錢的單機還想著破解,弄外掛,你們真的也是夠了,有啥意思,除了自慰。。。(發自肺腑)。。。

   

  上面用C/C++寫的程式碼是用於從加密的 “偽dll” 中提取真正的 “.net dlllib”,u3d-csharp 是基於 mono 的體系,而 mono 只支援到 .net 3.5(所以這個dll 工程師是 .net 2.0 的也不足為奇)當然你可以利用 mono 對你 .net dlllib 加密,但是這個東西真的很脆弱,雖然它在不同版本中可能會不一致,但是大體函式的簽名是沒有變的,破掉的方法有幾種,一種是呼叫 XXX【打黑碼,本人不是教你們來玩破解的】 庫載入到程序的模組空間,然後在把它 dump 出來(無論你是通過emit組建,還是直接從模組表中提出)還有就是破解密函式(這個比較省事,需要分析寫的程式碼都會少很多),.... ,另外我想,你們能把 mono 內鏈靜態編譯的話,幾乎就把目前 99% 人砍掉,剩下這批也沒多大心情會去搞你這個玩意,浪費的時間與回報簡直不成正比,當然辦法還有很多增加別人成本,到它不能忍受你就贏了,要想根治是不可能的。。。

   本人隨便從 “太吾繪卷” 中摘要一些程式碼吧,它們噴別人的程式碼中帶有 “MonoBehaviour” 我就貼幾個與此相關的程式碼,各位看官自行判斷吧。

BoneFollower:

// Spine.Unity.BoneFollower
using Spine;
using Spine.Unity;
using System;
using UnityEngine;
using UnityEngine.Serialization;

[ExecuteInEditMode]
[AddComponentMenu("Spine/BoneFollower")]
public class BoneFollower : MonoBehaviour
{
	public SkeletonRenderer skeletonRenderer;

	[SpineBone("", "skeletonRenderer", true, false)]
	[SerializeField]
	public string boneName;

	public bool followZPosition = true;

	public bool followBoneRotation = true;

	[Tooltip("Follows the skeleton's flip state by controlling this Transform's local scale.")]
	public bool followSkeletonFlip = true;

	[Tooltip("Follows the target bone's local scale. BoneFollower cannot inherit world/skewed scale because of UnityEngine.Transform property limitations.")]
	public bool followLocalScale = false;

	[FormerlySerializedAs("resetOnAwake")]
	public bool initializeOnAwake = true;

	[NonSerialized]
	public bool valid;

	[NonSerialized]
	public Bone bone;

	private Transform skeletonTransform;

	private bool skeletonTransformIsParent;

	public SkeletonRenderer SkeletonRenderer
	{
		get
		{
			return skeletonRenderer;
		}
		set
		{
			skeletonRenderer = value;
			Initialize();
		}
	}

	public bool SetBone(string name)
	{
		bone = skeletonRenderer.skeleton.FindBone(name);
		if (bone != null)
		{
			boneName = name;
			return true;
		}
		Debug.LogError("Bone not found: " + name, this);
		return false;
	}

	public void Awake()
	{
		if (initializeOnAwake)
		{
			Initialize();
		}
	}

	public void HandleRebuildRenderer(SkeletonRenderer skeletonRenderer)
	{
		Initialize();
	}

	public void Initialize()
	{
		bone = null;
		valid = ((UnityEngine.Object)skeletonRenderer != (UnityEngine.Object)null && skeletonRenderer.valid);
		if (valid)
		{
			skeletonTransform = skeletonRenderer.transform;
			skeletonRenderer.OnRebuild -= HandleRebuildRenderer;
			skeletonRenderer.OnRebuild += HandleRebuildRenderer;
			skeletonTransformIsParent = object.ReferenceEquals(skeletonTransform, base.transform.parent);
			if (!string.IsNullOrEmpty(boneName))
			{
				bone = skeletonRenderer.skeleton.FindBone(boneName);
			}
		}
	}

	private void OnDestroy()
	{
		if ((UnityEngine.Object)skeletonRenderer != (UnityEngine.Object)null)
		{
			skeletonRenderer.OnRebuild -= HandleRebuildRenderer;
		}
	}

	public void LateUpdate()
	{
		if (!valid)
		{
			Initialize();
		}
		else
		{
			if (bone == null)
			{
				if (string.IsNullOrEmpty(boneName))
				{
					return;
				}
				bone = skeletonRenderer.skeleton.FindBone(boneName);
				if (!SetBone(boneName))
				{
					return;
				}
			}
			Transform transform = base.transform;
			Quaternion quaternion;
			if (skeletonTransformIsParent)
			{
				Transform transform2 = transform;
				float worldX = bone.worldX;
				float worldY = bone.worldY;
				float z;
				if (followZPosition)
				{
					z = 0f;
				}
				else
				{
					Vector3 localPosition = transform.localPosition;
					z = localPosition.z;
				}
				transform2.localPosition = new Vector3(worldX, worldY, z);
				if (followBoneRotation)
				{
					float num = Mathf.Atan2(bone.c, bone.a) * 0.5f;
					if (followLocalScale && bone.scaleX < 0f)
					{
						num += 1.57079637f;
					}
					quaternion = default(Quaternion);
					Quaternion localRotation = quaternion;
					localRotation.z = Mathf.Sin(num);
					localRotation.w = Mathf.Cos(num);
					transform.localRotation = localRotation;
				}
			}
			else
			{
				Vector3 position = skeletonTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY, 0f));
				if (!followZPosition)
				{
					Vector3 position2 = transform.position;
					position.z = position2.z;
				}
				float num2 = bone.WorldRotationX;
				Transform parent = transform.parent;
				if ((UnityEngine.Object)parent != (UnityEngine.Object)null)
				{
					Matrix4x4 localToWorldMatrix = parent.localToWorldMatrix;
					if (localToWorldMatrix.m00 * localToWorldMatrix.m11 - localToWorldMatrix.m01 * localToWorldMatrix.m10 < 0f)
					{
						num2 = 0f - num2;
					}
				}
				if (followBoneRotation)
				{
					quaternion = skeletonTransform.rotation;
					Vector3 eulerAngles = quaternion.eulerAngles;
					if (followLocalScale && bone.scaleX < 0f)
					{
						num2 += 180f;
					}
					transform.SetPositionAndRotation(position, Quaternion.Euler(eulerAngles.x, eulerAngles.y, eulerAngles.z + num2));
				}
				else
				{
					transform.position = position;
				}
			}
			Vector3 localScale = (!followLocalScale) ? new Vector3(1f, 1f, 1f) : new Vector3(bone.scaleX, bone.scaleY, 1f);
			if (followSkeletonFlip)
			{
				localScale.y *= ((!(bone.skeleton.flipX ^ bone.skeleton.flipY)) ? 1f : (-1f));
			}
			transform.localScale = localScale;
		}
	}
}

SkeletonUtility:

// Spine.Unity.SkeletonUtility
using Spine;
using Spine.Unity;
using System;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(ISkeletonAnimation))]
[ExecuteInEditMode]
public class SkeletonUtility : MonoBehaviour
{
	public delegate void SkeletonUtilityDelegate();

	public Transform boneRoot;

	[HideInInspector]
	public SkeletonRenderer skeletonRenderer;

	[HideInInspector]
	public ISkeletonAnimation skeletonAnimation;

	[NonSerialized]
	public List<SkeletonUtilityBone> utilityBones = new List<SkeletonUtilityBone>();

	[NonSerialized]
	public List<SkeletonUtilityConstraint> utilityConstraints = new List<SkeletonUtilityConstraint>();

	protected bool hasTransformBones;

	protected bool hasUtilityConstraints;

	protected bool needToReprocessBones;

	public event SkeletonUtilityDelegate OnReset;

	public static PolygonCollider2D AddBoundingBoxGameObject(Skeleton skeleton, string skinName, string slotName, string attachmentName, Transform parent, bool isTrigger = true)
	{
		Skin skin = (!string.IsNullOrEmpty(skinName)) ? skeleton.data.FindSkin(skinName) : skeleton.data.defaultSkin;
		if (skin != null)
		{
			Attachment attachment = skin.GetAttachment(skeleton.FindSlotIndex(slotName), attachmentName);
			if (attachment != null)
			{
				BoundingBoxAttachment boundingBoxAttachment = attachment as BoundingBoxAttachment;
				if (boundingBoxAttachment == null)
				{
					Debug.LogFormat("Attachment '{0}' was not a Bounding Box.", attachmentName);
					return null;
				}
				Slot slot = skeleton.FindSlot(slotName);
				return AddBoundingBoxGameObject(boundingBoxAttachment.Name, boundingBoxAttachment, slot, parent, isTrigger);
			}
			Debug.LogFormat("Attachment in slot '{0}' named '{1}' not found in skin '{2}'.", slotName, attachmentName, skin.name);
			return null;
		}
		Debug.LogError("Skin " + skinName + " not found!");
		return null;
	}

	public static PolygonCollider2D AddBoundingBoxGameObject(string name, BoundingBoxAttachment box, Slot slot, Transform parent, bool isTrigger = true)
	{
		GameObject gameObject = new GameObject("[BoundingBox]" + ((!string.IsNullOrEmpty(name)) ? name : box.Name));
		Transform transform = gameObject.transform;
		transform.parent = parent;
		transform.localPosition = Vector3.zero;
		transform.localRotation = Quaternion.identity;
		transform.localScale = Vector3.one;
		return AddBoundingBoxAsComponent(box, slot, gameObject, isTrigger, true, 0f);
	}

	public static PolygonCollider2D AddBoundingBoxAsComponent(BoundingBoxAttachment box, Slot slot, GameObject gameObject, bool isTrigger = true, bool isKinematic = true, float gravityScale = 0f)
	{
		if (box != null)
		{
			if (slot.bone != slot.Skeleton.RootBone)
			{
				Rigidbody2D component = gameObject.GetComponent<Rigidbody2D>();
				if ((UnityEngine.Object)component == (UnityEngine.Object)null)
				{
					component = gameObject.AddComponent<Rigidbody2D>();
					component.isKinematic = isKinematic;
					component.gravityScale = gravityScale;
				}
			}
			PolygonCollider2D polygonCollider2D = gameObject.AddComponent<PolygonCollider2D>();
			polygonCollider2D.isTrigger = isTrigger;
			SetColliderPointsLocal(polygonCollider2D, slot, box);
			return polygonCollider2D;
		}
		return null;
	}

	public static void SetColliderPointsLocal(PolygonCollider2D collider, Slot slot, BoundingBoxAttachment box)
	{
		if (box != null)
		{
			if (box.IsWeighted())
			{
				Debug.LogWarning("UnityEngine.PolygonCollider2D does not support weighted or animated points. Collider points will not be animated and may have incorrect orientation. If you want to use it as a collider, please remove weights and animations from the bounding box in Spine editor.");
			}
			Vector2[] localVertices = box.GetLocalVertices(slot, null);
			collider.SetPath(0, localVertices);
		}
	}

	public static Bounds GetBoundingBoxBounds(BoundingBoxAttachment boundingBox, float depth = 0f)
	{
		float[] vertices = boundingBox.Vertices;
		int num = vertices.Length;
		Bounds result = default(Bounds);
		result.center = new Vector3(vertices[0], vertices[1], 0f);
		for (int i = 2; i < num; i += 2)
		{
			result.Encapsulate(new Vector3(vertices[i], vertices[i + 1], 0f));
		}
		Vector3 size = result.size;
		size.z = depth;
		result.size = size;
		return result;
	}

	private void Update()
	{
		Skeleton skeleton = skeletonRenderer.skeleton;
		if ((UnityEngine.Object)boneRoot != (UnityEngine.Object)null && skeleton != null)
		{
			Vector3 one = Vector3.one;
			if (skeleton.FlipX)
			{
				one.x = -1f;
			}
			if (skeleton.FlipY)
			{
				one.y = -1f;
			}
			boneRoot.localScale = one;
		}
	}

	private void OnEnable()
	{
		if ((UnityEngine.Object)skeletonRenderer == (UnityEngine.Object)null)
		{
			skeletonRenderer = GetComponent<SkeletonRenderer>();
		}
		if (skeletonAnimation == null)
		{
			skeletonAnimation = GetComponent<SkeletonAnimation>();
			if (skeletonAnimation == null)
			{
				skeletonAnimation = GetComponent<SkeletonAnimator>();
			}
		}
		skeletonRenderer.OnRebuild -= HandleRendererReset;
		skeletonRenderer.OnRebuild += HandleRendererReset;
		if (skeletonAnimation != null)
		{
			skeletonAnimation.UpdateLocal -= UpdateLocal;
			skeletonAnimation.UpdateLocal += UpdateLocal;
		}
		CollectBones();
	}

	private void Start()
	{
		CollectBones();
	}

	private void OnDisable()
	{
		skeletonRenderer.OnRebuild -= HandleRendererReset;
		if (skeletonAnimation != null)
		{
			skeletonAnimation.UpdateLocal -= UpdateLocal;
			skeletonAnimation.UpdateWorld -= UpdateWorld;
			skeletonAnimation.UpdateComplete -= UpdateComplete;
		}
	}

	private void HandleRendererReset(SkeletonRenderer r)
	{
		if (this.OnReset != null)
		{
			this.OnReset();
		}
		CollectBones();
	}

	public void RegisterBone(SkeletonUtilityBone bone)
	{
		if (!utilityBones.Contains(bone))
		{
			utilityBones.Add(bone);
			needToReprocessBones = true;
		}
	}

	public void UnregisterBone(SkeletonUtilityBone bone)
	{
		utilityBones.Remove(bone);
	}

	public void RegisterConstraint(SkeletonUtilityConstraint constraint)
	{
		if (!utilityConstraints.Contains(constraint))
		{
			utilityConstraints.Add(constraint);
			needToReprocessBones = true;
		}
	}

	public void UnregisterConstraint(SkeletonUtilityConstraint constraint)
	{
		utilityConstraints.Remove(constraint);
	}

	public void CollectBones()
	{
		Skeleton skeleton = skeletonRenderer.skeleton;
		if (skeleton != null)
		{
			if ((UnityEngine.Object)boneRoot != (UnityEngine.Object)null)
			{
				List<object> list = new List<object>();
				ExposedList<IkConstraint> ikConstraints = skeleton.IkConstraints;
				int i = 0;
				for (int count = ikConstraints.Count; i < count; i++)
				{
					list.Add(ikConstraints.Items[i].target);
				}
				ExposedList<TransformConstraint> transformConstraints = skeleton.TransformConstraints;
				int j = 0;
				for (int count2 = transformConstraints.Count; j < count2; j++)
				{
					list.Add(transformConstraints.Items[j].target);
				}
				List<SkeletonUtilityBone> list2 = utilityBones;
				int k = 0;
				for (int count3 = list2.Count; k < count3; k++)
				{
					SkeletonUtilityBone skeletonUtilityBone = list2[k];
					if (skeletonUtilityBone.bone != null)
					{
						hasTransformBones |= (skeletonUtilityBone.mode == SkeletonUtilityBone.Mode.Override);
						hasUtilityConstraints |= list.Contains(skeletonUtilityBone.bone);
					}
				}
				hasUtilityConstraints |= (utilityConstraints.Count > 0);
				if (skeletonAnimation != null)
				{
					skeletonAnimation.UpdateWorld -= UpdateWorld;
					skeletonAnimation.UpdateComplete -= UpdateComplete;
					if (hasTransformBones || hasUtilityConstraints)
					{
						skeletonAnimation.UpdateWorld += UpdateWorld;
					}
					if (hasUtilityConstraints)
					{
						skeletonAnimation.UpdateComplete += UpdateComplete;
					}
				}
				needToReprocessBones = false;
			}
			else
			{
				utilityBones.Clear();
				utilityConstraints.Clear();
			}
		}
	}

	private void UpdateLocal(ISkeletonAnimation anim)
	{
		if (needToReprocessBones)
		{
			CollectBones();
		}
		List<SkeletonUtilityBone> list = utilityBones;
		if (list != null)
		{
			int i = 0;
			for (int count = list.Count; i < count; i++)
			{
				list[i].transformLerpComplete = false;
			}
			UpdateAllBones(SkeletonUtilityBone.UpdatePhase.Local);
		}
	}

	private void UpdateWorld(ISkeletonAnimation anim)
	{
		UpdateAllBones(SkeletonUtilityBone.UpdatePhase.World);
		int i = 0;
		for (int count = utilityConstraints.Count; i < count; i++)
		{
			utilityConstraints[i].DoUpdate();
		}
	}

	private void UpdateComplete(ISkeletonAnimation anim)
	{
		UpdateAllBones(SkeletonUtilityBone.UpdatePhase.Complete);
	}

	private void UpdateAllBones(SkeletonUtilityBone.UpdatePhase phase)
	{
		if ((UnityEngine.Object)boneRoot == (UnityEngine.Object)null)
		{
			CollectBones();
		}
		List<SkeletonUtilityBone> list = utilityBones;
		if (list != null)
		{
			int i = 0;
			for (int count = list.Count; i < count; i++)
			{
				list[i].DoUpdate(phase);
			}
		}
	}

	public Transform GetBoneRoot()
	{
		if (!((UnityEngine.Object)boneRoot != (UnityEngine.Object)null))
		{
			boneRoot = new GameObject("SkeletonUtility-Root").transform;
			boneRoot.parent = base.transform;
			boneRoot.localPosition = Vector3.zero;
			boneRoot.localRotation = Quaternion.identity;
			boneRoot.localScale = Vector3.one;
			return boneRoot;
		}
		return boneRoot;
	}

	public GameObject SpawnRoot(SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca)
	{
		GetBoneRoot();
		Skeleton skeleton = skeletonRenderer.skeleton;
		GameObject result = SpawnBone(skeleton.RootBone, boneRoot, mode, pos, rot, sca);
		CollectBones();
		return result;
	}

	public GameObject SpawnHierarchy(SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca)
	{
		GetBoneRoot();
		Skeleton skeleton = skeletonRenderer.skeleton;
		GameObject result = SpawnBoneRecursively(skeleton.RootBone, boneRoot, mode, pos, rot, sca);
		CollectBones();
		return result;
	}

	public GameObject SpawnBoneRecursively(Bone bone, Transform parent, SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca)
	{
		GameObject gameObject = SpawnBone(bone, parent, mode, pos, rot, sca);
		ExposedList<Bone> children = bone.Children;
		int i = 0;
		for (int count = children.Count; i < count; i++)
		{
			Bone bone2 = children.Items[i];
			SpawnBoneRecursively(bone2, gameObject.transform, mode, pos, rot, sca);
		}
		return gameObject;
	}

	public GameObject SpawnBone(Bone bone, Transform parent, SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca)
	{
		GameObject gameObject = new GameObject(bone.Data.Name);
		gameObject.transform.parent = parent;
		SkeletonUtilityBone skeletonUtilityBone = gameObject.AddComponent<SkeletonUtilityBone>();
		skeletonUtilityBone.skeletonUtility = this;
		skeletonUtilityBone.position = pos;
		skeletonUtilityBone.rotation = rot;
		skeletonUtilityBone.scale = sca;
		skeletonUtilityBone.mode = mode;
		skeletonUtilityBone.zPosition = true;
		skeletonUtilityBone.Reset();
		skeletonUtilityBone.bone = bone;
		skeletonUtilityBone.boneName = bone.Data.Name;
		skeletonUtilityBone.valid = true;
		if (mode == SkeletonUtilityBone.Mode.Override)
		{
			if (rot)
			{
				gameObject.transform.localRotation = Quaternion.Euler(0f, 0f, skeletonUtilityBone.bone.AppliedRotation);
			}
			if (pos)
			{
				gameObject.transform.localPosition = new Vector3(skeletonUtilityBone.bone.X, skeletonUtilityBone.bone.Y, 0f);
			}
			gameObject.transform.localScale = new Vector3(skeletonUtilityBone.bone.scaleX, skeletonUtilityBone.bone.scaleY, 0f);
		}
		return gameObject;
	}
}

  PointFollower:

// Spine.Unity.PointFollower
using Spine;
using Spine.Unity;
using UnityEngine;

[ExecuteInEditMode]
[AddComponentMenu("Spine/Point Follower")]
public class PointFollower : MonoBehaviour, IHasSkeletonRenderer, IHasSkeletonComponent
{
	[SerializeField]
	public SkeletonRenderer skeletonRenderer;

	[SpineSlot("", "skeletonRenderer", false, true, false)]
	public string slotName;

	[SpineAttachment(true, false, false, "slotName", "skeletonRenderer", "", true, true)]
	public string pointAttachmentName;

	public bool followRotation = true;

	public bool followSkeletonFlip = true;

	public bool followSkeletonZPosition = false;

	private Transform skeletonTransform;

	private bool skeletonTransformIsParent;

	private PointAttachment point;

	private Bone bone;

	private bool valid;

	public SkeletonRenderer SkeletonRenderer
	{
		get
		{
			return skeletonRenderer;
		}
	}

	public ISkeletonComponent SkeletonComponent
	{
		get
		{
			return skeletonRenderer;
		}
	}

	public bool IsValid
	{
		get
		{
			return valid;
		}
	}

	public void Initialize()
	{
		valid = ((Object)skeletonRenderer != (Object)null && skeletonRenderer.valid);
		if (valid)
		{
			UpdateReferences();
		}
	}

	private void HandleRebuildRenderer(SkeletonRenderer skeletonRenderer)
	{
		Initialize();
	}

	private void UpdateReferences()
	{
		skeletonTransform = skeletonRenderer.transform;
		skeletonRenderer.OnRebuild -= HandleRebuildRenderer;
		skeletonRenderer.OnRebuild += HandleRebuildRenderer;
		skeletonTransformIsParent = object.ReferenceEquals(skeletonTransform, base.transform.parent);
		bone = null;
		point = null;
		if (!string.IsNullOrEmpty(pointAttachmentName))
		{
			Skeleton skeleton = skeletonRenderer.skeleton;
			int num = skeleton.FindSlotIndex(slotName);
			if (num >= 0)
			{
				Slot slot = skeleton.slots.Items[num];
				bone = slot.bone;
				point = (skeleton.GetAttachment(num, pointAttachmentName) as PointAttachment);
			}
		}
	}

	public void LateUpdate()
	{
		if (point == null)
		{
			if (string.IsNullOrEmpty(pointAttachmentName))
			{
				return;
			}
			UpdateReferences();
			if (point == null)
			{
				return;
			}
		}
		Vector2 vector = default(Vector2);
		point.ComputeWorldPosition(bone, out vector.x, out vector.y);
		float num = point.ComputeWorldRotation(bone);
		Transform transform = base.transform;
		Quaternion quaternion;
		if (skeletonTransformIsParent)
		{
			Transform transform2 = transform;
			float x = vector.x;
			float y = vector.y;
			float z;
			if (followSkeletonZPosition)
			{
				z = 0f;
			}
			else
			{
				Vector3 localPosition = transform.localPosition;
				z = localPosition.z;
			}
			transform2.localPosition = new Vector3(x, y, z);
			if (followRotation)
			{
				float f = num * 0.5f * 0.0174532924f;
				quaternion = default(Quaternion);
				Quaternion localRotation = quaternion;
				localRotation.z = Mathf.Sin(f);
				localRotation.w = Mathf.Cos(f);
				transform.localRotation = localRotation;
			}
		}
		else
		{
			Vector3 position = skeletonTransform.TransformPoint(new Vector3(vector.x, vector.y, 0f));
			if (!followSkeletonZPosition)
			{
				Vector3 position2 = transform.position;
				position.z = position2.z;
			}
			Transform parent = transform.parent;
			if ((Object)parent != (Object)null)
			{
				Matrix4x4 localToWorldMatrix = parent.localToWorldMatrix;
				if (localToWorldMatrix.m00 * localToWorldMatrix.m11 - localToWorldMatrix.m01 * localToWorldMatrix.m10 < 0f)
				{
					num = 0f - num;
				}
			}
			if (followRotation)
			{
				quaternion = skeletonTransform.rotation;
				Vector3 eulerAngles = quaternion.eulerAngles;
				transform.SetPositionAndRotation(position, Quaternion.Euler(eulerAngles.x, eulerAngles.y, eulerAngles.z + num));
			}
			else
			{
				transform.position = position;
			}
		}
		if (followSkeletonFlip)
		{
			Vector3 localScale = transform.localScale;
			localScale.y = Mathf.Abs(localScale.y) * ((!(bone.skeleton.flipX ^ bone.skeleton.flipY)) ? 1f : (-1f));
			transform.localScale = localScale;
		}
	}
}