├── .gitignore ├── CopySrc2Test ├── Engine.Editor ├── Engine.Editor.asmdef └── Src │ ├── Math │ └── Editor │ │ ├── EditorCreateLUT.cs │ │ ├── EditorGUILayoutExt.cs │ │ ├── EditorLFloat.cs │ │ ├── EditorLVector2.cs │ │ ├── EditorLVector3.cs │ │ └── EditorLVectorDrawTool.cs │ └── PathFinding │ └── Editor │ └── EditorNavMeshTool.cs ├── Engine.LockstepEngine ├── Engine.LockstepEngine.asmdef └── Src │ ├── BehaviourTree │ └── Src │ │ ├── Attribute.cs │ │ ├── BTActionLeaf.cs │ │ ├── BTBaseAction.cs │ │ ├── BTComposite.cs │ │ ├── BTNode.cs │ │ ├── BTPrecondition.cs │ │ ├── BTRunningStatus.cs │ │ ├── BTWorkingData.cs │ │ ├── Composite │ │ ├── BTActionLoop.cs │ │ ├── BTActionNonPrioritizedSelector.cs │ │ ├── BTActionParallel.cs │ │ ├── BTActionPrioritizedSelector.cs │ │ └── BTActionSequence.cs │ │ ├── Condition │ │ ├── BTCondition.cs │ │ ├── BTConditionFalse.cs │ │ └── BTConditionTrue.cs │ │ ├── Data │ │ ├── BTCActionLeaf.cs │ │ ├── BTCActionNonPrioritizedSelector.cs │ │ ├── BTCActionParallel.cs │ │ ├── BTCActionPrioritizedSelector.cs │ │ └── BTCActionSequence.cs │ │ ├── Decorator │ │ └── BTDecorator.cs │ │ ├── Factory │ │ ├── BTFactory.cs │ │ ├── BTInfo.cs │ │ └── EBTBuildInTypeIdx.cs │ │ ├── IBTContent.cs │ │ └── TAny.cs │ ├── Collision2D │ ├── CRigidbody.cs │ ├── CTransform2D.cs │ ├── ColliderData.cs │ ├── ColliderPart.cs │ ├── ColliderPrefab.cs │ ├── ColliderProxy.cs │ ├── CollisionHelper.cs │ ├── CollisionHelper1.cs │ ├── CollisionSystem.cs │ ├── CollisionSystem_Unity.cs │ ├── ICollisionSystem.cs │ ├── QuadTree │ │ ├── BoundQuadTree.cs │ │ ├── BoundQuadTreeNode.cs │ │ └── QuadTreeExt.cs │ ├── Shape │ │ ├── CAABB.cs │ │ ├── CBaseShape.cs │ │ ├── CCircle.cs │ │ ├── COBB.cs │ │ ├── CPolygon.cs │ │ ├── CRay.cs │ │ └── CSegment.cs │ └── Utils.cs │ ├── ECS.ECDefine │ ├── Attributions.cs │ ├── Interfaces.cs │ └── Structs.cs │ ├── Logging │ └── Src │ │ ├── BaseLogger.cs │ │ ├── Debug.cs │ │ ├── LogEventArgs.cs │ │ ├── LogSeverity.cs │ │ └── Logger.cs │ ├── Math │ ├── BaseType │ │ ├── LAxis2D.cs │ │ ├── LAxis3D.cs │ │ ├── LFloat.cs │ │ ├── LMatrix33.cs │ │ ├── LQuaternion.cs │ │ ├── LRect.cs │ │ ├── LVector2.cs │ │ ├── LVector2Int.cs │ │ ├── LVector3.cs │ │ └── LVector3Int.cs │ ├── HashCodeExtension.cs │ ├── LMath.cs │ ├── LMathExtension.cs │ ├── LMathExtension2.cs │ ├── LMath_Vector.cs │ ├── LRandom.cs │ ├── LUT │ │ ├── LUTAcos.cs │ │ ├── LUTAsin.cs │ │ ├── LUTAtan2.cs │ │ ├── LUTCos.cs │ │ └── LUTSin.cs │ └── PrimerLUT.cs │ ├── NetMsg.Common │ └── Src │ │ ├── DictExtensions.cs │ │ ├── EMsgSC.cs │ │ ├── ExtensionMsg.cs │ │ ├── MsgDefine.cs │ │ ├── MsgDefine_Login.cs │ │ ├── NetworkDefine.cs │ │ └── Udp │ │ ├── InputCmd.cs │ │ ├── Msg_PlayerInput.cs │ │ ├── MutilDiscFrames.cs │ │ ├── MutilFrames.cs │ │ └── ServerFrame.cs │ ├── Network │ ├── AChannel.cs │ ├── AService.cs │ ├── Circularbuffer.cs │ ├── ErrorCode.cs │ ├── IMessage.cs │ ├── IMessageDispatcher.cs │ ├── IMessagePacker.cs │ ├── Log.cs │ ├── NetworkHelper.cs │ ├── NetworkProxy.cs │ ├── OneThreadSynchronizationContext.cs │ └── TCP │ │ ├── PacketParser.cs │ │ ├── TChannel.cs │ │ └── TService.cs │ ├── PathFinding │ ├── BSP │ │ ├── BspNode.cs │ │ ├── BspTree.cs │ │ ├── ESplitType.cs │ │ ├── SplitPlane.cs │ │ └── TriRef.cs │ └── NavMesh │ │ ├── Geometry │ │ ├── GeometryUtil.cs │ │ ├── Plane.cs │ │ └── Ray.cs │ │ ├── NavMesh │ │ ├── EdgePoint.cs │ │ ├── Funnel.cs │ │ ├── Triangle.cs │ │ ├── TriangleData.cs │ │ ├── TriangleEdge.cs │ │ ├── TriangleGraph.cs │ │ ├── TriangleGraphPath.cs │ │ ├── TriangleHeuristic.cs │ │ ├── TriangleNavMesh.cs │ │ └── TrianglePointPath.cs │ │ ├── PathFinder │ │ ├── Connection.cs │ │ ├── DefaultGraphPath.cs │ │ ├── Graph.cs │ │ ├── GraphPath.cs │ │ ├── Heuristic.cs │ │ ├── IndexedAStarPathFinder.cs │ │ ├── IndexedGraph.cs │ │ ├── NavMesh.cs │ │ ├── NavMeshData.cs │ │ ├── NodeBinaryHeap.cs │ │ └── PathFinder.cs │ │ └── VectorExtension.cs │ ├── Serializaition │ └── Src │ │ ├── BaseMsg.cs │ │ ├── ByteHelper.cs │ │ ├── Compressor.cs │ │ ├── Deserializer.cs │ │ ├── FastBitConverter.cs │ │ ├── NetMsgExtension.cs │ │ ├── Serializer.cs │ │ └── TestSerializationExt.cs │ ├── Services │ ├── Core │ │ ├── IService.cs │ │ ├── IServiceContainer.cs │ │ ├── ITimeMachine.cs │ │ └── ITimeMachineService.cs │ ├── Interfaces │ │ ├── IECSFactoryService.cs │ │ ├── IHashCode.cs │ │ ├── IIdService.cs │ │ └── IRandomService.cs │ └── Services │ │ ├── IdService.cs │ │ ├── RandomService.cs │ │ ├── ServiceContainer.cs │ │ └── TimeMachineContainer.cs │ ├── TableReader │ ├── TableData.cs │ ├── TableHelper.cs │ ├── TableInfo.cs │ ├── TableManager.cs │ └── TableRowInfo.cs │ └── Util │ ├── ProjectUtil.cs │ └── Src │ ├── CodeGenUtil.cs │ ├── CoroutineHelper.cs │ ├── ECS.cs │ ├── JsonUtil.cs │ ├── LTime.cs │ ├── LTimer.cs │ ├── LitJson │ ├── IJsonWrapper.cs │ ├── JsonData.cs │ ├── JsonException.cs │ ├── JsonMapper.cs │ ├── JsonMockWrapper.cs │ ├── JsonReader.cs │ ├── JsonWriter.cs │ ├── Lexer.cs │ ├── Netstandard15Polyfill.cs │ └── ParserToken.cs │ ├── NativeUtil │ ├── Buffer.cs │ ├── NativeHelper.cs │ └── NativePool.cs │ ├── NetworkHelper.cs │ ├── PathUtil.cs │ ├── Pool.cs │ ├── Profiler.cs │ ├── ReflectionUtility.cs │ └── Util.cs ├── Engine.View ├── Engine.View.asmdef └── Src │ ├── Collision2D │ ├── ColliderDataMono.cs │ └── DebugExtension.cs │ ├── NavMesh │ ├── LVectorExtension.cs │ └── NavMeshTool.cs │ └── UnityLogHandler.cs ├── README.md └── Test.Unity ├── .gitignore └── ProjectSettings ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── Physics2DSettings.asset ├── PresetManager.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset ├── UnityConnectSettings.asset ├── VFXManager.asset └── XRSettings.asset /.gitignore: -------------------------------------------------------------------------------- 1 | Games/ 2 | Unity/DumpStr/ 3 | DumpLog/ 4 | TempCode/ 5 | #暂时忽略这个项目 6 | BombMan/ 7 | # Build and Object Folders 8 | bin/ 9 | obj/ 10 | #数据库文件不提交 11 | *.db 12 | # Nuget packages directory 13 | packages/ 14 | # ide 15 | .idea/ 16 | .vs/ 17 | ## Ignore Visual Studio temporary files, build results, and 18 | ## files generated by popular Visual Studio add-ons. 19 | 20 | # User-specific files 21 | *.suo 22 | *.user 23 | *.sln.docstates 24 | 25 | # Build results 26 | [Dd]ebug/ 27 | [Rr]elease/ 28 | x64/ 29 | *_i.c 30 | *_p.c 31 | *.ilk 32 | *.obj 33 | *.pch 34 | *.pdb 35 | *.pgc 36 | *.pgd 37 | *.rsp 38 | *.sbr 39 | *.tlb 40 | *.tli 41 | *.tlh 42 | *.tmp 43 | *.log 44 | *.vspscc 45 | *.vssscc 46 | .builds 47 | 48 | # Visual C++ cache files 49 | ipch/ 50 | *.aps 51 | *.ncb 52 | *.opensdf 53 | *.sdf 54 | 55 | # Visual Studio profiler 56 | *.psess 57 | *.vsp 58 | *.vspx 59 | 60 | # Guidance Automation Toolkit 61 | *.gpState 62 | 63 | # ReSharper is a .NET coding add-in 64 | _ReSharper* 65 | 66 | # NCrunch 67 | *.ncrunch* 68 | .*crunch*.local.xml 69 | 70 | # Installshield output folder 71 | [Ee]xpress 72 | 73 | # DocProject is a documentation generator add-in 74 | DocProject/buildhelp/ 75 | DocProject/Help 76 | UpgradeLog*.XML 77 | 78 | # Lightswitch 79 | _Pvt_Extensions 80 | GeneratedArtifacts 81 | *.xap 82 | ModelManifest.xml 83 | 84 | #Backup file 85 | *.bak -------------------------------------------------------------------------------- /CopySrc2Test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | clear 3 | dir="$(cd $(dirname ${BASH_SOURCE[0]}) && pwd)" 4 | cd $dir/ 5 | pwd 6 | 7 | find ./Engine.Editor/ -name '*.meta' -type f | xargs rm -f 8 | find ./Engine.View/ -name '*.meta' -type f | xargs rm -f 9 | find ./Engine.LockstepEngine/ -name '*.meta' -type f | xargs rm -f 10 | rm -rf ./Test.Unity/Assets/* 11 | mkdir -p ./Test.Unity/Assets/ 12 | cp -rf ./Engine.Editor ./Test.Unity/Assets/ 13 | cp -rf ./Engine.View ./Test.Unity/Assets/ 14 | cp -rf ./Engine.LockstepEngine ./Test.Unity/Assets/ 15 | -------------------------------------------------------------------------------- /Engine.Editor/Engine.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Engine.Editor", 3 | "references": [ 4 | "Engine.LockstepEngine", 5 | "Engine.View", 6 | "Unity.Entities", 7 | "Unity.Entities.Hybrid", 8 | "Unity.Mathematics", 9 | "Unity.Transforms", 10 | "Unity.Jobs", 11 | "Unity.Collections", 12 | "Unity.Burst" 13 | ], 14 | "allowUnsafeCode": true 15 | } 16 | -------------------------------------------------------------------------------- /Engine.Editor/Src/Math/Editor/EditorGUILayoutExt.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | #if UNITY_EDITOR 4 | using UnityEngine; 5 | using Lockstep.Math; 6 | 7 | namespace UnityEditor { 8 | public static class EditorGUILayoutExt { 9 | public static LFloat FloatField( string label,LFloat value,params GUILayoutOption[] options){ 10 | return EditorGUILayout.FloatField(label, value.ToFloat(),options).ToLFloat(); 11 | } 12 | public static LVector2 Vector2Field( string label,LVector2 value,params GUILayoutOption[] options){ 13 | return EditorGUILayout.Vector2Field(label, value.ToVector2(),options).ToLVector2(); 14 | } 15 | public static LVector3 Vector3Field( string label,LVector3 value,params GUILayoutOption[] options){ 16 | return EditorGUILayout.Vector3Field(label, value.ToVector3(),options).ToLVector3(); 17 | } 18 | } 19 | } 20 | #endif -------------------------------------------------------------------------------- /Engine.Editor/Src/Math/Editor/EditorLFloat.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | #if UNITY_EDITOR 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using Lockstep.Math; 7 | using UnityEngine; 8 | using UnityEditor; 9 | 10 | [CustomPropertyDrawer(typeof(LFloat))] 11 | public class EditorLFloat : UnityEditor.PropertyDrawer { 12 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label){ 13 | var xProperty = property.FindPropertyRelative("_val"); 14 | float LabelWidth = EditorGUIUtility.labelWidth - EditorLVectorDrawTool.LableWidthOffset; 15 | float lableWid = EditorLVectorDrawTool.LableWid; 16 | var labelRect = new Rect(position.x, position.y, LabelWidth, position.height); 17 | EditorGUI.LabelField(labelRect, label); 18 | float filedWid = (position.width - LabelWidth); 19 | float initX = position.x + LabelWidth; 20 | var valRect = new Rect(initX, position.y, filedWid, position.height); 21 | var fVal = EditorGUI.FloatField(valRect, xProperty.intValue * 1.0f / LFloat.Precision); 22 | xProperty.intValue = (int) (fVal * LFloat.Precision); 23 | } 24 | } 25 | #endif -------------------------------------------------------------------------------- /Engine.Editor/Src/Math/Editor/EditorLVector2.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | #if UNITY_EDITOR 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using Lockstep.Math; 7 | using UnityEngine; 8 | using UnityEditor; 9 | 10 | [CustomPropertyDrawer(typeof(LVector2))] 11 | public class EditorLVector2 : UnityEditor.PropertyDrawer { 12 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label){ 13 | var xProperty = property.FindPropertyRelative("_x"); 14 | var yProperty = property.FindPropertyRelative("_y"); 15 | float LabelWidth = EditorGUIUtility.labelWidth - EditorLVectorDrawTool.LableWidthOffset; 16 | float lableWid = EditorLVectorDrawTool.LableWid; 17 | 18 | var labelRect = new Rect(position.x, position.y, LabelWidth, position.height); 19 | EditorGUI.LabelField(labelRect, label); 20 | float filedWid = (position.width - LabelWidth) / 2 - lableWid; 21 | float initX = position.x + LabelWidth; 22 | float offset = 0; 23 | EditorLVectorDrawTool.DrawField(position, initX, ref offset, lableWid, filedWid, xProperty, new GUIContent("x:")); 24 | EditorLVectorDrawTool.DrawField(position, initX, ref offset, lableWid, filedWid, yProperty, new GUIContent("y:")); 25 | } 26 | } 27 | #endif -------------------------------------------------------------------------------- /Engine.Editor/Src/Math/Editor/EditorLVector3.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | #if UNITY_EDITOR 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using Lockstep.Math; 7 | using UnityEngine; 8 | using UnityEditor; 9 | 10 | 11 | [CustomPropertyDrawer(typeof(LVector3))] 12 | public class EditorLVector3 : UnityEditor.PropertyDrawer { 13 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label){ 14 | var xProperty = property.FindPropertyRelative("_x"); 15 | var yProperty = property.FindPropertyRelative("_y"); 16 | var zProperty = property.FindPropertyRelative("_z"); 17 | float LabelWidth = EditorGUIUtility.labelWidth - EditorLVectorDrawTool.LableWidthOffset; 18 | float lableWid = EditorLVectorDrawTool.LableWid; 19 | 20 | var labelRect = new Rect(position.x, position.y, LabelWidth, position.height); 21 | EditorGUI.LabelField(labelRect, label); 22 | float filedWid = (position.width - LabelWidth) / 3 - lableWid; 23 | float initX = position.x + LabelWidth; 24 | float offset = 0; 25 | EditorLVectorDrawTool.DrawField(position, initX, ref offset, lableWid, filedWid, xProperty, new GUIContent("x:")); 26 | EditorLVectorDrawTool.DrawField(position, initX, ref offset, lableWid, filedWid, yProperty, new GUIContent("y:")); 27 | EditorLVectorDrawTool.DrawField(position, initX, ref offset, lableWid, filedWid, zProperty, new GUIContent("z:")); 28 | } 29 | } 30 | #endif -------------------------------------------------------------------------------- /Engine.Editor/Src/Math/Editor/EditorLVectorDrawTool.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | #if UNITY_EDITOR 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using Lockstep.Math; 7 | using UnityEngine; 8 | using UnityEditor; 9 | 10 | public static class EditorLVectorDrawTool { 11 | public const float LableWidthOffset = 45; 12 | public const float LableWid = 20; 13 | 14 | public static void DrawField(Rect position, float initX, ref float offset, float lableWid, float filedWid, 15 | SerializedProperty property, GUIContent label){ 16 | var lableRect = new Rect(initX + offset, position.y, 70, position.height); 17 | EditorGUI.LabelField(lableRect, label.text); 18 | var valRect = new Rect(initX + offset + lableWid, position.y, filedWid, position.height); 19 | var fVal = EditorGUI.FloatField(valRect, property.intValue * 1.0f / LFloat.Precision); 20 | property.intValue = (int) (fVal * LFloat.Precision); 21 | offset += filedWid + lableWid; 22 | } 23 | } 24 | #endif -------------------------------------------------------------------------------- /Engine.LockstepEngine/Engine.LockstepEngine.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Engine.LockstepEngine", 3 | "references": [], 4 | "includePlatforms": [], 5 | "excludePlatforms": [], 6 | "allowUnsafeCode": true, 7 | "overrideReferences": false, 8 | "precompiledReferences": [], 9 | "autoReferenced": true, 10 | "defineConstraints": [], 11 | "versionDefines": [] 12 | } 13 | -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Attribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | 5 | namespace Lockstep.BehaviourTree { 6 | 7 | [AttributeUsage(AttributeTargets.Class,Inherited = false)] 8 | public class StringInfoAttribute : Attribute { 9 | public int idx = 0; 10 | public string menu; 11 | 12 | public StringInfoAttribute(string menu,int idx){ 13 | this.menu = menu; 14 | this.idx = idx; 15 | } 16 | } 17 | 18 | [AttributeUsage(AttributeTargets.Class,Inherited = false)] 19 | public class BuildInNodeAttribute : StringInfoAttribute { 20 | public BuildInNodeAttribute(string menu,EBTBuildInTypeIdx eidx) : base(menu,(int) eidx){ } 21 | 22 | public BuildInNodeAttribute(Type type,EBTBuildInTypeIdx eidx): base(type.Name,(int) eidx){ 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/BTActionLeaf.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace Lockstep.BehaviourTree { 7 | public abstract unsafe partial class BTActionLeaf : BTAction { 8 | private const int ACTION_READY = 0; 9 | private const int ACTION_RUNNING = 1; 10 | private const int ACTION_FINISHED = 2; 11 | 12 | public override object[] GetRuntimeData(BTWorkingData wData){ 13 | return new object[] {*(BTCActionLeaf*) wData.GetContext(_uniqueKey)}; 14 | } 15 | 16 | protected override int MemSize => sizeof(BTCActionLeaf); 17 | public override Type DataType => typeof(BTCActionLeaf); 18 | 19 | public BTActionLeaf() 20 | : base(0){ } 21 | 22 | protected sealed override int OnUpdate(BTWorkingData wData){ 23 | int runningState = BTRunningStatus.FINISHED; 24 | var thisContext = (BTCActionLeaf*) wData.GetContext(_uniqueKey); 25 | #if DEBUG 26 | BTCActionLeaf __DEBUGval = *thisContext; 27 | #endif 28 | if (thisContext->status == ACTION_READY) { 29 | OnEnter(wData); 30 | thisContext->needExit = true; 31 | thisContext->status = ACTION_RUNNING; 32 | } 33 | 34 | if (thisContext->status == ACTION_RUNNING) { 35 | runningState = OnExecute(wData); 36 | if (BTRunningStatus.IsFinished(runningState)) { 37 | thisContext->status = ACTION_FINISHED; 38 | } 39 | } 40 | 41 | if (thisContext->status == ACTION_FINISHED) { 42 | if (thisContext->needExit) { 43 | OnExit(wData, runningState); 44 | } 45 | 46 | thisContext->status = ACTION_READY; 47 | thisContext->needExit = false; 48 | } 49 | 50 | return runningState; 51 | } 52 | 53 | protected sealed override void OnTransition(BTWorkingData wData){ 54 | var thisContext = (BTCActionLeaf*) wData.GetContext(_uniqueKey); 55 | if (thisContext->needExit) { 56 | OnExit(wData, BTRunningStatus.TRANSITION); 57 | } 58 | 59 | thisContext->status = ACTION_READY; 60 | thisContext->needExit = false; 61 | } 62 | 63 | protected void* GetUserContextData(BTWorkingData wData){ 64 | return ((byte*) wData.GetContext(_uniqueKey) + sizeof(BTCActionLeaf)); 65 | } 66 | 67 | //-------------------------------------------------------- 68 | // inherented by children- 69 | protected virtual void OnEnter( /*in*/ BTWorkingData wData){ } 70 | 71 | protected virtual int OnExecute(BTWorkingData wData){ 72 | return BTRunningStatus.FINISHED; 73 | } 74 | 75 | protected virtual void OnExit(BTWorkingData wData, int runningStatus){ } 76 | } 77 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/BTBaseAction.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using Lockstep.Serialization; 6 | 7 | namespace Lockstep.BehaviourTree { 8 | public class BTActionContext { } 9 | 10 | public abstract unsafe partial class BTAction : BTNode { 11 | 12 | //------------------------------------------------------------- 13 | public BTAction(int maxChildCount) 14 | : base(maxChildCount){ 15 | } 16 | 17 | ~BTAction(){ 18 | Precondition = null; 19 | } 20 | 21 | //------------------------------------------------------------- 22 | public bool Evaluate( /*in*/ BTWorkingData wData){ 23 | return (Precondition == null || Precondition.IsTrue(wData)) && OnEvaluate(wData); 24 | } 25 | 26 | public int Update(BTWorkingData wData){ 27 | wData.HasVisitedInfos[_uniqueKey] = true; 28 | return OnUpdate(wData); 29 | } 30 | 31 | public void Transition(BTWorkingData wData){ 32 | OnTransition(wData); 33 | } 34 | 35 | public BTAction SetPrecondition(BTPrecondition precondition){ 36 | Precondition = precondition; 37 | return this; 38 | } 39 | 40 | public override int GetHashCode(){ 41 | return _uniqueKey; 42 | } 43 | 44 | //-------------------------------------------------------- 45 | // inherented by children 46 | protected virtual bool OnEvaluate( /*in*/ BTWorkingData wData){ 47 | return true; 48 | } 49 | 50 | protected virtual int OnUpdate(BTWorkingData wData){ 51 | return BTRunningStatus.FINISHED; 52 | } 53 | 54 | protected virtual void OnTransition(BTWorkingData wData){ } 55 | } 56 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/BTComposite.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.BehaviourTree { 4 | public partial class BTComposite : BTAction { 5 | public BTComposite(int maxChildCount) 6 | : base(maxChildCount){ } 7 | public BTComposite( ) 8 | : this(int.MaxValue){ } 9 | } 10 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/BTPrecondition.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | 5 | namespace Lockstep.BehaviourTree { 6 | //--------------------------------------------------------------- 7 | public abstract unsafe partial class BTPrecondition : BTNode { 8 | public BTPrecondition(int maxChildCount) 9 | : base(maxChildCount){ } 10 | 11 | public abstract bool IsTrue( /*in*/ BTWorkingData wData); 12 | } 13 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/BTRunningStatus.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | 5 | namespace Lockstep.BehaviourTree { 6 | public unsafe partial class BTRunningStatus { 7 | //------------------------------------------------------- 8 | //Any value which is below ZERO means error occurs 9 | //------------------------------------------------------- 10 | //default running status 11 | public const int EXECUTING = 0; 12 | public const int FINISHED = 1; 13 | 14 | public const int TRANSITION = 2; 15 | 16 | //------------------------------------------------------- 17 | //User running status 18 | //50-100, reserved user executing status 19 | public const int USER_EXECUTING = 50; 20 | 21 | //>=100, reserved user finished status 22 | public const int USER_FINISHED = 100; 23 | 24 | //------------------------------------------------------- 25 | public static bool IsOK(int runningStatus){ 26 | return runningStatus == BTRunningStatus.FINISHED || 27 | runningStatus >= BTRunningStatus.USER_FINISHED; 28 | } 29 | 30 | public static bool IsError(int runningStatus){ 31 | return runningStatus < 0; 32 | } 33 | 34 | public static bool IsFinished(int runningStatus){ 35 | return IsOK(runningStatus) || IsError(runningStatus); 36 | } 37 | 38 | public static bool IsExecuting(int runningStatus){ 39 | return !IsFinished(runningStatus); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/BTWorkingData.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using Lockstep.Logging; 6 | using Lockstep.Util; 7 | 8 | namespace Lockstep.BehaviourTree { 9 | public unsafe partial class BTWorkingData : TAny { 10 | ~BTWorkingData(){ 11 | if (_pDatas != null) { 12 | NativeHelper.Free(new IntPtr(_pDatas)); 13 | _pDatas = null; 14 | } 15 | } 16 | 17 | public byte* _pDatas = null; 18 | private int[] _dataOffset; 19 | public bool[] HasVisitedInfos; 20 | public int _dataLen = 0; 21 | 22 | public void ClearRunTimeInfo(){ 23 | #if DEBUG 24 | for (int i = 0; i < HasVisitedInfos.Length; i++) { 25 | HasVisitedInfos[i] = false; 26 | } 27 | #endif 28 | } 29 | 30 | public unsafe void* GetContext(int idx){ 31 | var offset = _dataOffset[idx]; 32 | Debug.Assert(offset >= 0 && offset < _dataLen, " out of range"); 33 | return _pDatas + offset; 34 | } 35 | 36 | public void Init(int[] offsets, int totalMemSize){ 37 | _pDatas = NativeHelper.AllocAndZero(totalMemSize); 38 | _dataOffset = offsets; 39 | HasVisitedInfos = new bool[offsets.Length]; 40 | _dataLen = totalMemSize; 41 | } 42 | 43 | public BTWorkingData Clone(){ 44 | var ret = new BTWorkingData(); 45 | ret.Init(this._dataOffset, this._dataLen); 46 | NativeHelper.Copy(this._pDatas, ret._pDatas, _dataLen); 47 | return ret; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Composite/BTActionLoop.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Runtime.InteropServices; 5 | using Lockstep.Util; 6 | 7 | namespace Lockstep.BehaviourTree 8 | { 9 | [BuildInNode(typeof(BTActionLoop),EBTBuildInTypeIdx.BTActionLoop)] 10 | public unsafe partial class BTActionLoop : BTComposite 11 | { 12 | public const int INFINITY = -1; 13 | [StructLayout(LayoutKind.Sequential, Pack = NativeHelper.STRUCT_PACK)] 14 | public unsafe partial struct BTActionLoopContext 15 | { 16 | internal int currentCount; 17 | } 18 | //-------------------------------------------------------- 19 | private int _loopCount; 20 | //-------------------------------------------------------- 21 | public BTActionLoop() 22 | : base(1) 23 | { 24 | _loopCount = INFINITY; 25 | } 26 | public BTActionLoop SetLoopCount(int count) 27 | { 28 | _loopCount = count; 29 | return this; 30 | } 31 | //------------------------------------------------------- 32 | protected override bool OnEvaluate(/*in*/BTWorkingData wData) 33 | { 34 | var thisContext = (BTActionLoopContext*)wData.GetContext(_uniqueKey); 35 | bool checkLoopCount = (_loopCount == INFINITY || thisContext->currentCount < _loopCount); 36 | if (checkLoopCount == false) { 37 | return false; 38 | } 39 | if (IsIndexValid(0)) { 40 | BTAction node = GetChild(0); 41 | return node.Evaluate(wData); 42 | } 43 | return false; 44 | } 45 | protected override int OnUpdate(BTWorkingData wData) 46 | { 47 | var thisContext = (BTActionLoopContext*)wData.GetContext(_uniqueKey); 48 | int runningStatus = BTRunningStatus.FINISHED; 49 | if (IsIndexValid(0)) { 50 | BTAction node = GetChild(0); 51 | runningStatus = node.Update(wData); 52 | if (BTRunningStatus.IsFinished(runningStatus)) { 53 | thisContext->currentCount++; 54 | if (thisContext->currentCount < _loopCount || _loopCount == INFINITY) { 55 | runningStatus = BTRunningStatus.EXECUTING; 56 | } 57 | } 58 | } 59 | return runningStatus; 60 | } 61 | protected override void OnTransition(BTWorkingData wData) 62 | { 63 | var thisContext = (BTActionLoopContext*)wData.GetContext(_uniqueKey); 64 | if (IsIndexValid(0)) { 65 | BTAction node = GetChild(0); 66 | node.Transition(wData); 67 | } 68 | thisContext->currentCount = 0; 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Composite/BTActionNonPrioritizedSelector.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace Lockstep.BehaviourTree { 7 | [BuildInNode(typeof(BTActionNonPrioritizedSelector), EBTBuildInTypeIdx.BTActionNonPrioritizedSelector)] 8 | public unsafe partial class BTActionNonPrioritizedSelector : BTActionPrioritizedSelector { 9 | public override object[] GetRuntimeData(BTWorkingData wData){ 10 | return new object[] { 11 | *(BTCActionNonPrioritizedSelector*) wData.GetContext(_uniqueKey), 12 | }; 13 | } 14 | 15 | protected override int MemSize => sizeof(BTCActionNonPrioritizedSelector); 16 | public override Type DataType => typeof(BTCActionNonPrioritizedSelector); 17 | 18 | 19 | 20 | protected override bool OnEvaluate( /*in*/ BTWorkingData wData){ 21 | var thisContext = (BTCActionNonPrioritizedSelector*) wData.GetContext(_uniqueKey); 22 | //check last node first 23 | if (IsIndexValid(thisContext->currentSelectedIndex)) { 24 | BTAction node = GetChild(thisContext->currentSelectedIndex); 25 | if (node.Evaluate(wData)) { 26 | return true; 27 | } 28 | } 29 | 30 | return base.OnEvaluate(wData); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Composite/BTActionPrioritizedSelector.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace Lockstep.BehaviourTree { 7 | [BuildInNode(typeof(BTActionPrioritizedSelector),EBTBuildInTypeIdx.BTActionPrioritizedSelector)] 8 | public unsafe partial class BTActionPrioritizedSelector : BTComposite { 9 | public override object[] GetRuntimeData(BTWorkingData wData){ 10 | return new object[] { 11 | *(BTCActionPrioritizedSelector*) wData.GetContext(_uniqueKey), 12 | }; 13 | } 14 | public override Type DataType => typeof(BTCActionPrioritizedSelector); 15 | protected override int MemSize => sizeof(BTCActionPrioritizedSelector); 16 | 17 | 18 | protected override bool OnEvaluate( /*in*/ BTWorkingData wData){ 19 | var thisContext = (BTCActionPrioritizedSelector*) wData.GetContext(_uniqueKey); 20 | thisContext->currentSelectedIndex = -1; 21 | int childCount = GetChildCount(); 22 | for (int i = 0; i < childCount; ++i) { 23 | BTAction node = GetChild(i); 24 | if (node.Evaluate(wData)) { 25 | thisContext->currentSelectedIndex = i; 26 | return true; 27 | } 28 | } 29 | 30 | return false; 31 | } 32 | 33 | protected override int OnUpdate(BTWorkingData wData){ 34 | var thisContext = (BTCActionPrioritizedSelector*) wData.GetContext(_uniqueKey); 35 | int runningState = BTRunningStatus.FINISHED; 36 | if (thisContext->currentSelectedIndex != thisContext->lastSelectedIndex) { 37 | if (IsIndexValid(thisContext->lastSelectedIndex)) { 38 | BTAction node = GetChild(thisContext->lastSelectedIndex); 39 | node.Transition(wData); 40 | } 41 | 42 | thisContext->lastSelectedIndex = thisContext->currentSelectedIndex; 43 | } 44 | 45 | if (IsIndexValid(thisContext->lastSelectedIndex)) { 46 | BTAction node = GetChild(thisContext->lastSelectedIndex); 47 | runningState = node.Update(wData); 48 | if (BTRunningStatus.IsFinished(runningState)) { 49 | thisContext->lastSelectedIndex = -1; 50 | } 51 | } 52 | 53 | return runningState; 54 | } 55 | 56 | protected override void OnTransition(BTWorkingData wData){ 57 | var thisContext = (BTCActionPrioritizedSelector*) wData.GetContext(_uniqueKey); 58 | BTAction node = GetChild(thisContext->lastSelectedIndex); 59 | if (node != null) { 60 | node.Transition(wData); 61 | } 62 | 63 | thisContext->lastSelectedIndex = -1; 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Composite/BTActionSequence.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace Lockstep.BehaviourTree { 7 | [BuildInNode(typeof(BTActionSequence), EBTBuildInTypeIdx.BTActionSequence)] 8 | public unsafe partial class BTActionSequence : BTComposite { 9 | public override object[] GetRuntimeData(BTWorkingData wData){ 10 | return new object[] { 11 | *(BTCActionSequence*) wData.GetContext(_uniqueKey), 12 | }; 13 | } 14 | protected override int MemSize => sizeof(BTCActionSequence); 15 | 16 | public override Type DataType => typeof(BTCActionSequence); 17 | 18 | //------------------------------------------------------- 19 | private bool _continueIfErrorOccors; 20 | 21 | //------------------------------------------------------- 22 | public BTActionSequence(){ 23 | _continueIfErrorOccors = false; 24 | } 25 | 26 | public BTActionSequence SetContinueIfErrorOccors(bool v){ 27 | _continueIfErrorOccors = v; 28 | return this; 29 | } 30 | 31 | //------------------------------------------------------ 32 | protected override bool OnEvaluate( /*in*/ BTWorkingData wData){ 33 | var thisContext = (BTCActionSequence*) wData.GetContext(_uniqueKey); 34 | int checkedNodeIndex = -1; 35 | if (IsIndexValid(thisContext->currentSelectedIndex)) { 36 | checkedNodeIndex = thisContext->currentSelectedIndex; 37 | } 38 | else { 39 | checkedNodeIndex = 0; 40 | } 41 | 42 | if (IsIndexValid(checkedNodeIndex)) { 43 | BTAction node = GetChild(checkedNodeIndex); 44 | if (node.Evaluate(wData)) { 45 | thisContext->currentSelectedIndex = checkedNodeIndex; 46 | return true; 47 | } 48 | } 49 | 50 | return false; 51 | } 52 | 53 | protected override int OnUpdate(BTWorkingData wData){ 54 | var thisContext = (BTCActionSequence*) wData.GetContext(_uniqueKey); 55 | int runningStatus = BTRunningStatus.FINISHED; 56 | BTAction node = GetChild(thisContext->currentSelectedIndex); 57 | runningStatus = node.Update(wData); 58 | if (_continueIfErrorOccors == false && BTRunningStatus.IsError(runningStatus)) { 59 | thisContext->currentSelectedIndex = -1; 60 | return runningStatus; 61 | } 62 | 63 | if (BTRunningStatus.IsFinished(runningStatus)) { 64 | thisContext->currentSelectedIndex++; 65 | if (IsIndexValid(thisContext->currentSelectedIndex)) { 66 | runningStatus = BTRunningStatus.EXECUTING; 67 | } 68 | else { 69 | thisContext->currentSelectedIndex = -1; 70 | } 71 | } 72 | 73 | return runningStatus; 74 | } 75 | 76 | protected override void OnTransition(BTWorkingData wData){ 77 | var thisContext = (BTCActionSequence*) wData.GetContext(_uniqueKey); 78 | BTAction node = GetChild(thisContext->currentSelectedIndex); 79 | if (node != null) { 80 | node.Transition(wData); 81 | } 82 | 83 | thisContext->currentSelectedIndex = -1; 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Condition/BTCondition.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.BehaviourTree { 4 | public abstract partial class BTCondition : BTPrecondition { 5 | public BTCondition() 6 | : base(0){ } 7 | } 8 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Condition/BTConditionFalse.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.BehaviourTree { 4 | [BuildInNode(typeof(BTConditionFalse),EBTBuildInTypeIdx.BTConditionFalse)] 5 | public partial class BTConditionFalse : BTCondition { 6 | public override bool IsTrue( /*in*/ BTWorkingData wData){ 7 | return false; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Condition/BTConditionTrue.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.BehaviourTree { 4 | [BuildInNode(typeof(BTConditionTrue),EBTBuildInTypeIdx.BTConditionTrue)] 5 | public partial class BTConditionTrue : BTCondition { 6 | public override bool IsTrue( /*in*/ BTWorkingData wData){ 7 | return true; 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Data/BTCActionLeaf.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.Runtime.InteropServices; 4 | using Lockstep.Util; 5 | 6 | namespace Lockstep.BehaviourTree { 7 | [StructLayout(LayoutKind.Sequential, Pack = NativeHelper.STRUCT_PACK)] 8 | public unsafe partial struct BTCActionLeaf : IBTContent { 9 | internal int status; 10 | internal bool needExit; 11 | } 12 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Data/BTCActionNonPrioritizedSelector.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.Runtime.InteropServices; 4 | using Lockstep.Util; 5 | 6 | namespace Lockstep.BehaviourTree { 7 | [StructLayout(LayoutKind.Sequential, Pack = NativeHelper.STRUCT_PACK)] 8 | public unsafe partial struct BTCActionNonPrioritizedSelector :IBTContent{ 9 | public int currentSelectedIndex; 10 | public int lastSelectedIndex; 11 | 12 | public BTCActionNonPrioritizedSelector(int curIdx = -1, int lastIdx = -1){ 13 | currentSelectedIndex = curIdx; 14 | lastSelectedIndex = lastIdx; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Data/BTCActionParallel.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | #pragma warning disable 0169 4 | using System; 5 | using System.Runtime.InteropServices; 6 | using Lockstep.Util; 7 | 8 | namespace Lockstep.BehaviourTree { 9 | [StructLayout(LayoutKind.Sequential, Pack = NativeHelper.STRUCT_PACK)] 10 | public unsafe partial struct BTCActionParallel:IBTContent { 11 | public struct BTCParallelStatusEval { 12 | public const int Size = 16; 13 | public fixed bool status[Size]; 14 | 15 | public void Init(bool val){ 16 | for (int i = 0; i < Size; i++) { 17 | fixed(bool* p = status) p[i] = val; 18 | } 19 | } 20 | 21 | void CheckIdx(Int32 index){ 22 | if (index < 0 || index >= Size) { 23 | NativeHelper.ArrayOutOfRange(); 24 | } 25 | } 26 | 27 | public bool this[int index] { 28 | get { 29 | CheckIdx(index); 30 | fixed (bool* p = status) return p[index]; 31 | } 32 | set { 33 | CheckIdx(index); 34 | fixed(bool* p = status) p[index] = value; 35 | } 36 | } 37 | } 38 | 39 | public unsafe struct BTCParallelStatusRunning { 40 | public const int Size = 16; 41 | public fixed byte status[Size]; 42 | 43 | public void Init(byte val){ 44 | for (int i = 0; i < Size; i++) { 45 | fixed(byte* p = status) p[i] = val; 46 | } 47 | } 48 | 49 | void CheckIdx(Int32 index){ 50 | if (index < 0 || index >= Size) { 51 | NativeHelper.ArrayOutOfRange(); 52 | } 53 | } 54 | 55 | public byte this[int index] { 56 | get { 57 | CheckIdx(index); 58 | fixed (byte* p = status) return p[index]; 59 | } 60 | set { 61 | CheckIdx(index); 62 | fixed(byte* p = status) p[index] = value; 63 | } 64 | } 65 | } 66 | 67 | internal BTCParallelStatusEval evaluationStatus; 68 | internal BTCParallelStatusRunning StatusRunning; 69 | } 70 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Data/BTCActionPrioritizedSelector.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.Runtime.InteropServices; 4 | using Lockstep.Util; 5 | 6 | namespace Lockstep.BehaviourTree { 7 | [StructLayout(LayoutKind.Sequential, Pack = NativeHelper.STRUCT_PACK)] 8 | public unsafe partial struct BTCActionPrioritizedSelector :IBTContent{ 9 | public int currentSelectedIndex; 10 | public int lastSelectedIndex; 11 | 12 | public BTCActionPrioritizedSelector(int curIdx = -1, int lastIdx = -1){ 13 | currentSelectedIndex = curIdx; 14 | lastSelectedIndex = lastIdx; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Data/BTCActionSequence.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.Runtime.InteropServices; 4 | using Lockstep.Util; 5 | 6 | namespace Lockstep.BehaviourTree { 7 | [StructLayout(LayoutKind.Sequential, Pack = NativeHelper.STRUCT_PACK)] 8 | public unsafe partial struct BTCActionSequence :IBTContent 9 | { 10 | internal int currentSelectedIndex; 11 | public BTCActionSequence(int idx = -1) 12 | { 13 | currentSelectedIndex = idx; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Decorator/BTDecorator.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.BehaviourTree { 4 | 5 | public abstract partial class BTPreconditionUnary : BTDecorator { 6 | public BTPreconditionUnary() 7 | : base(1){ } 8 | 9 | public BTPreconditionUnary(BTPrecondition lhs) 10 | : base(1){ 11 | AddChild(lhs); 12 | } 13 | } 14 | public abstract partial class BTDecorator : BTPrecondition { 15 | public BTDecorator(int maxChildCount) : base(maxChildCount){ } 16 | 17 | } 18 | 19 | public abstract partial class BTPreconditionBinary : BTDecorator { 20 | public BTPreconditionBinary() 21 | : base(2){ } 22 | 23 | public BTPreconditionBinary(BTPrecondition lhs, BTPrecondition rhs) 24 | : base(2){ 25 | AddChild(lhs).AddChild(rhs); 26 | } 27 | } 28 | 29 | 30 | //--------------------------------------------------------------- 31 | //unary precondition 32 | [BuildInNode(typeof(BTPreconditionNot),EBTBuildInTypeIdx.BTPreconditionNot)] 33 | public partial class BTPreconditionNot : BTPreconditionUnary { 34 | public BTPreconditionNot(){ } 35 | 36 | public BTPreconditionNot(BTPrecondition lhs, int uniqueKey) 37 | : base(lhs){ 38 | _uniqueKey = uniqueKey; 39 | } 40 | 41 | public override bool IsTrue( /*in*/ BTWorkingData wData){ 42 | return !GetChild(0).IsTrue(wData); 43 | } 44 | } 45 | 46 | //--------------------------------------------------------------- 47 | //binary precondition 48 | [BuildInNode(typeof(BTPreconditionAnd),EBTBuildInTypeIdx.BTPreconditionAnd)] 49 | public partial class BTPreconditionAnd : BTPreconditionBinary { 50 | public BTPreconditionAnd(){ } 51 | 52 | public BTPreconditionAnd(BTPrecondition lhs, BTPrecondition rhs, int uniqueKey) 53 | : base(lhs, rhs){ 54 | _uniqueKey = uniqueKey; 55 | } 56 | 57 | public override bool IsTrue( /*in*/ BTWorkingData wData){ 58 | return GetChild(0).IsTrue(wData) && 59 | GetChild(1).IsTrue(wData); 60 | } 61 | } 62 | 63 | [BuildInNode(typeof(BTPreconditionOr),EBTBuildInTypeIdx.BTPreconditionOr)] 64 | public partial class BTPreconditionOr : BTPreconditionBinary { 65 | public BTPreconditionOr(){ } 66 | 67 | public BTPreconditionOr(BTPrecondition lhs, BTPrecondition rhs, int uniqueKey) 68 | : base(lhs, rhs){ 69 | _uniqueKey = uniqueKey; 70 | } 71 | 72 | public override bool IsTrue( /*in*/ BTWorkingData wData){ 73 | return GetChild(0).IsTrue(wData) || 74 | GetChild(1).IsTrue(wData); 75 | } 76 | } 77 | 78 | [BuildInNode(typeof(BTPreconditionXor),EBTBuildInTypeIdx.BTPreconditionXor)] 79 | public partial class BTPreconditionXor : BTPreconditionBinary { 80 | public BTPreconditionXor(){ } 81 | 82 | public BTPreconditionXor(BTPrecondition lhs, BTPrecondition rhs, int uniqueKey) 83 | : base(lhs, rhs){ 84 | _uniqueKey = uniqueKey; 85 | } 86 | 87 | public override bool IsTrue( /*in*/ BTWorkingData wData){ 88 | return GetChild(0).IsTrue(wData) ^ 89 | GetChild(1).IsTrue(wData); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Factory/BTFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using Lockstep.BehaviourTree; 8 | using Lockstep.Logging; 9 | 10 | namespace Lockstep.BehaviourTree{ 11 | public partial class BTFactory { 12 | public static string FileExt = ".bytes"; 13 | public const short MaxBuildInIdx = (short)(int)EBTBuildInTypeIdx.MaxEnumCount; 14 | private static int _curIdx = 0; 15 | public static BTInfo CreateBtInfo(BTAction bt){ 16 | var offsets = bt.GetTotalOffsets(); 17 | var memSize = bt.GetTotalMemSize(); 18 | return new BTInfo() { 19 | MemSize = memSize, 20 | Offsets = offsets, 21 | RootNode = bt, 22 | }; 23 | } 24 | public static void BeforeCreateNode(){ 25 | _curIdx = 0; 26 | } 27 | public static T CreateNode() where T : BTNode, new(){ 28 | return new T() {UniqueKey = _curIdx++}; 29 | } 30 | 31 | public static Dictionary type2Id = new Dictionary(); 32 | public static Dictionary gameType2Id = new Dictionary(); 33 | 34 | public static void LogBuildInTypes(){ 35 | var types = typeof(BTFactory).Assembly.GetTypes().Where(t => typeof(BTNode).IsAssignableFrom(t) 36 | && !t.IsAbstract 37 | //&& t.Name.StartsWith("BT") 38 | ) ; 39 | StringBuilder sb = new StringBuilder(); 40 | int idx = -1; 41 | foreach (var type in types) { 42 | sb.AppendLine($"{{ typeof({type.Name}),{idx--.ToString()} }},"); 43 | } 44 | 45 | Debug.LogError(sb.ToString()); 46 | return; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/Factory/EBTBuildInTypeIdx.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.BehaviourTree { 4 | public enum EBTBuildInTypeIdx{ 5 | BTConditionFalse = 0 , 6 | BTConditionTrue = 1 , 7 | BTPreconditionNot = 2 , 8 | BTPreconditionAnd = 3 , 9 | BTPreconditionOr = 4 , 10 | BTPreconditionXor = 5 , 11 | BTActionLoop = 6 , 12 | BTActionNonPrioritizedSelector = 7 , 13 | BTActionParallel = 8 , 14 | BTActionPrioritizedSelector = 9 , 15 | BTActionSequence = 10, 16 | MaxEnumCount = 100 17 | } 18 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/IBTContent.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.BehaviourTree { 4 | public interface IBTContent { } 5 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/BehaviourTree/Src/TAny.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.BehaviourTree 4 | { 5 | public class TAny 6 | { 7 | public T As() where T : TAny 8 | { 9 | return (T)this; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Collision2D/ColliderData.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using Lockstep.Math; 5 | #if UNITY_5_3_OR_NEWER 6 | using UnityEngine; 7 | #endif 8 | 9 | namespace Lockstep.Collision2D { 10 | [Serializable] 11 | public partial class ColliderData :IBaseComponent{ 12 | #if UNITY_5_3_OR_NEWER 13 | [Header("Offset")] 14 | #endif 15 | public LFloat y; 16 | public LVector2 pos; 17 | #if UNITY_5_3_OR_NEWER 18 | [Header("Collider data")] 19 | #endif 20 | public LFloat high; 21 | public LFloat radius; 22 | public LVector2 size; 23 | public LVector2 up; 24 | public LFloat deg; 25 | 26 | public bool IsCircle(){ 27 | return radius > 0; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Collision2D/ColliderPart.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.Collision2D { 4 | public class ColliderPart { 5 | public CBaseShape collider; 6 | public CTransform2D transform; 7 | } 8 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Collision2D/ColliderPrefab.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.Collections.Generic; 4 | using Lockstep.Logging; 5 | using Lockstep.Math; 6 | using Lockstep.UnsafeCollision2D; 7 | 8 | namespace Lockstep.Collision2D { 9 | public class ColliderPrefab { 10 | #if UNITY_EDITOR 11 | public string name = ""; 12 | #endif 13 | public List parts = new List(); 14 | public CBaseShape collider => parts[0].collider; 15 | public CTransform2D transform => parts[0].transform; 16 | 17 | public LRect GetBounds(){ 18 | //TODO 19 | var col = collider; 20 | var tran = transform; 21 | var type = (EShape2D) col.TypeId; 22 | switch (type) { 23 | case EShape2D.Circle: { 24 | var radius = ((CCircle) col).radius; 25 | return LRect.CreateRect(tran.pos, new LVector2(radius, radius)); 26 | } 27 | case EShape2D.AABB: { 28 | var halfSize = ((CAABB) col).size; 29 | return LRect.CreateRect(tran.pos, halfSize); 30 | } 31 | case EShape2D.OBB: { 32 | var radius = ((COBB) col).radius; 33 | return LRect.CreateRect(tran.pos, new LVector2(radius, radius)); 34 | } 35 | } 36 | 37 | Debug.LogError("No support type" + type); 38 | 39 | return new LRect(); 40 | } 41 | 42 | public override string ToString(){ 43 | string ss = collider.ToString(); 44 | #if UNITY_EDITOR 45 | ss = name + ss; 46 | #endif 47 | return ss; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Collision2D/CollisionSystem_Unity.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | #if UNITY_5_3_OR_NEWER 4 | using System; 5 | using System.Collections.Generic; 6 | using Lockstep.Math; 7 | using Lockstep.UnsafeCollision2D; 8 | using UnityEngine; 9 | using Debug = Lockstep.Logging.Debug; 10 | using Random = System.Random; 11 | 12 | namespace Lockstep.Collision2D { 13 | public partial class CollisionSystem { 14 | public static ColliderPrefab CreateColliderPrefab(GameObject fab, ColliderData data){ 15 | Debug.Trace("CreateColliderPrefab " + fab.name); 16 | 17 | if (data == null) { 18 | Debug.LogError(fab.name + " Miss ColliderDataMono "); 19 | return null; 20 | } 21 | 22 | Debug.Trace($"{fab.name} !!!CreateCollider deg: {data.deg} up:{data.size} radius:{data.radius}"); 23 | return CreateColliderPrefab(data); 24 | } 25 | 26 | public static ColliderPrefab CreateColliderPrefab(ColliderData data){ 27 | CBaseShape collider = null; 28 | if (LMath.Abs(data.deg - 45) < 1) { 29 | int i = 09; 30 | } 31 | 32 | //warning data.deg is unity deg 33 | //changed unity deg to ccw deg 34 | var collisionDeg = -data.deg + 90; 35 | if (data.radius > 0) { 36 | //circle 37 | collider = new CCircle(data.radius); 38 | } 39 | else { 40 | //obb 41 | collider = new COBB(data.size, collisionDeg); 42 | } 43 | 44 | collider.high = data.high; 45 | var colFab = new ColliderPrefab(); 46 | colFab.parts.Add(new ColliderPart() { 47 | transform = new CTransform2D(data.pos,data.y,data.deg), 48 | collider = collider 49 | }); 50 | return colFab; 51 | } 52 | } 53 | } 54 | #endif -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Collision2D/ICollisionSystem.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using Lockstep.Math; 5 | using Lockstep.UnsafeCollision2D; 6 | 7 | namespace Lockstep.Collision2D { 8 | public delegate void FuncCollision(ColliderProxy obj); 9 | 10 | public interface ICollisionSystem { 11 | void DoStart(bool[] interestingMasks, int[] allTypes); 12 | void DoUpdate(LFloat deltaTime); 13 | ColliderProxy GetCollider(int id); 14 | void AddCollider(ColliderProxy collider); 15 | void RemoveCollider(ColliderProxy collider); 16 | bool Raycast(int layerType, Ray2D checkRay, out LFloat t, out int id, LFloat maxDistance); 17 | bool Raycast(int layerType, Ray2D checkRay, out LFloat t, out int id); 18 | void QueryRegion(int layerType, LVector2 pos, LVector2 size, LVector2 forward, FuncCollision callback); 19 | void QueryRegion(int layerType, LVector2 pos, LFloat radius, FuncCollision callback); 20 | 21 | //for debug 22 | void DrawGizmos(); 23 | int ShowTreeId { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Collision2D/Shape/CAABB.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Math; 4 | using Lockstep.UnsafeCollision2D; 5 | 6 | namespace Lockstep.Collision2D { 7 | public class CAABB : CCircle { 8 | public override int TypeId => (int) EShape2D.AABB; 9 | /// Half size of BoundBox 10 | public LVector2 size; 11 | 12 | public CAABB() : base(){ } 13 | 14 | public CAABB(LVector2 size){ 15 | this.size = size; 16 | radius = size.magnitude; 17 | } 18 | public override string ToString(){ 19 | return $"(radius:{radius} deg:{radius} hSize:{size})"; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Collision2D/Shape/CBaseShape.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Math; 4 | using Lockstep.UnsafeCollision2D; 5 | 6 | namespace Lockstep.Collision2D { 7 | public class CBaseShape { 8 | public virtual int TypeId => (int) EShape2D.EnumCount; 9 | public int id; 10 | public LFloat high; 11 | } 12 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Collision2D/Shape/CCircle.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Math; 4 | using Lockstep.UnsafeCollision2D; 5 | 6 | namespace Lockstep.Collision2D { 7 | public class CCircle : CBaseShape { 8 | public override int TypeId => (int) EShape2D.Circle; 9 | public LFloat radius; 10 | 11 | public CCircle() : this(LFloat.zero){ } 12 | 13 | public CCircle(LFloat radius){ 14 | this.radius = radius; 15 | } 16 | 17 | public override string ToString(){ 18 | return $"radius:{radius}"; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Collision2D/Shape/COBB.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Math; 4 | using Lockstep.UnsafeCollision2D; 5 | 6 | namespace Lockstep.Collision2D { 7 | public class COBB : CAABB { 8 | public override int TypeId => (int) EShape2D.OBB; 9 | public LFloat deg; 10 | public LVector2 up; 11 | 12 | public COBB(LVector2 size, LFloat deg) : base(size){ 13 | this.deg = deg; 14 | SetDeg(deg); 15 | } 16 | 17 | public COBB(LVector2 size, LVector2 up) : base(size){ 18 | SetUp(up); 19 | } 20 | 21 | //CCW 旋转角度 22 | public void Rotate(LFloat rdeg){ 23 | deg += rdeg; 24 | if (deg > 360 || deg < -360) { 25 | deg = deg - (deg / 360 * 360); 26 | } 27 | 28 | SetDeg(deg); 29 | } 30 | 31 | public void SetUp(LVector2 up){ 32 | this.up = up; 33 | this.deg = LMath.Atan2(-up.x, up.y); 34 | } 35 | 36 | public void SetDeg(LFloat rdeg){ 37 | deg = rdeg; 38 | var rad = LMath.Deg2Rad * deg; 39 | var c = LMath.Cos(rad); 40 | var s = LMath.Sin(rad); 41 | up = new LVector2(c,s); 42 | } 43 | public override string ToString(){ 44 | return $"(radius:{radius} up:{size} deg:{radius} up:{up} )"; 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Collision2D/Shape/CPolygon.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Math; 4 | using Lockstep.UnsafeCollision2D; 5 | 6 | namespace Lockstep.Collision2D { 7 | public class CPolygon : CCircle { 8 | public override int TypeId => (int) EShape2D.Polygon; 9 | public int vertexCount; 10 | public LFloat deg; 11 | public LVector2[] vertexes; 12 | } 13 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Collision2D/Shape/CRay.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.Runtime.InteropServices; 4 | using Lockstep.Math; 5 | using Lockstep.UnsafeCollision2D; 6 | using Lockstep.Util; 7 | 8 | namespace Lockstep.Collision2D { 9 | public class CRay : CBaseShape { 10 | public override int TypeId => (int) EShape2D.Ray; 11 | public LVector2 pos; 12 | public LVector2 dir; 13 | } 14 | 15 | [StructLayout(LayoutKind.Sequential, Pack = NativeHelper.STRUCT_PACK)] 16 | public unsafe struct Ray2D { 17 | public int TypeId => (int) EShape2D.Ray; 18 | public LVector2 origin; 19 | public LVector2 direction; 20 | } 21 | 22 | [StructLayout(LayoutKind.Sequential, Pack = NativeHelper.STRUCT_PACK)] 23 | public struct LRaycastHit2D { 24 | public LVector2 point; 25 | public LFloat distance; 26 | public int colliderId; 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Collision2D/Shape/CSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Math; 4 | using Lockstep.UnsafeCollision2D; 5 | 6 | namespace Lockstep.Collision2D { 7 | public class CSegment : CBaseShape { 8 | public override int TypeId => (int) EShape2D.Segment; 9 | public LVector2 pos1; 10 | public LVector2 pos2; 11 | } 12 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/ECS.ECDefine/Attributions.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | 5 | namespace Lockstep.UnsafeECSDefine { 6 | 7 | [AttributeUsage(AttributeTargets.Method)] 8 | public class SignalAttribute : System.Attribute { } 9 | 10 | [AttributeUsage(AttributeTargets.Class)] 11 | public class AbstractAttribute : System.Attribute { } 12 | 13 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field)] 14 | public class InitEntityCountAttribute : System.Attribute { 15 | public int count; 16 | 17 | public InitEntityCountAttribute(int count){ 18 | this.count = count; 19 | } 20 | } 21 | 22 | [AttributeUsage(AttributeTargets.Class| AttributeTargets.Field,AllowMultiple = true)] 23 | public class AttributeAttribute : System.Attribute { 24 | public string name; 25 | public AttributeAttribute(string name){ 26 | this.name = name; 27 | } 28 | } 29 | 30 | [AttributeUsage(AttributeTargets.Enum)] 31 | public class IgnoreAttribute : System.Attribute { 32 | } 33 | 34 | /// 不导出Excel 35 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field)] 36 | public class NoExcelAttribute : System.Attribute { 37 | } 38 | 39 | /// 不导出Excel 40 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field)] 41 | public class KeyIdAttribute : System.Attribute { 42 | } 43 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/ECS.ECDefine/Interfaces.cs: -------------------------------------------------------------------------------- 1 | namespace Lockstep.UnsafeECSDefine { 2 | 3 | 4 | 5 | 6 | public interface ISystem { } 7 | public interface ISystemWithIdx { } 8 | public interface ISystemWithEntity { } 9 | 10 | /// System 定义 11 | public interface IPureSystem : ISystem { } 12 | 13 | public interface IPureSystemWithEntity : IPureSystem, ISystemWithEntity { } 14 | 15 | public interface IJobSystem : ISystem { } 16 | 17 | public interface IJobSystemWithEntity : IJobSystem, ISystemWithEntity { } 18 | 19 | public interface IJobForEachSystem : IJobSystem { } 20 | 21 | public interface IJobForEachSystemWithEntity : IJobForEachSystem, ISystemWithEntity { } 22 | 23 | public interface IJobHashMapSystem : ISystem { } 24 | 25 | 26 | /// 全局数据定义 27 | public interface IGlobal { } 28 | /// Enitty目标集 29 | public interface IAsset { } 30 | 31 | public interface IComponent { } 32 | 33 | public interface IEntity { } 34 | 35 | public interface IBitset { } 36 | 37 | public interface IFields { } 38 | 39 | public interface IServiceState { } 40 | 41 | public interface IEvent{} 42 | //碰撞事件定义 43 | public interface ICollisionEvent { } 44 | 45 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/ECS.ECDefine/Structs.cs: -------------------------------------------------------------------------------- 1 | namespace Lockstep.UnsafeECSDefine { 2 | public class Vector2 { } 3 | 4 | public class Vector3 { } 5 | 6 | public class Quaternion { } 7 | public class Vector2Int { } 8 | public class Vector3Int { } 9 | 10 | public class EntityRef { } 11 | 12 | public class Entity { } 13 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Logging/Src/BaseLogger.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | 5 | namespace Lockstep.Logging { 6 | public class BaseLogger { 7 | protected DebugInstance Debug; 8 | 9 | public void SetLogger(DebugInstance logger){ 10 | this.Debug = logger; 11 | } 12 | 13 | protected void Log(string format, params object[] args){ 14 | Debug?.Log(format, args); 15 | } 16 | 17 | protected void LogFormat(string format, params object[] args){ 18 | Debug?.LogFormat(format, args); 19 | } 20 | 21 | protected void LogError(string format, params object[] args){ 22 | Debug?.LogError(format, args); 23 | } 24 | 25 | protected void LogError(Exception e){ 26 | Debug?.LogError(e); 27 | } 28 | 29 | protected void LogErrorFormat(string format, params object[] args){ 30 | Debug?.LogErrorFormat(format, args); 31 | } 32 | 33 | protected void Assert(bool val, string msg = ""){ 34 | Debug?.Assert(val, msg); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Logging/Src/LogEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | 5 | namespace Lockstep.Logging 6 | { 7 | public class LogEventArgs : EventArgs 8 | { 9 | public LogSeverity LogSeverity { get; } 10 | 11 | public string Message { get; } 12 | 13 | public LogEventArgs(LogSeverity logSeverity, string message) 14 | { 15 | LogSeverity = logSeverity; 16 | Message = message; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Logging/Src/LogSeverity.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | 5 | namespace Lockstep.Logging 6 | { 7 | [Flags] 8 | public enum LogSeverity 9 | { 10 | Exception = 1, 11 | Error = 2, 12 | Warn = 4, 13 | Info = 8, 14 | Trace = 16 15 | } 16 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Logging/Src/Logger.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Diagnostics; 5 | using System.Text; 6 | 7 | namespace Lockstep.Logging { 8 | public static class Logger { 9 | public static LogSeverity LogSeverityLevel = 10 | LogSeverity.Info | LogSeverity.Warn | LogSeverity.Error | LogSeverity.Exception; 11 | 12 | public static event EventHandler OnMessage = DefaultServerLogHandler; 13 | public static Action OnAssert; 14 | 15 | public static void SetLogAllSeverities(){ 16 | LogSeverityLevel = LogSeverity.Trace | LogSeverity.Info | LogSeverity.Warn | LogSeverity.Error | 17 | LogSeverity.Exception; 18 | } 19 | 20 | public static void Err(object sender, string message, params object[] args){ 21 | LogMessage(sender, LogSeverity.Error, message, args); 22 | } 23 | 24 | public static void Warn(object sender, string message, params object[] args){ 25 | LogMessage(sender, LogSeverity.Warn, message, args); 26 | } 27 | 28 | public static void Info(object sender, string message, params object[] args){ 29 | LogMessage(sender, LogSeverity.Info, message, args); 30 | } 31 | 32 | public static void Trace(object sender, string message, params object[] args){ 33 | LogMessage(sender, LogSeverity.Trace, message, args); 34 | } 35 | 36 | public static void Assert(object sender, bool val, string message){ 37 | if (!val) { 38 | LogMessage(sender, LogSeverity.Error, "AssertFailed!!! " + message); 39 | } 40 | } 41 | 42 | private static void LogMessage(object sender, LogSeverity sev, string format, params object[] args){ 43 | if (OnMessage != null && (LogSeverityLevel & sev) != 0) { 44 | var message = (args != null && args.Length > 0) ? string.Format(format, args) : format; 45 | OnMessage.Invoke(sender, new LogEventArgs(sev, message)); 46 | } 47 | } 48 | 49 | static StringBuilder _logBuffer = new StringBuilder(); 50 | public static void DefaultServerLogHandler(object sernder, LogEventArgs logArgs){ 51 | if ((LogSeverity.Error & logArgs.LogSeverity) != 0 52 | || (LogSeverity.Exception & logArgs.LogSeverity) != 0 53 | ) { 54 | StackTrace st = new StackTrace(true); 55 | StackFrame[] sf = st.GetFrames(); 56 | for (int i = 4; i < sf.Length; ++i) { 57 | var frame = sf[i]; 58 | _logBuffer.AppendLine(frame.GetMethod().DeclaringType.FullName + "::" + frame.GetMethod().Name + 59 | " Line=" + frame.GetFileLineNumber()); 60 | } 61 | } 62 | 63 | Console.WriteLine(logArgs.Message); 64 | if (_logBuffer.Length != 0) { 65 | Console.WriteLine(_logBuffer.ToString()); 66 | _logBuffer.Length = 0; 67 | _logBuffer.Clear(); 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Math/BaseType/LAxis2D.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Math; 4 | using static Lockstep.Math.LMath; 5 | 6 | namespace Lockstep.Math 7 | { 8 | 9 | public struct LAxis2D 10 | { 11 | public LVector3 x; 12 | public LVector3 y; 13 | 14 | public static readonly LAxis2D identity = new LAxis2D(LVector3.right, LVector3.up); 15 | public LAxis2D(LVector3 x, LVector3 y) 16 | { 17 | this.x = x; 18 | this.y = y; 19 | } 20 | public LVector3 this[int index] 21 | { 22 | get 23 | { 24 | switch (index) 25 | { 26 | case 0: return x; 27 | case 1: return y; 28 | default: throw new System.IndexOutOfRangeException("vector idx invalid" + index); 29 | } 30 | } 31 | 32 | set 33 | { 34 | switch (index) 35 | { 36 | case 0: 37 | x = value; 38 | break; 39 | case 1: 40 | y = value; 41 | break; 42 | default: throw new System.IndexOutOfRangeException("vector idx invalid" + index); 43 | } 44 | } 45 | } 46 | } 47 | 48 | 49 | 50 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Math/BaseType/LAxis3D.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Math; 4 | using static Lockstep.Math.LVector3; 5 | 6 | namespace Lockstep.Math 7 | { 8 | public struct LAxis3D 9 | { 10 | public LVector3 x; 11 | public LVector3 y; 12 | public LVector3 z; 13 | public static readonly LAxis3D identity = new LAxis3D(LVector3.right, LVector3.up, LVector3.forward); 14 | 15 | public LAxis3D(LVector3 right, LVector3 up, LVector3 forward) 16 | { 17 | this.x = right; 18 | this.y = up; 19 | this.z = forward; 20 | } 21 | 22 | public LVector3 WorldToLocal(LVector3 vec) 23 | { 24 | var _x = Dot(x, vec); 25 | var _y = Dot(y, vec); 26 | var _z = Dot(z, vec); 27 | return new LVector3(_x, _y, _z); 28 | } 29 | public LVector3 LocalToWorld(LVector3 vec) 30 | { 31 | return x * vec.x + y * vec.y + z * vec.z; 32 | } 33 | 34 | public LVector3 this[int index] 35 | { 36 | get 37 | { 38 | switch (index) 39 | { 40 | case 0: return x; 41 | case 1: return y; 42 | case 2: return z; 43 | default: throw new System.IndexOutOfRangeException("vector idx invalid" + index); 44 | } 45 | } 46 | 47 | set 48 | { 49 | switch (index) 50 | { 51 | case 0: 52 | x = value; 53 | break; 54 | case 1: 55 | y = value; 56 | break; 57 | case 2: 58 | z = value; 59 | break; 60 | default: throw new System.IndexOutOfRangeException("vector idx invalid" + index); 61 | } 62 | } 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Math/HashCodeExtension.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Collision2D; 4 | using Lockstep.Math; 5 | 6 | namespace Lockstep.Util { 7 | public static class HashCodeExtension { 8 | 9 | public static int GetHash(this byte val,ref int idx){ 10 | return val; 11 | } 12 | 13 | public static int GetHash(this short val,ref int idx){ 14 | return val; 15 | } 16 | 17 | public static int GetHash(this int val,ref int idx){ 18 | return val; 19 | } 20 | public static int GetHash(this long val,ref int idx){ 21 | return (int) val; 22 | } 23 | 24 | public static int GetHash(this sbyte val,ref int idx){ 25 | return val; 26 | } 27 | 28 | public static int GetHash(this ushort val,ref int idx){ 29 | return val; 30 | } 31 | 32 | public static int GetHash(this uint val,ref int idx){ 33 | return (int) val; 34 | } 35 | 36 | public static int GetHash(this ulong val,ref int idx){ 37 | return (int) val; 38 | } 39 | 40 | public static int GetHash(this bool val,ref int idx){ 41 | return val ? 1 : 0; 42 | } 43 | public static int GetHash(this string val,ref int idx){ 44 | return val?.GetHashCode() ?? 0; 45 | } 46 | public static int GetHash(this LFloat val,ref int idx){ 47 | return PrimerLUT.GetPrimer(val._val); 48 | } 49 | 50 | public static int GetHash(this LVector2 val,ref int idx){ 51 | return PrimerLUT.GetPrimer(val._x) + PrimerLUT.GetPrimer(val._y) * 17; 52 | } 53 | 54 | public static int GetHash(this LVector3 val,ref int idx){ 55 | return PrimerLUT.GetPrimer(val._x) 56 | + PrimerLUT.GetPrimer(val._y) * 31 57 | + PrimerLUT.GetPrimer(val._z) * 37; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Math/LMathExtension.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | 4 | using Lockstep.UnsafeCollision2D; 5 | #if UNITY_5_3_OR_NEWER 6 | using UnityEngine; 7 | #endif 8 | using Lockstep.Math; 9 | 10 | namespace Lockstep.Math { 11 | #if UNITY_5_3_OR_NEWER 12 | public static partial class LMathExtension { 13 | public static LVector2 ToLVector2(this Vector2Int vec){ 14 | return new LVector2(true,vec.x * LFloat.Precision, vec.y * LFloat.Precision); 15 | } 16 | 17 | public static LVector3 ToLVector3(this Vector3Int vec){ 18 | return new LVector3(true,vec.x * LFloat.Precision, vec.y * LFloat.Precision, vec.z * LFloat.Precision); 19 | } 20 | 21 | public static LVector2Int ToLVector2Int(this Vector2Int vec){ 22 | return new LVector2Int(vec.x, vec.y); 23 | } 24 | 25 | public static LVector3Int ToLVector3Int(this Vector3Int vec){ 26 | return new LVector3Int(vec.x, vec.y, vec.z); 27 | } 28 | public static Vector2Int ToVector2Int(this LVector2Int vec){ 29 | return new Vector2Int(vec.x, vec.y); 30 | } 31 | 32 | public static Vector3Int ToVector3Int(this LVector3Int vec){ 33 | return new Vector3Int(vec.x, vec.y, vec.z); 34 | } 35 | public static LVector2 ToLVector2(this Vector2 vec){ 36 | return new LVector2( 37 | LMath.ToLFloat(vec.x), 38 | LMath.ToLFloat(vec.y)); 39 | } 40 | 41 | public static LVector3 ToLVector3(this Vector3 vec){ 42 | return new LVector3( 43 | LMath.ToLFloat(vec.x), 44 | LMath.ToLFloat(vec.y), 45 | LMath.ToLFloat(vec.z)); 46 | } 47 | public static LVector2 ToLVector2XZ(this Vector3 vec){ 48 | return new LVector2( 49 | LMath.ToLFloat(vec.x), 50 | LMath.ToLFloat(vec.z)); 51 | } 52 | public static Vector2 ToVector2(this LVector2 vec){ 53 | return new Vector2(vec.x.ToFloat(), vec.y.ToFloat()); 54 | } 55 | public static Vector3 ToVector3(this LVector2 vec){ 56 | return new Vector3(vec.x.ToFloat(), vec.y.ToFloat(),0); 57 | } 58 | public static Vector3 ToVector3XZ(this LVector2 vec,LFloat y){ 59 | return new Vector3(vec.x.ToFloat(), y.ToFloat(),vec.y.ToFloat()); 60 | } 61 | public static Vector3 ToVector3XZ(this LVector2 vec){ 62 | return new Vector3(vec.x.ToFloat(), 0,vec.y.ToFloat()); 63 | } 64 | public static Vector3 ToVector3(this LVector3 vec){ 65 | return new Vector3(vec.x.ToFloat(), vec.y.ToFloat(), vec.z.ToFloat()); 66 | } 67 | public static Rect ToRect(this LRect vec){ 68 | return new Rect(vec.position.ToVector2(),vec.size.ToVector2()); 69 | } 70 | } 71 | #endif 72 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Math/LMathExtension2.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Collision2D; 4 | using Lockstep.Math; 5 | 6 | namespace Lockstep.Math { 7 | public static partial class LMathExtension { 8 | public static LVector2 ToLVector2(this LVector2Int vec){ 9 | return new LVector2(true, vec.x * LFloat.Precision, vec.y * LFloat.Precision); 10 | } 11 | 12 | public static LVector3 ToLVector3(this LVector3Int vec){ 13 | return new LVector3(true, vec.x * LFloat.Precision, vec.y * LFloat.Precision, vec.z * LFloat.Precision); 14 | } 15 | 16 | public static LVector2Int ToLVector2Int(this LVector2 vec){ 17 | return new LVector2Int(vec.x.ToInt(), vec.y.ToInt()); 18 | } 19 | 20 | public static LVector3Int ToLVector3Int(this LVector3 vec){ 21 | return new LVector3Int(vec.x.ToInt(), vec.y.ToInt(), vec.z.ToInt()); 22 | } 23 | } 24 | 25 | public static partial class LMathExtension { 26 | public static LFloat ToLFloat(this float v){ 27 | return LMath.ToLFloat(v); 28 | } 29 | 30 | public static LFloat ToLFloat(this int v){ 31 | return LMath.ToLFloat(v); 32 | } 33 | 34 | public static LFloat ToLFloat(this long v){ 35 | return LMath.ToLFloat(v); 36 | } 37 | } 38 | 39 | public static partial class LMathExtension { 40 | public static LVector2Int Floor(this LVector2 vec){ 41 | return new LVector2Int(LMath.FloorToInt(vec.x), LMath.FloorToInt(vec.y)); 42 | } 43 | 44 | public static LVector3Int Floor(this LVector3 vec){ 45 | return new LVector3Int( 46 | LMath.FloorToInt(vec.x), 47 | LMath.FloorToInt(vec.y), 48 | LMath.FloorToInt(vec.z) 49 | ); 50 | } 51 | } 52 | 53 | public static partial class LMathExtension { 54 | public static LVector2 RightVec(this LVector2 vec){ 55 | return new LVector2(true, vec._y, -vec._x); 56 | } 57 | 58 | public static LVector2 LeftVec(this LVector2 vec){ 59 | return new LVector2(true, -vec._y, vec._x); 60 | } 61 | 62 | public static LVector2 BackVec(this LVector2 vec){ 63 | return new LVector2(true, -vec._x, -vec._y); 64 | } 65 | public static LFloat ToDeg(this LVector2 vec){ 66 | return CTransform2D.ToDeg(vec); 67 | } 68 | 69 | public static LFloat Abs(this LFloat val){ 70 | return LMath.Abs(val); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Math/LRandom.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using Lockstep.Math; 5 | 6 | namespace Lockstep.Math { 7 | public partial struct Random { 8 | public ulong randSeed ; 9 | public Random(uint seed = 17){ 10 | randSeed = seed; 11 | } 12 | public LFloat value => new LFloat(true, Range(0, (int)LFloat.Precision)); 13 | 14 | public uint Next(){ 15 | randSeed = randSeed * 1103515245 + 36153; 16 | return (uint) (randSeed / 65536); 17 | } 18 | // range:[0 ~(max-1)] 19 | public uint Next(uint max){ 20 | return Next() % max; 21 | } 22 | public LVector2 NextVector2(){ 23 | return new LVector2(true, Next((uint)LFloat.Precision),Next((uint)LFloat.Precision)); 24 | } 25 | public LVector3 NextVector3(){ 26 | return new LVector3(true, Next((uint)LFloat.Precision),Next((uint)LFloat.Precision),Next((uint)LFloat.Precision)); 27 | } 28 | public int Next(int max){ 29 | return (int) (Next() % max); 30 | } 31 | // range:[min~(max-1)] 32 | public uint Range(uint min, uint max){ 33 | if (min > max) 34 | throw new ArgumentOutOfRangeException("minValue", 35 | string.Format("'{0}' cannot be greater than {1}.", min, max)); 36 | 37 | uint num = max - min; 38 | return this.Next(num) + min; 39 | } 40 | public int Range(int min, int max){ 41 | if (min >= max - 1) 42 | return min; 43 | int num = max - min; 44 | 45 | return this.Next(num) + min; 46 | } 47 | 48 | public LFloat Range(LFloat min, LFloat max){ 49 | if (min > max) 50 | throw new ArgumentOutOfRangeException("minValue", 51 | string.Format("'{0}' cannot be greater than {1}.", min, max)); 52 | 53 | var num = (max._val - min._val); 54 | return new LFloat(true, Next((uint)num) + min._val); 55 | } 56 | } 57 | #if false 58 | public class LRandom { 59 | private static Random _i = new Random(3274); 60 | public static LFloat value => _i.value; 61 | public static uint Next(){return _i.Next();} 62 | public static uint Next(uint max){return _i.Next(max);} 63 | public static int Next(int max){return _i.Next(max);} 64 | public static uint Range(uint min, uint max){return _i.Range(min, max);} 65 | public static int Range(int min, int max){return _i.Range(min, max);} 66 | public static LFloat Range(LFloat min, LFloat max){return _i.Range(min, max);} 67 | } 68 | #endif 69 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/NetMsg.Common/Src/DictExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.Collections.Generic; 4 | 5 | namespace NetMsg.Common{ 6 | public static class DictExtensions { 7 | public static TValue GetRefVal(this Dictionary dict, TKey key) 8 | where TValue : class{ 9 | if (dict.TryGetValue(key, out TValue val)) { 10 | return val; 11 | } 12 | 13 | return null; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/NetMsg.Common/Src/EMsgSC.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | 4 | namespace NetMsg.Common { 5 | 6 | public enum EServerDetailPortType { 7 | ServerPort, 8 | TcpPort, 9 | UdpPort, 10 | } 11 | 12 | public enum ELoginResult { 13 | Success, 14 | Reconnect, 15 | PasswordMissMatch, 16 | ErrorHash, 17 | NotLogin, 18 | } 19 | 20 | public enum ERoomOperatorResult { 21 | Succ, 22 | Full, 23 | NotExist, 24 | AlreadyExist, 25 | } 26 | 27 | public enum EGameState { 28 | Idle, 29 | Loading, 30 | PartLoaded, 31 | Playing, 32 | PartFinished, 33 | FinishAll, 34 | } 35 | 36 | //msg between client RoomServer 37 | public enum EMsgSC : ushort { 38 | //GC 39 | //!! please ensure udp msg's id < 255 40 | //Room msg 41 | C2G_UdpHello, 42 | G2C_UdpHello, 43 | C2G_UdpMessage, 44 | G2C_UdpMessage, 45 | C2G_TcpMessage, 46 | G2C_TcpMessage, 47 | //udp 48 | C2G_ReqMissFrame, 49 | C2G_RepMissFrameAck, 50 | G2C_RepMissFrame, 51 | C2G_HashCode, 52 | C2G_PlayerInput, 53 | G2C_FrameData, 54 | C2G_PlayerPing, 55 | G2C_PlayerPing, 56 | //end of Udp 57 | EnumEndOfUdpMessage, 58 | 59 | 60 | S2C_TickPlayer, 61 | 62 | //IC 63 | C2I_UserLogin, 64 | I2C_LoginResult, 65 | 66 | //LC 67 | //chat 68 | C2L_RoomChatInfo, 69 | L2C_RoomChatInfo, 70 | 71 | //Room Operator 72 | I2L_UserLogin, 73 | C2L_UserLogin, 74 | //Room Operator 75 | C2L_ReqRoomList, 76 | L2C_RoomList, 77 | L2C_RoomInfoUpdate, 78 | 79 | C2L_JoinRoom, 80 | L2C_JoinRoom, 81 | L2C_JoinRoomResult, 82 | C2L_ReadyInRoom, 83 | L2C_ReadyInRoom, 84 | C2L_LeaveRoom, 85 | L2C_LeaveRoom, 86 | C2L_CreateRoom, 87 | L2C_CreateRoomResult, 88 | C2L_StartGame, 89 | L2C_StartGame, 90 | 91 | //LG 92 | L2G_CreateGame, 93 | L2G_UserReconnect, 94 | 95 | //GC Tcp 96 | C2G_Hello, 97 | G2C_Hello, 98 | G2C_GameStartInfo, 99 | C2G_LoadingProgress, 100 | G2C_LoadingProgress, 101 | G2C_AllFinishedLoaded, 102 | C2G_FinishedLevel, 103 | /// 104 | /// game state:Failed Success PartLoaded 105 | /// 106 | G2C_GameStatu, 107 | 108 | // 109 | C2G_GameEvent, 110 | G2C_GameEvent, 111 | 112 | 113 | EnumCount 114 | } 115 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/NetMsg.Common/Src/NetworkDefine.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace NetMsg.Common { 4 | 5 | public class NetworkDefine { 6 | /// 7 | /// 最大延迟时间 超过这个时间 依旧等不到玩家的输入包,默认玩家没有输入(输入丢失) 8 | /// 9 | public const int MAX_DELAY_TIME_MS = 300; 10 | 11 | /// 正常玩家的延迟 12 | public const int NORMAL_PLAYER_MAX_DELAY = 100; 13 | 14 | /// 正常玩家最大收到输入确认包的延迟 (有其中一个玩家输入延迟太大 且自身网络达到66%丢包率 情况下的时延) 15 | public const int MAX_FRAME_DATA_DELAY = MAX_DELAY_TIME_MS + NORMAL_PLAYER_MAX_DELAY + 2 * UPDATE_DELTATIME; 16 | 17 | /// 帧率 18 | public const int FRAME_RATE = 33; 19 | 20 | public const int UPDATE_DELTATIME = 30; 21 | 22 | public const string NetKey = "LockstepPlatform"; 23 | } 24 | 25 | 26 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/NetMsg.Common/Src/Udp/InputCmd.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Diagnostics; 5 | using Lockstep.Serialization; 6 | 7 | namespace NetMsg.Common { 8 | 9 | [System.Serializable] 10 | [SelfImplement] 11 | [Udp] 12 | public partial class InputCmd : BaseMsg { 13 | public byte type => content[0]; 14 | 15 | public byte[] content; 16 | public InputCmd(){ } 17 | 18 | public InputCmd(byte type){ 19 | content = new byte[1] {type}; 20 | } 21 | 22 | public InputCmd(byte[] bytes){ 23 | content = bytes; 24 | } 25 | 26 | public bool Equals(InputCmd cmdb){ 27 | if (cmdb == null) return false; 28 | return content.EqualsEx(cmdb.content); 29 | } 30 | 31 | public override bool Equals(object obj){ 32 | var cmdb = obj as InputCmd; 33 | return Equals(cmdb); 34 | } 35 | 36 | public override int GetHashCode(){ 37 | return content.GetHashCode(); 38 | } 39 | 40 | public override string ToString(){ 41 | return $"t:{content[0]} content:{content?.Length ?? 0}"; 42 | } 43 | 44 | 45 | public override void Serialize(Serializer writer){ 46 | Debug.Assert(content != null && content.Length>0&& content.Length < byte.MaxValue 47 | , $"!!!!!!!!! Input Cmd len{content?.Length ?? 0} should less then {byte.MaxValue}"); 48 | writer.WriteBytes_255(content); 49 | } 50 | 51 | public override void Deserialize(Deserializer reader){ 52 | content = reader.ReadBytes_255(); 53 | Debug.Assert(content != null && content.Length > 0,"!!!!!!!!! Input Cmd len{content?.Length ?? 0} should less then {byte.MaxValue}"); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/NetMsg.Common/Src/Udp/Msg_PlayerInput.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | #define DEBUG_FRAME_DELAY 4 | using System.Collections.Generic; 5 | using Lockstep.Serialization; 6 | 7 | namespace NetMsg.Common { 8 | [System.Serializable] 9 | [SelfImplement] 10 | [Udp] 11 | public partial class Msg_PlayerInput : BaseMsg { 12 | public byte[] InputDatas; //real data 13 | public bool IsMiss; 14 | public byte ActorId; 15 | public int Tick; 16 | public InputCmd[] Commands; 17 | #if DEBUG_FRAME_DELAY 18 | public float timeSinceStartUp; 19 | #endif 20 | 21 | public Msg_PlayerInput(int tick, byte actorID, List inputs){ 22 | this.Tick = tick; 23 | this.ActorId = actorID; 24 | if (inputs != null && inputs.Count > 0) { 25 | this.Commands = inputs.ToArray(); 26 | } 27 | } 28 | public Msg_PlayerInput(int tick, byte actorID, InputCmd[] inputs = null){ 29 | this.Tick = tick; 30 | this.ActorId = actorID; 31 | if (inputs != null && inputs.Length > 0) { 32 | this.Commands = inputs; 33 | } 34 | } 35 | 36 | public Msg_PlayerInput(){ } 37 | 38 | public override bool Equals(object obj){ 39 | return Equals(obj as Msg_PlayerInput); 40 | } 41 | 42 | public bool Equals(Msg_PlayerInput other){ 43 | if (other == null) return false; 44 | if (Tick != other.Tick) return false; 45 | return Commands.EqualsEx(other.Commands); 46 | } 47 | 48 | public override int GetHashCode(){ 49 | return (int) (ActorId << 24 & Tick); 50 | } 51 | 52 | /// 53 | /// TODO 合并 输入 54 | /// 55 | /// 56 | public void Combine(Msg_PlayerInput inputb){ } 57 | 58 | public override void Serialize(Serializer writer){ 59 | #if DEBUG_FRAME_DELAY 60 | writer.Write(timeSinceStartUp); 61 | #endif 62 | writer.Write(IsMiss); 63 | writer.Write(ActorId); 64 | writer.Write(Tick); 65 | int count = Commands?.Length ?? 0; 66 | writer.Write((byte) count); 67 | for (int i = 0; i < count; i++) { 68 | Commands[i].Serialize(writer); 69 | } 70 | } 71 | 72 | public override void Deserialize(Deserializer reader){ 73 | #if DEBUG_FRAME_DELAY 74 | timeSinceStartUp = reader.ReadSingle(); 75 | #endif 76 | IsMiss = reader.ReadBoolean(); 77 | ActorId = reader.ReadByte(); 78 | Tick = reader.ReadInt32(); 79 | int count = reader.ReadByte(); 80 | if (count == 0) { 81 | Commands = null; 82 | return; 83 | } 84 | 85 | Commands = new InputCmd[count]; 86 | for (int i = 0; i < count; i++) { 87 | var cmd = reader.Parse(); 88 | Commands[i] = cmd; 89 | } 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/NetMsg.Common/Src/Udp/MutilDiscFrames.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Serialization; 4 | 5 | namespace NetMsg.Common { 6 | [SelfImplement] 7 | [Udp] 8 | public partial class MutilDiscFrames : BaseMsg { 9 | public int startTick; 10 | public ServerFrame[] frames; 11 | 12 | public override void Serialize(Serializer writer){ 13 | writer.Write(startTick); 14 | writer.Write(frames); 15 | } 16 | 17 | public override void Deserialize(Deserializer reader){ 18 | startTick = reader.ReadInt32(); 19 | frames = reader.ReadArray(frames); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/NetMsg.Common/Src/Udp/MutilFrames.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Diagnostics; 5 | using Lockstep.Serialization; 6 | 7 | namespace NetMsg.Common { 8 | [SelfImplement] 9 | [Udp] 10 | [Serializable] 11 | public partial class MutilFrames : BaseMsg { 12 | public int startTick; 13 | public ServerFrame[] frames; 14 | 15 | public override void Serialize(Serializer writer){ 16 | writer.Write(startTick); 17 | var count = (ushort) frames.Length; 18 | writer.Write(count); 19 | for (int i = 0; i < count; i++) { 20 | Debug.Assert(frames[i].Tick == startTick + i, "Frame error"); 21 | frames[i].BeforeSerialize(); 22 | writer.Write(frames[i].InputDatas); 23 | } 24 | } 25 | 26 | public override void Deserialize(Deserializer reader){ 27 | startTick = reader.ReadInt32(); 28 | var tickCount = reader.ReadUInt16(); 29 | frames = new ServerFrame[tickCount]; 30 | for (int i = 0; i < tickCount; i++) { 31 | var frame = new ServerFrame(); 32 | frame.Tick = startTick + i; 33 | frame.InputDatas = reader.ReadBytes(); 34 | frame.AfterDeserialize(); 35 | frames[i] = frame; 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Network/AChannel.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Net; 6 | using System.Net.Sockets; 7 | using System.Threading.Tasks; 8 | 9 | namespace Lockstep.Network { 10 | [Flags] 11 | public enum PacketFlags { 12 | None = 0, 13 | Reliable = 1 << 0, 14 | Unsequenced = 1 << 1, 15 | NoAllocate = 1 << 2 16 | } 17 | 18 | public enum ChannelType { 19 | Connect, 20 | Accept, 21 | } 22 | 23 | public class NetBase : IDisposable { 24 | public long Id; 25 | public bool IsDisposed; 26 | public virtual void Dispose(){ } 27 | } 28 | 29 | public class IdGenerater { 30 | private static long id = 0; 31 | 32 | public static long GenerateId(){ 33 | return id++; 34 | } 35 | } 36 | 37 | public abstract class AChannel : NetBase { 38 | public ChannelType ChannelType { get; } 39 | 40 | protected AService service; 41 | 42 | public IPEndPoint RemoteAddress { get; protected set; } 43 | 44 | private event Action errorCallback; 45 | 46 | public event Action ErrorCallback { 47 | add { this.errorCallback += value; } 48 | remove { this.errorCallback -= value; } 49 | } 50 | 51 | protected void OnError(SocketError e){ 52 | if (this.IsDisposed) { 53 | return; 54 | } 55 | 56 | this.errorCallback?.Invoke(this, e); 57 | } 58 | 59 | 60 | protected AChannel(AService service, ChannelType channelType){ 61 | this.Id = IdGenerater.GenerateId(); 62 | this.ChannelType = channelType; 63 | this.service = service; 64 | } 65 | 66 | /// 67 | /// 发送消息 68 | /// 69 | public abstract void Send(byte[] buffer, int index, int length); 70 | 71 | public abstract void Send(List buffers); 72 | 73 | /// 74 | /// 接收消息 75 | /// 76 | public abstract Task Recv(); 77 | 78 | public override void Dispose(){ 79 | if (this.IsDisposed) { 80 | return; 81 | } 82 | 83 | base.Dispose(); 84 | 85 | this.service.Remove(this.Id); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Network/AService.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Net; 5 | using System.Threading.Tasks; 6 | 7 | namespace Lockstep.Network 8 | { 9 | public enum NetworkProtocol 10 | { 11 | TCP, 12 | } 13 | 14 | public abstract class AService :NetBase 15 | { 16 | public abstract AChannel GetChannel(long id); 17 | 18 | public abstract Task AcceptChannel(); 19 | 20 | public abstract AChannel ConnectChannel(IPEndPoint ipEndPoint); 21 | 22 | public abstract void Remove(long channelId); 23 | 24 | public abstract void Update(); 25 | } 26 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Network/ErrorCode.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | 5 | namespace Lockstep.Network { 6 | public class RpcException : Exception { 7 | public int Error { get; private set; } 8 | 9 | public RpcException(int error, string message) : base($"Error: {error} Message: {message}"){ 10 | this.Error = error; 11 | } 12 | 13 | public RpcException(int error, string message, Exception e) : base($"Error: {error} Message: {message}", e){ 14 | this.Error = error; 15 | } 16 | } 17 | 18 | public static class ErrorCode { 19 | public const int ERR_Success = 0; 20 | public const int ERR_NotFoundActor = 2; 21 | 22 | public const int ERR_AccountOrPasswordError = 102; 23 | public const int ERR_SessionActorError = 103; 24 | public const int ERR_NotFoundUnit = 104; 25 | public const int ERR_ConnectGateKeyError = 105; 26 | 27 | public const int ERR_Exception = 1000; 28 | 29 | public const int ERR_RpcFail = 2001; 30 | public const int ERR_SocketDisconnected = 2002; 31 | public const int ERR_ReloadFail = 2003; 32 | public const int ERR_ActorLocationNotFound = 2004; 33 | } 34 | 35 | public static class BytesHelper { 36 | public static byte[] GetBytes(ushort val){ 37 | if (BitConverter.IsLittleEndian) { 38 | return BitConverter.GetBytes(val); 39 | } 40 | else { 41 | return BitConverter.GetBytes(val).Swap(); 42 | } 43 | } 44 | 45 | public static byte[] GetBytes(int val){ 46 | if (BitConverter.IsLittleEndian) { 47 | return BitConverter.GetBytes(val); 48 | } 49 | else { 50 | return BitConverter.GetBytes(val).Swap(); 51 | } 52 | } 53 | 54 | public static ushort ToUInt16(byte[] value, int startIndex){ 55 | if (BitConverter.IsLittleEndian) { 56 | return BitConverter.ToUInt16(value, startIndex); 57 | } 58 | else { 59 | return BitConverter.ToUInt16(value.Swap(startIndex, sizeof(ushort)), startIndex); 60 | } 61 | } 62 | 63 | private static byte[] Swap(this byte[] vals, int startIdx, int len){ 64 | var dst = new byte[len]; 65 | Buffer.BlockCopy(vals, startIdx, dst, 0, len); 66 | return Swap(dst); 67 | } 68 | 69 | private static byte[] Swap(this byte[] vals){ 70 | var count = vals.Length; 71 | for (int i = 0, j = count - 1; i < j; ++i, --j) { 72 | var temp = vals[i]; 73 | vals[i] = vals[j]; 74 | vals[j] = temp; 75 | } 76 | 77 | return vals; 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Network/IMessage.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.Network { 4 | public interface IMessage { 5 | ushort opcode { get; set; } 6 | } 7 | public interface IRequest : IMessage { 8 | int RpcId { get; set; } 9 | } 10 | 11 | public interface IResponse : IMessage { 12 | int Error { get; set; } 13 | string Message { get; set; } 14 | int RpcId { get; set; } 15 | } 16 | 17 | public class ResponseMessage : IResponse { 18 | public ushort opcode { get; set; } 19 | public int Error { get; set; } 20 | public string Message { get; set; } 21 | public int RpcId { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Network/IMessageDispatcher.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.Network { 4 | public interface IMessageDispatcher { 5 | void Dispatch(Session session, Packet packet); 6 | } 7 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Network/IMessagePacker.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.Network { 4 | public interface IMessagePacker { 5 | object DeserializeFrom(ushort type, byte[] bytes, int index, int count); 6 | byte[] SerializeToByteArray(IMessage msg); 7 | } 8 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Network/Log.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | #if UNITY_5_3_OR_NEWER 5 | using UnityEngine; 6 | #endif 7 | 8 | namespace Lockstep.Network { 9 | public class Log { 10 | public static void Error(string msg){ 11 | #if UNITY_5_3_OR_NEWER 12 | Debug.LogError(msg); 13 | #else 14 | Console.WriteLine(msg); 15 | #endif 16 | } 17 | 18 | public static void sLog(string msg){ 19 | #if UNITY_5_3_OR_NEWER 20 | Debug.Log(msg); 21 | #else 22 | Console.WriteLine(msg); 23 | #endif 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Network/NetworkHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.Net; 4 | 5 | namespace Lockstep.Network 6 | { 7 | public static class NetworkHelper 8 | { 9 | public static IPEndPoint ToIPEndPoint(string host, int port) 10 | { 11 | return new IPEndPoint(IPAddress.Parse(host), port); 12 | } 13 | 14 | public static IPEndPoint ToIPEndPoint(string address) 15 | { 16 | int index = address.LastIndexOf(':'); 17 | string host = address.Substring(0, index); 18 | string p = address.Substring(index + 1); 19 | int port = int.Parse(p); 20 | return ToIPEndPoint(host, port); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Network/OneThreadSynchronizationContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Concurrent; 5 | using System.Threading; 6 | 7 | namespace Lockstep.Network { 8 | public class OneThreadSynchronizationContext : SynchronizationContext { 9 | // 线程同步队列,发送接收socket回调都放到该队列,由poll线程统一执行 10 | private readonly ConcurrentQueue queue = new ConcurrentQueue(); 11 | 12 | private void Add(Action action){ 13 | this.queue.Enqueue(action); 14 | } 15 | 16 | public void Update(){ 17 | while (true) { 18 | Action a; 19 | if (!this.queue.TryDequeue(out a)) { 20 | return; 21 | } 22 | a(); 23 | } 24 | } 25 | 26 | public override void Post(SendOrPostCallback callback, object state){ 27 | this.Add(() => { callback(state); }); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Network/TCP/PacketParser.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | 5 | namespace Lockstep.Network 6 | { 7 | internal enum ParserState 8 | { 9 | PacketSize, 10 | PacketBody 11 | } 12 | 13 | public struct Packet 14 | { 15 | public const int MinSize = 2; 16 | public const int FlagIndex = 0; 17 | public const int OpcodeIndex = 1; 18 | public const int Index = 3; 19 | 20 | /// 21 | /// 只读,不允许修改 22 | /// 23 | public byte[] Bytes { get; } 24 | public ushort Length { get; set; } 25 | 26 | public Packet(int length) 27 | { 28 | this.Length = 0; 29 | this.Bytes = new byte[length]; 30 | } 31 | 32 | public Packet(byte[] bytes) 33 | { 34 | this.Bytes = bytes; 35 | this.Length = (ushort)bytes.Length; 36 | } 37 | 38 | public byte Flag() 39 | { 40 | return this.Bytes[0]; 41 | } 42 | 43 | public ushort Opcode() 44 | { 45 | return BitConverter.ToUInt16(this.Bytes, OpcodeIndex); 46 | } 47 | } 48 | 49 | internal class PacketParser 50 | { 51 | private readonly CircularBuffer buffer; 52 | 53 | private ushort packetSize; 54 | private ParserState state; 55 | private Packet packet = new Packet(ushort.MaxValue); 56 | private bool isOK; 57 | 58 | public PacketParser(CircularBuffer buffer) 59 | { 60 | this.buffer = buffer; 61 | } 62 | 63 | public bool Parse() 64 | { 65 | if (this.isOK) 66 | { 67 | return true; 68 | } 69 | 70 | bool finish = false; 71 | while (!finish) 72 | { 73 | switch (this.state) 74 | { 75 | case ParserState.PacketSize: 76 | if (this.buffer.Length < 2) 77 | { 78 | finish = true; 79 | } 80 | else 81 | { 82 | this.buffer.Read(this.packet.Bytes, 0, 2); 83 | this.packetSize = BytesHelper.ToUInt16(this.packet.Bytes, 0); 84 | if (packetSize > 60000) 85 | { 86 | throw new Exception($"packet too large, size: {this.packetSize}"); 87 | } 88 | this.state = ParserState.PacketBody; 89 | } 90 | break; 91 | case ParserState.PacketBody: 92 | if (this.buffer.Length < this.packetSize) 93 | { 94 | finish = true; 95 | } 96 | else 97 | { 98 | this.buffer.Read(this.packet.Bytes, 0, this.packetSize); 99 | this.packet.Length = this.packetSize; 100 | this.isOK = true; 101 | this.state = ParserState.PacketSize; 102 | finish = true; 103 | } 104 | break; 105 | } 106 | } 107 | return this.isOK; 108 | } 109 | 110 | public Packet GetPacket() 111 | { 112 | this.isOK = false; 113 | return this.packet; 114 | } 115 | } 116 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Network/TCP/TService.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Net.Sockets; 8 | using System.Threading.Tasks; 9 | 10 | namespace Lockstep.Network 11 | { 12 | public sealed class TService: AService 13 | { 14 | private TcpListener acceptor; 15 | 16 | private readonly Dictionary idChannels = new Dictionary(); 17 | 18 | /// 19 | /// 即可做client也可做server 20 | /// 21 | public TService(IPEndPoint ipEndPoint) 22 | { 23 | this.acceptor = new TcpListener(ipEndPoint); 24 | this.acceptor.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 25 | this.acceptor.Server.NoDelay = true; 26 | this.acceptor.Start(); 27 | } 28 | 29 | public TService() 30 | { 31 | } 32 | 33 | public override void Dispose() 34 | { 35 | if (this.acceptor == null) 36 | { 37 | return; 38 | } 39 | 40 | foreach (long id in this.idChannels.Keys.ToArray()) 41 | { 42 | TChannel channel = this.idChannels[id]; 43 | channel.Dispose(); 44 | } 45 | this.acceptor.Stop(); 46 | this.acceptor = null; 47 | } 48 | 49 | public override AChannel GetChannel(long id) 50 | { 51 | TChannel channel = null; 52 | this.idChannels.TryGetValue(id, out channel); 53 | return channel; 54 | } 55 | 56 | public override async Task AcceptChannel() 57 | { 58 | if (this.acceptor == null) 59 | { 60 | throw new Exception("service construct must use host and port param"); 61 | } 62 | TcpClient tcpClient = await this.acceptor.AcceptTcpClientAsync(); 63 | TChannel channel = new TChannel(tcpClient, this); 64 | this.idChannels[channel.Id] = channel; 65 | return channel; 66 | } 67 | 68 | public override AChannel ConnectChannel(IPEndPoint ipEndPoint) 69 | { 70 | TcpClient tcpClient = new TcpClient(); 71 | TChannel channel = new TChannel(tcpClient, ipEndPoint, this); 72 | this.idChannels[channel.Id] = channel; 73 | 74 | return channel; 75 | } 76 | 77 | 78 | public override void Remove(long id) 79 | { 80 | TChannel channel; 81 | if (!this.idChannels.TryGetValue(id, out channel)) 82 | { 83 | return; 84 | } 85 | if (channel == null) 86 | { 87 | return; 88 | } 89 | this.idChannels.Remove(id); 90 | channel.Dispose(); 91 | } 92 | 93 | public override void Update() 94 | { 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/BSP/ESplitType.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.PathFinding { 4 | public enum ESplitType { 5 | Left, 6 | Right, 7 | OnPlane, 8 | EnumCount 9 | } 10 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/BSP/SplitPlane.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Math; 4 | 5 | namespace Lockstep.PathFinding { 6 | public struct SplitPlane { 7 | public SplitPlane(LVector2 a, LVector2 b){ 8 | this.a = a; 9 | this.b = b; 10 | } 11 | 12 | public LVector2 a; 13 | public LVector2 b; 14 | public LVector2 dir => b - a; 15 | 16 | private static LFloat val; 17 | public static ESplitType GetSplitResult(SplitPlane plane, TriRef tri){ 18 | var planeDir = plane.dir; 19 | var valA = LVector2.Cross(planeDir, tri.a - plane.a); 20 | var valB = LVector2.Cross(planeDir, tri.b - plane.a); 21 | var valC = LVector2.Cross(planeDir, tri.c - plane.a); 22 | 23 | var isRight = false; 24 | if (valA != 0) isRight = valA < 0; 25 | if (valB != 0) isRight = valB < 0; 26 | if (valC != 0) isRight = valC < 0; 27 | 28 | var isA = valA <= 0; 29 | var isB = valB <= 0; 30 | var isC = valC <= 0; 31 | if (isA == isB && isB == isC) { 32 | return isRight ? ESplitType.Right : ESplitType.Left; 33 | } 34 | 35 | isA = valA >= 0; 36 | isB = valB >= 0; 37 | isC = valC >= 0; 38 | if (isA == isB && isB == isC) { 39 | return isRight ? ESplitType.Right : ESplitType.Left; 40 | } 41 | 42 | return ESplitType.OnPlane; 43 | } 44 | 45 | public static ESplitType ClassifyPointToPlane(SplitPlane plane, LVector2 vertex){ 46 | var val = LVector2.Cross(plane.dir, vertex - plane.a); 47 | if (val == 0) 48 | return ESplitType.OnPlane; 49 | else { 50 | return val < 0 ? ESplitType.Right : ESplitType.Left; 51 | } 52 | } 53 | 54 | public static LVector2 GetIntersectPoint(LVector2 p0, LVector2 p1, LVector2 p2, LVector2 p3){ 55 | var diff = p2 - p0; 56 | var d1 = p1 - p0; 57 | var d2 = p3 - p2; 58 | var demo = LMath.Cross2D(d1, d2); //det 59 | if (LMath.Abs(demo) < LFloat.EPSILON) //parallel 60 | return p0; 61 | 62 | var t1 = LMath.Cross2D(diff, d2) / demo; // Cross2D(diff,-d2) 63 | return p0 + (p1 - p0) * t1; 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/BSP/TriRef.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using Lockstep.Collision2D; 6 | using Lockstep.Math; 7 | using Debug = Lockstep.Logging.Debug; 8 | 9 | namespace Lockstep.PathFinding { 10 | public class TriRef { 11 | public int index; //正数为 原三角形,否则为 12 | public bool isSplit = false; 13 | 14 | public bool Contain(LVector2 pos){ 15 | var isRightA = LVector2.Cross(b - a, pos - a) > 0; 16 | if (isRightA) return false; 17 | var isRightB = LVector2.Cross(c - b, pos - b) > 0; 18 | if (isRightB) return false; 19 | var isRightC = LVector2.Cross(a - c, pos - c) > 0; 20 | if (isRightC) return false; 21 | return true; 22 | } 23 | 24 | public TriRef(List vertexs, TriRef tri) 25 | : this(vertexs[0], vertexs[1], vertexs[2], tri){ } 26 | 27 | 28 | public TriRef(LVector2 a, LVector2 b, LVector2 c, TriRef tri) 29 | : this(a, b, c, tri.index){ 30 | isSplit = true; 31 | } 32 | 33 | public TriRef(Triangle tri) : this( 34 | tri.a.ToLVector2XZ(), 35 | tri.b.ToLVector2XZ(), 36 | tri.c.ToLVector2XZ(), 37 | tri.index){ } 38 | 39 | public TriRef(LVector2 a, LVector2 b, LVector2 c, int idx){ 40 | this.a = a; 41 | this.b = b; 42 | this.c = c; 43 | index = idx; 44 | 45 | borders = new SplitPlane[] { 46 | new SplitPlane(a, b), 47 | new SplitPlane(b, c), 48 | new SplitPlane(c, a) 49 | }; 50 | //check valid 51 | CheckValid(); 52 | } 53 | 54 | void CheckValid(){ 55 | for (int i = 0; i < 3; i++) { 56 | if (borders[i].dir == LVector2.zero) { 57 | Debug.Assert(false); 58 | } 59 | } 60 | } 61 | 62 | public LVector2 a; 63 | public LVector2 b; 64 | public LVector2 c; 65 | 66 | public SplitPlane[] borders; 67 | 68 | public LVector2 this[int index] { 69 | get { 70 | switch (index) { 71 | case 0: return a; 72 | case 1: return b; 73 | case 2: return c; 74 | default: throw new IndexOutOfRangeException("vector idx invalid" + index); 75 | } 76 | } 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/Geometry/Plane.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using Lockstep.Math; 5 | 6 | namespace Lockstep.PathFinding { 7 | public class Plane { 8 | private static long serialVersionUID = -1240652082930747866L; 9 | 10 | public LVector3 normal = new LVector3(); // 单位长度 11 | public LFloat d = LFloat.zero; // 距离 12 | 13 | public Plane(){ } 14 | 15 | public Plane(LVector3 normal, LFloat d){ 16 | this.normal.set(normal).nor(); 17 | this.d = d; 18 | } 19 | 20 | public Plane(LVector3 normal, LVector3 point){ 21 | this.normal.set(normal).nor(); 22 | this.d = -this.normal.dot(point); 23 | } 24 | 25 | public Plane(LVector3 point1, LVector3 point2, LVector3 point3){ 26 | set(point1, point2, point3); 27 | } 28 | 29 | public void set(LVector3 point1, LVector3 point2, LVector3 point3){ 30 | normal = (point1).sub(point2).cross(point2.x - point3.x, point2.y - point3.y, point2.z - point3.z).nor(); 31 | d = -point1.dot(normal); 32 | } 33 | 34 | 35 | 36 | public LFloat distance(LVector3 point){ 37 | return normal.dot(point) + d; 38 | } 39 | 40 | public PlaneSide testPoint(LVector3 point){ 41 | LFloat dist = normal.dot(point) + d; 42 | 43 | if (dist == 0) 44 | return PlaneSide.OnPlane; 45 | else if (dist < 0) 46 | return PlaneSide.Back; 47 | else 48 | return PlaneSide.Front; 49 | } 50 | 51 | 52 | public PlaneSide testPoint(LFloat x, LFloat y, LFloat z){ 53 | LFloat dist = normal.dot(x, y, z) + d; 54 | 55 | if (dist == 0) 56 | return PlaneSide.OnPlane; 57 | else if (dist < 0) 58 | return PlaneSide.Back; 59 | else 60 | return PlaneSide.Front; 61 | } 62 | 63 | 64 | public bool isFrontFacing(LVector3 direction){ 65 | LFloat dot = normal.dot(direction); 66 | return dot <= 0; 67 | } 68 | 69 | /** @return The normal */ 70 | public LVector3 getNormal(){ 71 | return normal; 72 | } 73 | 74 | /** @return The distance to the origin */ 75 | public LFloat getD(){ 76 | return d; 77 | } 78 | 79 | 80 | public void set(LVector3 point, LVector3 normal){ 81 | this.normal.set(normal); 82 | d = -point.dot(normal); 83 | } 84 | 85 | public void set(LFloat pointX, LFloat pointY, LFloat pointZ, LFloat norX, LFloat norY, LFloat norZ){ 86 | this.normal.set(norX, norY, norZ); 87 | d = -(pointX * norX + pointY * norY + pointZ * norZ); 88 | } 89 | 90 | 91 | public void set(Plane plane){ 92 | this.normal.set(plane.normal); 93 | this.d = plane.d; 94 | } 95 | 96 | public override String ToString(){ 97 | return normal.ToString() + ", " + d; 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/Geometry/Ray.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using Lockstep.Math; 5 | 6 | namespace Lockstep.PathFinding { 7 | public class Ray { 8 | private static long serialVersionUID = -620692054835390878L; 9 | public LVector3 origin = new LVector3(); // 10 | public LVector3 direction = new LVector3(); // 11 | 12 | public Ray(){ } 13 | 14 | public Ray(LVector3 origin, LVector3 direction){ 15 | this.origin.set(origin); 16 | this.direction.set(direction).nor(); 17 | } 18 | 19 | /** @return a copy of this ray. */ 20 | public Ray cpy(){ 21 | return new Ray(this.origin, this.direction); 22 | } 23 | 24 | 25 | public LVector3 getEndPoint(LVector3 _out, LFloat distance){ 26 | return _out.set(direction).scl(distance).Add(origin); 27 | } 28 | 29 | static LVector3 tmp = new LVector3(); 30 | 31 | 32 | /** {@inheritDoc} */ 33 | public String toString(){ 34 | return "ray [" + origin + ":" + direction + "]"; 35 | } 36 | 37 | 38 | public Ray set(LVector3 origin, LVector3 direction){ 39 | this.origin.set(origin); 40 | this.direction.set(direction); 41 | return this; 42 | } 43 | 44 | public Ray set(LFloat x, LFloat y, LFloat z, LFloat dx, LFloat dy, LFloat dz){ 45 | this.origin.set(x, y, z); 46 | this.direction.set(dx, dy, dz); 47 | return this; 48 | } 49 | 50 | 51 | public Ray set(Ray ray){ 52 | this.origin.set(ray.origin); 53 | this.direction.set(ray.direction); 54 | return this; 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/NavMesh/EdgePoint.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.Collections.Generic; 4 | using Lockstep.Math; 5 | namespace Lockstep.PathFinding { 6 | public class EdgePoint { 7 | /** 8 | * Triangle which must be crossed to reach the next path point. 9 | */ 10 | public Triangle toNode; 11 | 12 | /** 13 | * Triangle which was crossed to reach this point. 14 | */ 15 | public Triangle fromNode; 16 | 17 | /** 18 | * Path edges connected to this point. Can be used for spline generation at some 19 | * point perhaps... 20 | */ 21 | public List connectingEdges = new List(); 22 | 23 | /** 24 | * The point where the path crosses an edge. 25 | */ 26 | public LVector3 point; 27 | 28 | public EdgePoint(LVector3 point, Triangle toNode){ 29 | this.point = point; 30 | this.toNode = toNode; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/NavMesh/Funnel.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Math; 4 | 5 | namespace Lockstep.PathFinding { 6 | public class Funnel { 7 | 8 | public Plane leftPlane = new Plane(); // 左平面,高度为y轴 9 | public Plane rightPlane = new Plane(); 10 | public LVector3 leftPortal = new LVector3(); // 路径左顶点, 11 | public LVector3 rightPortal = new LVector3(); // 路径右顶点 12 | public LVector3 pivot = new LVector3(); // 漏斗点,路径的起点或拐点 13 | 14 | public void setLeftPlane(LVector3 pivot, LVector3 leftEdgeVertex){ 15 | leftPlane.set(pivot, pivot.Add(LVector3.up), leftEdgeVertex); 16 | leftPortal = leftEdgeVertex; 17 | } 18 | 19 | public void setRightPlane(LVector3 pivot, LVector3 rightEdgeVertex){ 20 | rightPlane.set(pivot, pivot.Add(LVector3.up), rightEdgeVertex); // 高度 21 | rightPlane.normal = -rightPlane.normal; // 平面方向取反 22 | rightPlane.d = -rightPlane.d; 23 | rightPortal = (rightEdgeVertex); 24 | } 25 | 26 | public void setPlanes(LVector3 pivot, TriangleEdge edge){ 27 | setLeftPlane(pivot, edge.leftVertex); 28 | setRightPlane(pivot, edge.rightVertex); 29 | } 30 | 31 | public PlaneSide sideLeftPlane(LVector3 point){ 32 | return leftPlane.testPoint(point); 33 | } 34 | 35 | public PlaneSide sideRightPlane(LVector3 point){ 36 | return rightPlane.testPoint(point); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/NavMesh/Triangle.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using Lockstep.Math; 6 | using Lockstep.Math; 7 | 8 | namespace Lockstep.PathFinding { 9 | public class Triangle { 10 | /** 三角形序号 */ 11 | public int index; 12 | public LVector3 a; 13 | public LVector3 b; 14 | public LVector3 c; 15 | 16 | public LFloat y; //三角形高度,三个顶点的平均高度 17 | 18 | /** 中点 */ 19 | public LVector3 center; 20 | 21 | /** 三角形和其他三角形的共享边 */ 22 | public List> connections; 23 | 24 | /**三角形顶点序号*/ 25 | public int[] vectorIndex; 26 | 27 | public Triangle(LVector3 a, LVector3 b, LVector3 c, int index, params int[] vectorIndex){ 28 | this.a = a; 29 | this.b = b; 30 | this.c = c; 31 | this.y = (a.y + b.y + c.y) / 3; 32 | this.index = index; 33 | this.center = a.Add(b).Add(c).scl(1/3.ToLFloat()); 34 | this.connections = new List>(); 35 | this.vectorIndex = vectorIndex; 36 | } 37 | 38 | public override String ToString(){ 39 | return "Triangle [index=" + index + ", a=" + a + ", b=" + b + ", c=" + c + ", center=" + center + "]"; 40 | } 41 | 42 | public int getIndex(){ 43 | return this.index; 44 | } 45 | 46 | public List> getConnections(){ 47 | return connections; 48 | } 49 | 50 | 51 | 52 | public bool IsInnerPoint(LVector3 point){ 53 | bool res = pointInLineLeft(a, b, point); 54 | if (res != pointInLineLeft(b, c, point)) { 55 | return false; 56 | } 57 | 58 | if (res != pointInLineLeft(c, a, point)) { 59 | return false; 60 | } 61 | 62 | if (cross2D(a, b, c) == 0) { //三点共线 63 | return false; 64 | } 65 | 66 | return true; 67 | } 68 | 69 | public static LFloat cross2D(LVector3 fromPoint, LVector3 toPoint, LVector3 p){ 70 | return (toPoint.x - fromPoint.x) * (p.z - fromPoint.z) - (toPoint.z - fromPoint.z) * (p.x - fromPoint.x); 71 | } 72 | 73 | public static bool pointInLineLeft(LVector3 fromPoint, LVector3 toPoint, LVector3 p){ 74 | return cross2D(fromPoint, toPoint, p) > 0; 75 | } 76 | 77 | 78 | public override int GetHashCode(){ 79 | int prime = 31; 80 | int result = 1; 81 | result = prime * result + index; 82 | return result; 83 | } 84 | 85 | public override bool Equals(object obj){ 86 | if (this == obj) 87 | return true; 88 | if (obj == null) 89 | return false; 90 | if (GetType() != obj.GetType()) 91 | return false; 92 | Triangle other = (Triangle) obj; 93 | if (index != other.index) 94 | return false; 95 | return true; 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/NavMesh/TriangleData.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Lockstep.PathFinding { 8 | [Serializable] 9 | public class TriangleData : NavMeshData { 10 | private static long serialVersionUID = 1L; 11 | } 12 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/NavMesh/TriangleEdge.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using Lockstep.Math; 7 | 8 | 9 | 10 | 11 | 12 | /** 13 | * 相连接三角形的共享边 14 | * 15 | * @author JiangZhiYong 16 | * @QQ 359135103 2017年11月7日 下午4:50:11 17 | */ 18 | 19 | using System; 20 | using System.Text; 21 | 22 | namespace Lockstep.PathFinding { 23 | public class TriangleEdge : Connection { 24 | /** 右顶点 */ 25 | public LVector3 rightVertex; 26 | public LVector3 leftVertex; 27 | 28 | /** 源三角形 */ 29 | public Triangle fromNode; 30 | 31 | /** 指向的三角形 */ 32 | public Triangle toNode; 33 | 34 | public TriangleEdge(LVector3 rightVertex, LVector3 leftVertex) : this(null, null, rightVertex, leftVertex){ } 35 | 36 | public TriangleEdge(Triangle fromNode, Triangle toNode, LVector3 rightVertex, LVector3 leftVertex){ 37 | this.fromNode = fromNode; 38 | this.toNode = toNode; 39 | this.rightVertex = rightVertex; 40 | this.leftVertex = leftVertex; 41 | } 42 | 43 | public LFloat GetCost(){ 44 | return LFloat.one; 45 | } 46 | 47 | public Triangle GetFromNode(){ 48 | return fromNode; 49 | } 50 | 51 | public Triangle GetToNode(){ 52 | return toNode; 53 | } 54 | 55 | public override String ToString(){ 56 | StringBuilder sb = new StringBuilder("Edge{"); 57 | sb.Append("fromNode=").Append(fromNode.index); 58 | //sb.Append(", toNode=").Append(toNode == null ? "null" : toNode.index); 59 | sb.Append(", rightVertex=").Append(rightVertex); 60 | sb.Append(", leftVertex=").Append(leftVertex); 61 | sb.Append('}'); 62 | return sb.ToString(); 63 | } 64 | 65 | } 66 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/NavMesh/TriangleGraphPath.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using Lockstep.Math; 6 | 7 | namespace Lockstep.PathFinding { 8 | public class TriangleGraphPath : DefaultGraphPath> { 9 | /** 10 | * The start point when generating a point path for this triangle path 11 | */ 12 | public LVector3 start; 13 | 14 | /** 15 | * The end point when generating a point path for this triangle path 16 | */ 17 | public LVector3 end; 18 | 19 | /** 20 | * If the triangle path is empty, the point path will span this triangle 21 | */ 22 | public Triangle startTri; 23 | 24 | /** 25 | * @return Last triangle in the path. 26 | */ 27 | public Triangle GetEndTriangle(){ 28 | return (GetCount() > 0) ? Get(GetCount() - 1).GetToNode() : startTri; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/NavMesh/TriangleHeuristic.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using Lockstep.Math; 6 | 7 | namespace Lockstep.PathFinding { 8 | public class TriangleHeuristic : Heuristic { 9 | private static LVector3 A_AB = new LVector3(); 10 | private static LVector3 A_BC = new LVector3(); 11 | private static LVector3 A_CA = new LVector3(); 12 | private static LVector3 B_AB = new LVector3(); 13 | private static LVector3 B_BC = new LVector3(); 14 | private static LVector3 B_CA = new LVector3(); 15 | 16 | public LFloat Estimate(Triangle node, Triangle endNode){ 17 | LFloat dst2; 18 | LFloat minDst2 = LFloat.MaxValue; 19 | A_AB = (node.a).Add(node.b) * LFloat.half; 20 | A_AB = (node.b).Add(node.c) * LFloat.half; 21 | A_AB = (node.c).Add(node.a) * LFloat.half; 22 | 23 | B_AB = (endNode.a).Add(endNode.b) * LFloat.half; 24 | B_BC = (endNode.b).Add(endNode.c) * LFloat.half; 25 | B_CA = (endNode.c).Add(endNode.a) * LFloat.half; 26 | 27 | if ((dst2 = A_AB.dst2(B_AB)) < minDst2) 28 | minDst2 = dst2; 29 | if ((dst2 = A_AB.dst2(B_BC)) < minDst2) 30 | minDst2 = dst2; 31 | if ((dst2 = A_AB.dst2(B_CA)) < minDst2) 32 | minDst2 = dst2; 33 | 34 | if ((dst2 = A_BC.dst2(B_AB)) < minDst2) 35 | minDst2 = dst2; 36 | if ((dst2 = A_BC.dst2(B_BC)) < minDst2) 37 | minDst2 = dst2; 38 | if ((dst2 = A_BC.dst2(B_CA)) < minDst2) 39 | minDst2 = dst2; 40 | 41 | if ((dst2 = A_CA.dst2(B_AB)) < minDst2) 42 | minDst2 = dst2; 43 | if ((dst2 = A_CA.dst2(B_BC)) < minDst2) 44 | minDst2 = dst2; 45 | if ((dst2 = A_CA.dst2(B_CA)) < minDst2) 46 | minDst2 = dst2; 47 | 48 | return (LFloat) LMath.Sqrt(minDst2); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/NavMesh/TriangleNavMesh.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using Lockstep.Math; 6 | using Lockstep.Util; 7 | using Debug = Lockstep.Logging.Debug; 8 | 9 | namespace Lockstep.PathFinding { 10 | public class TriangleNavMesh : NavMesh { 11 | public TriangleGraph _graph; 12 | private TriangleHeuristic _heuristic; 13 | public IndexedAStarPathFinder _pathFinder; 14 | 15 | public TriangleNavMesh(String navMeshStr) : this(navMeshStr, 1){ } 16 | public BspTree bspTree => _graph.bspTree; 17 | public TriangleNavMesh(String navMeshStr, int scale){ 18 | var data = JsonUtil.ToObject(navMeshStr); 19 | _graph = new TriangleGraph(data, scale); 20 | _pathFinder = new IndexedAStarPathFinder(_graph, true); 21 | _heuristic = new TriangleHeuristic(); 22 | } 23 | 24 | public TriangleGraphPath navMeshGraphPath = null; 25 | 26 | public List FindPath(LVector3 fromPoint, LVector3 toPoint, TrianglePointPath navMeshPointPath){ 27 | navMeshGraphPath = new TriangleGraphPath(); 28 | bool find = FindPath(fromPoint, toPoint, navMeshGraphPath); 29 | if (!find) { 30 | return null; 31 | } 32 | 33 | navMeshPointPath.CalculateForGraphPath(navMeshGraphPath, false); 34 | return navMeshPointPath.getVectors(); 35 | } 36 | 37 | private bool FindPath(LVector3 fromPoint, LVector3 toPoint, TriangleGraphPath path){ 38 | path.Clear(); 39 | Triangle fromTriangle = GetTriangle(fromPoint); 40 | var toTriangle = GetTriangle(toPoint); 41 | if (_pathFinder.SearchPath(fromTriangle, toTriangle, _heuristic, path)) { 42 | path.start = fromPoint; 43 | path.end = toPoint; 44 | path.startTri = fromTriangle; 45 | return true; 46 | } 47 | 48 | return false; 49 | } 50 | 51 | public TriangleGraph GetGraph(){ 52 | return _graph; 53 | } 54 | 55 | public TriangleHeuristic GetHeuristic(){ 56 | return _heuristic; 57 | } 58 | 59 | public IndexedAStarPathFinder GetPathFinder(){ 60 | return _pathFinder; 61 | } 62 | 63 | 64 | public Triangle GetTriangle(LVector3 point){ 65 | return _graph.GetTriangle(point); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/PathFinder/Connection.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using Lockstep.Math; 6 | 7 | namespace Lockstep.PathFinding { 8 | public interface Connection { 9 | 10 | /** Returns the non-negative cost of this connection */ 11 | LFloat GetCost(); 12 | 13 | /** Returns the node that this connection came from */ 14 | N GetFromNode(); 15 | 16 | /** Returns the node that this connection leads to */ 17 | N GetToNode(); 18 | } 19 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/PathFinder/DefaultGraphPath.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using Lockstep.Math; 6 | 7 | namespace Lockstep.PathFinding { 8 | public class DefaultGraphPath : GraphPath { 9 | public List nodes; 10 | 11 | /** Creates a {@code DefaultGraphPath} with no nodes. */ 12 | public DefaultGraphPath() : this(new List()){ } 13 | 14 | /** Creates a {@code DefaultGraphPath} with the given capacity and no nodes. */ 15 | public DefaultGraphPath(int capacity) : this(new List(capacity)){ } 16 | 17 | /** Creates a {@code DefaultGraphPath} with the given nodes. */ 18 | public DefaultGraphPath(List nodes){ 19 | this.nodes = nodes; 20 | } 21 | 22 | public void Clear(){ 23 | nodes.Clear(); 24 | } 25 | 26 | public int GetCount(){ 27 | return nodes.Count; 28 | } 29 | 30 | public void Add(N node){ 31 | nodes.Add(node); 32 | } 33 | 34 | public N Get(int index){ 35 | return nodes[index]; 36 | } 37 | 38 | public void reverse(){ 39 | nodes.Reverse(); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/PathFinder/Graph.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using Lockstep.Math; 8 | 9 | 10 | 11 | /** 12 | * 图接口 13 | *
14 | * A graph is a collection of nodes, each one having a collection of 15 | * outgoing {@link Connection connections}. 16 | * 17 | * @param 18 | * Type of node 19 | * 20 | * @author davebaol 21 | */ 22 | 23 | using System.Collections.Generic; 24 | 25 | namespace Lockstep.PathFinding { 26 | public interface Graph { 27 | 28 | /**和当前节点相连的连接关系 29 | * Returns the connections outgoing from the given node. 30 | * 31 | * @param fromNode 32 | * the node whose outgoing connections will be returned 33 | * @return the array of connections outgoing from the given node. 34 | */ 35 | List> GetConnections(N fromNode); 36 | } 37 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/PathFinder/GraphPath.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using Lockstep.Math; 7 | 8 | namespace Lockstep.PathFinding { 9 | 10 | public interface GraphPath { 11 | 12 | /** Returns the number of items of this path. */ 13 | int GetCount(); 14 | 15 | /** Returns the item of this path at the given index. */ 16 | N Get(int index); 17 | 18 | /** Adds an item at the end of this path. */ 19 | void Add(N node); 20 | 21 | /** Clears this path. */ 22 | void Clear(); 23 | 24 | /** Reverses this path. */ 25 | void reverse(); 26 | 27 | } 28 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/PathFinder/Heuristic.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | 4 | 5 | using Lockstep.Math; 6 | 7 | namespace Lockstep.PathFinding { 8 | /** 9 | *
10 | * A {@code Heuristic} generates estimates of the cost to move from a given node to the goal. 11 | *

12 | * With a heuristic function pathfinding algorithms can choose the node that is most likely to lead to the optimal path. The 13 | * notion of "most likely" is controlled by a heuristic. If the heuristic is accurate, then the algorithm will be efficient. If 14 | * the heuristic is terrible, then it can perform even worse than other algorithms that don't use any heuristic function such as 15 | * Dijkstra. 16 | * 17 | * @param Type of node 18 | * 19 | * @author davebaol */ 20 | public interface Heuristic { 21 | 22 | /** Calculates an estimated cost to reach the goal node from the given node. 23 | * @param node the start node 24 | * @param endNode the end node 25 | * @return the estimated cost */ 26 | LFloat Estimate(N node, N endNode); 27 | } 28 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/PathFinder/IndexedGraph.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using Lockstep.Math; 8 | 9 | namespace Lockstep.PathFinding { 10 | 11 | /** 12 | *
13 | * A graph for the {@link IndexedAStarPathFinder}. 14 | * 15 | * @param Type of node 16 | * 17 | * @author davebaol */ 18 | public interface IndexedGraph : Graph { 19 | 20 | /** Returns the unique index of the given node. 21 | * @param node the node whose index will be returned 22 | * @return the unique index of the given node. */ 23 | int GetIndex(N node); 24 | 25 | /** Returns the number of nodes in this graph. */ 26 | int GetNodeCount(); 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/PathFinder/NavMesh.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using Lockstep.Math; 7 | 8 | namespace Lockstep.PathFinding { 9 | public abstract class NavMesh { 10 | 11 | /** 地图宽x轴 */ 12 | protected LFloat width; 13 | 14 | /** 地图高y轴 */ 15 | protected LFloat height; 16 | 17 | /** 配置id */ 18 | protected int mapId; 19 | 20 | public LFloat getWidth(){ 21 | return width; 22 | } 23 | 24 | public void setWidth(LFloat width){ 25 | this.width = width; 26 | } 27 | 28 | public LFloat getHeight(){ 29 | return height; 30 | } 31 | 32 | public void setHeight(LFloat height){ 33 | this.height = height; 34 | } 35 | 36 | public int getMapId(){ 37 | return mapId; 38 | } 39 | 40 | public void setMapId(int mapId){ 41 | this.mapId = mapId; 42 | } 43 | 44 | } 45 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/PathFinder/PathFinder.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.PathFinding { 4 | public interface PathFinder { 5 | 6 | bool SearchPath(N startNode, N endNode, Heuristic heuristic, GraphPath> outPath); 7 | 8 | bool SearchNodePath(N startNode, N endNode, Heuristic heuristic, GraphPath outPath); 9 | } 10 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/PathFinding/NavMesh/VectorExtension.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using Lockstep.Math; 7 | 8 | namespace Lockstep.PathFinding { 9 | public static class VectorExtension { 10 | public static LVector3 set(this LVector3 vec, LFloat x, LFloat y, LFloat z){ 11 | vec.x = x; 12 | vec.y = y; 13 | vec.z = z; 14 | return vec; 15 | } 16 | 17 | public static LVector3 set(this LVector3 vec, LVector3 val){ 18 | vec = val; 19 | return vec; 20 | } 21 | 22 | public static LVector3 mulAdd(this LVector3 _this, LVector3 vec, LFloat scalar){ 23 | _this.x += vec.x * scalar; 24 | _this.y += vec.y * scalar; 25 | _this.z += vec.z * scalar; 26 | return _this; 27 | } 28 | 29 | public static LVector3 Add(this LVector3 vec, LVector3 val){ 30 | return vec + val; 31 | } 32 | 33 | public static LVector3 sub(this LVector3 vec, LVector3 val){ 34 | return vec - val; 35 | } 36 | 37 | public static LVector3 scl(this LVector3 vec, LFloat val){ 38 | return vec * val; 39 | } 40 | 41 | public static LFloat dot(this LVector3 vec, LVector3 val){ 42 | return LVector3.Dot(vec, val); 43 | } 44 | public static LFloat dot(this LVector3 vec, LFloat x, LFloat y, LFloat z){ 45 | return LVector3.Dot(vec, new LVector3(x, y, z)); 46 | } 47 | 48 | 49 | public static LVector3 cross(this LVector3 vec, LVector3 vector){ 50 | return new LVector3(vec.y * vector.z - vec.z * vector.y, vec.z * vector.x - vec.x * vector.z, 51 | vec.x * vector.y - vec.y * vector.x); 52 | } 53 | 54 | public static LVector3 cross(this LVector3 vec, LFloat x, LFloat y, LFloat z){ 55 | return new LVector3(vec.y * z - vec.z * y, vec.z * x - vec.x * z, vec.x * y - vec.y * x); 56 | } 57 | 58 | public static LVector3 nor(this LVector3 vec){ 59 | return vec.normalized; 60 | } 61 | 62 | public static LFloat len(this LVector3 vec){ 63 | return vec.magnitude; 64 | } 65 | 66 | public static LFloat dst2(this LVector3 vec, LVector3 p){ 67 | return dst2(vec.x, vec.z, p.x, p.z); 68 | } 69 | 70 | public static LFloat dst2(LFloat x1, LFloat z1, LFloat x2, LFloat z2){ 71 | x1 -= x2; 72 | z1 -= z2; 73 | return (x1 * x1 + z1 * z1); 74 | } 75 | 76 | public static T get(this List lst, int idx){ 77 | return lst[idx]; 78 | } 79 | 80 | public static Tval get(this Dictionary lst, Tkey idx){ 81 | return lst[idx]; 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Serializaition/Src/BaseMsg.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Util; 4 | 5 | namespace Lockstep.Serialization { 6 | ///

7 | /// 不序列化到文件中 8 | /// 9 | [System.AttributeUsage( 10 | System.AttributeTargets.Class | 11 | System.AttributeTargets.Field | 12 | System.AttributeTargets.Property, 13 | AllowMultiple = false 14 | )] 15 | public class NoGenCodeAttribute : System.Attribute { } 16 | 17 | 18 | [System.Serializable] 19 | [SelfImplement] 20 | public partial class BaseFormater : ISerializable, ISerializablePacket { 21 | public virtual void Serialize(Serializer writer){ } 22 | 23 | public virtual void Deserialize(Deserializer reader){ } 24 | 25 | public override string ToString(){ 26 | return JsonUtil.ToJson(this); 27 | } 28 | 29 | public byte[] ToBytes(){ 30 | var writer = new Serializer(); 31 | Serialize(writer); 32 | var bytes = writer.CopyData(); // Compressor.Compress(writer.CopyData()); 33 | return bytes; 34 | } 35 | public void FromBytes(byte[] data){ 36 | var bytes = data; //Compressor.Decompress(data); 37 | var reader = new Deserializer(bytes); 38 | Deserialize(reader); 39 | } 40 | public void FromBytes(byte[] data,int offset,int size){ 41 | var bytes = data; //Compressor.Decompress(data); 42 | var reader = new Deserializer(bytes,offset,size); 43 | Deserialize(reader); 44 | } 45 | 46 | public static T FromBytes(byte[] data) where T : BaseFormater, new(){ 47 | var ret = new T(); 48 | ret.FromBytes(data,0,data.Length); 49 | return ret; 50 | } 51 | public static T FromBytes(byte[] data,int offset,int size) where T : BaseFormater, new(){ 52 | var ret = new T(); 53 | ret.FromBytes(data,offset,size); 54 | return ret; 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Serializaition/Src/ByteHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | 5 | namespace Lockstep.Serialization { 6 | public class ByteHelper { 7 | public static void CopyBytes(short value, byte[] buffer, int index){ 8 | CopyBytesImpl(value, 2, buffer, index); 9 | } 10 | 11 | /// Copies the specified 32-bit signed integer value into the specified byte array, 12 | /// beginning at the specified index. 13 | public static void CopyBytes(int value, byte[] buffer, int index){ 14 | CopyBytesImpl(value, 4, buffer, index); 15 | } 16 | 17 | protected static void CopyBytesImpl(long value, int bytes, byte[] buffer, int index){ 18 | for (var i = 0; i < bytes; i++) { 19 | buffer[i + index] = unchecked((byte) (value & 0xff)); 20 | value = value >> 8; 21 | } 22 | } 23 | 24 | /// Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array. 25 | public static short ToInt16(byte[] value, int startIndex){ 26 | return unchecked((short) CheckedFromBytes(value, startIndex, 2)); 27 | } 28 | 29 | /// Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array. 30 | public static int ToInt32(byte[] value, int startIndex){ 31 | return unchecked((int) CheckedFromBytes(value, startIndex, 4)); 32 | } 33 | 34 | private static long CheckedFromBytes(byte[] buffer, int startIndex, int bytesToConvert){ 35 | if (buffer == null) 36 | throw new ArgumentNullException("buffer"); 37 | if ((startIndex < 0) || (startIndex > buffer.Length - bytesToConvert)) 38 | throw new ArgumentOutOfRangeException("startIndex"); 39 | long ret = 0; 40 | for (var i = 0; i < bytesToConvert; i++) 41 | ret = unchecked((ret << 8) | buffer[startIndex + bytesToConvert - 1 - i]); 42 | return ret; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Serializaition/Src/Compressor.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.IO; 4 | using System.IO.Compression; 5 | 6 | namespace Lockstep.Serialization 7 | { 8 | public static class Compressor 9 | { 10 | 11 | public static byte[] Compress(byte[] data) 12 | { 13 | using (var output = new MemoryStream()) 14 | { 15 | using (var dstream = new DeflateStream(output, CompressionLevel.Optimal)) 16 | { 17 | dstream.Write(data, 0, data.Length); 18 | } 19 | return output.ToArray(); 20 | } 21 | } 22 | 23 | public static byte[] Compress(Serializer serializer) 24 | { 25 | using (var output = new MemoryStream()) 26 | { 27 | using (var dstream = new DeflateStream(output, CompressionLevel.Optimal)) 28 | { 29 | dstream.Write(serializer.Data, 0, serializer.Length); 30 | } 31 | return output.ToArray(); 32 | } 33 | } 34 | 35 | public static byte[] Decompress(byte[] data) 36 | { 37 | using (var input = new MemoryStream(data)) 38 | { 39 | using (var output = new MemoryStream()) 40 | { 41 | using (var dstream = new DeflateStream(input, CompressionMode.Decompress)) 42 | { 43 | dstream.CopyTo(output); 44 | } 45 | return output.ToArray(); 46 | } 47 | } 48 | 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Serializaition/Src/NetMsgExtension.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using Lockstep.Serialization; 5 | 6 | namespace Lockstep.Serialization { 7 | public class NoToBytesAttribute : Attribute { } 8 | 9 | public class ToBytesAttribute : Attribute { } 10 | 11 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] 12 | public class IndexAttribute : Attribute { 13 | public int idx; 14 | 15 | public IndexAttribute(int idx){ 16 | this.idx = idx; 17 | } 18 | } 19 | 20 | [AttributeUsage(AttributeTargets.Class)] 21 | public class TypeIdAttribute : Attribute { 22 | public int idx; 23 | 24 | public TypeIdAttribute(int idx){ 25 | this.idx = idx; 26 | } 27 | } 28 | 29 | 30 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] 31 | public class ExtFormatAttribute : Attribute { } 32 | 33 | public static class NetMsgExtension { 34 | 35 | public static T Parse(this Deserializer reader) where T : ISerializable,new (){ 36 | var val = new T(); 37 | val.Deserialize(reader); 38 | return val; 39 | } 40 | } 41 | 42 | 43 | public static class ArrayExtention { 44 | public static bool EqualsEx(this byte[] arra, byte[] arrb) { 45 | if ((arra == null) != (arrb == null)) return false; 46 | if (arra == null) { 47 | return true; 48 | } 49 | var count = arra.Length; 50 | if (count != arrb.Length) { 51 | return false; 52 | } 53 | for (int i = 0; i < count; i++) { 54 | if (arra[i] != arrb[i]) { 55 | return false; 56 | } 57 | } 58 | 59 | return true; 60 | } 61 | 62 | public static bool EqualsEx(this T[] arra, T[] arrb) where T : class{ 63 | if ((arra == null) != (arrb == null)) return false; 64 | if (arra == null) { 65 | return true; 66 | } 67 | 68 | var count = arra.Length; 69 | if (count != arrb.Length) { 70 | return false; 71 | } 72 | 73 | for (int i = 0; i < count; i++) { 74 | var a = arra[i]; 75 | var b = arrb[i]; 76 | if ((a == null) != (b == null)) return false; 77 | if (a == null) { 78 | continue; 79 | } 80 | 81 | if (!a.Equals(b)) { 82 | return false; 83 | } 84 | } 85 | 86 | return true; 87 | } 88 | } 89 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Services/Core/IService.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.Game 4 | { 5 | public interface IService { 6 | } 7 | 8 | public interface IDoInit { 9 | void DoInit(object objParent); 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Services/Core/IServiceContainer.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace Lockstep.Game 7 | { 8 | public interface IServiceContainer { 9 | T GetService() where T : IService; 10 | IService[] GetAllServices(); 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Services/Core/ITimeMachine.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | 6 | namespace Lockstep.Game { 7 | public interface ITimeMachine { 8 | int CurTick { get;} 9 | ///Rollback to tick , so all cmd between [tick,~)(Include tick) should undo 10 | void RollbackTo(int tick); 11 | void Backup(int tick); 12 | ///Discard all cmd between [0,maxVerifiedTick] (Include maxVerifiedTick) 13 | void Clean(int maxVerifiedTick); 14 | } 15 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Services/Core/ITimeMachineService.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.Game { 4 | public interface ITimeMachineService : ITimeMachine,IService { 5 | } 6 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Services/Interfaces/IECSFactoryService.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.Game { 4 | public interface IECSFactoryService : IService { 5 | object CreateContexts(); 6 | object CreateSystems(object contexts, IServiceContainer services); 7 | } 8 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Services/Interfaces/IHashCode.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.Game { 4 | public interface IHashCode { 5 | int GetHash(ref int idx); 6 | } 7 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Services/Interfaces/IIdService.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | namespace Lockstep.Game { 4 | public interface IIdService : IService { 5 | int GenId(); 6 | } 7 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Services/Interfaces/IRandomService.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Math; 4 | 5 | namespace Lockstep.Game { 6 | public interface IRandomService : IService { 7 | LFloat value { get; } 8 | uint Next(); 9 | uint Next(uint max); 10 | int Next(int max); 11 | uint Range(uint min, uint max); 12 | int Range(int min, int max); 13 | LFloat Range(LFloat min, LFloat max); 14 | } 15 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Services/Services/IdService.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.Collections.Generic; 4 | using Lockstep.Math; 5 | 6 | namespace Lockstep.Game { 7 | public partial class IdService : IIdService, ITimeMachine { 8 | public int CurTick { get; set; } 9 | 10 | private int Id; 11 | 12 | public int GenId(){ 13 | return Id++; 14 | } 15 | 16 | Dictionary _tick2Id = new Dictionary(); 17 | 18 | public void RollbackTo(int tick){ 19 | Id = _tick2Id[tick]; 20 | } 21 | 22 | public void Backup(int tick){ 23 | _tick2Id[tick] = Id; 24 | } 25 | 26 | public void Clean(int maxVerifiedTick){ } 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Services/Services/RandomService.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using Lockstep.Logging; 6 | using Lockstep.Math; 7 | using Random = Lockstep.Math.Random; 8 | 9 | namespace Lockstep.Game { 10 | public partial class RandomService : IRandomService ,ITimeMachine{ 11 | Random _i = new Math.Random(); 12 | public LFloat value => _i.value; 13 | 14 | public uint Next(){ 15 | return _i.Next(); 16 | } 17 | 18 | public uint Next(uint max){ 19 | return _i.Next(max); 20 | } 21 | 22 | public int Next(int max){ 23 | return _i.Next(max); 24 | } 25 | 26 | public uint Range(uint min, uint max){ 27 | return _i.Range(min, max); 28 | } 29 | 30 | public int Range(int min, int max){ 31 | return _i.Range(min, max); 32 | } 33 | 34 | public LFloat Range(LFloat min, LFloat max){ 35 | return _i.Range(min, max); 36 | } 37 | 38 | public int CurTick { get; set; } 39 | Dictionary _tick2Id = new Dictionary(); 40 | 41 | public void RollbackTo(int tick){ 42 | _i.randSeed = _tick2Id[tick]; 43 | } 44 | 45 | public void Backup(int tick){ 46 | _tick2Id[tick] = _i.randSeed; 47 | } 48 | 49 | public void Clean(int maxVerifiedTick){ 50 | 51 | } 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Services/Services/ServiceContainer.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace Lockstep.Game { 8 | public class ServiceContainer : IServiceContainer { 9 | protected Dictionary _allServices = new Dictionary(); 10 | 11 | public IService[] GetAllServices(){ 12 | return _allServices.Values.ToArray(); 13 | } 14 | 15 | public void RegisterService(IService service, bool overwriteExisting = true){ 16 | var interfaceTypes = service.GetType().FindInterfaces((type, criteria) => 17 | type.GetInterfaces().Any(t => t == typeof(IService)), service) 18 | .ToArray(); 19 | if (service is IDoInit svc) { 20 | svc.DoInit(null); 21 | } 22 | 23 | foreach (var type in interfaceTypes) { 24 | if (!_allServices.ContainsKey(type)) 25 | _allServices.Add(type, service); 26 | else if (overwriteExisting) { 27 | _allServices[type] = service; 28 | } 29 | } 30 | } 31 | 32 | 33 | public T GetService() where T : IService{ 34 | var key = typeof(T); 35 | if (!_allServices.ContainsKey(key)) { 36 | return default(T); 37 | } 38 | else { 39 | return (T) _allServices[key]; 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Services/Services/TimeMachineContainer.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace Lockstep.Game { 7 | public interface ITimeMachineContainer : ITimeMachineService { 8 | void RegisterTimeMachine(ITimeMachine roll); 9 | } 10 | 11 | public class TimeMachineContainer : ITimeMachineContainer { 12 | private HashSet _timeMachineHash = new HashSet(); 13 | private ITimeMachine[] _allTimeMachines; 14 | 15 | public int CurTick { get; private set; } 16 | private ITimeMachine[] GetAllTimeMachines(){ 17 | if (_allTimeMachines == null) { 18 | _allTimeMachines = _timeMachineHash.ToArray(); 19 | } 20 | 21 | return _allTimeMachines; 22 | } 23 | 24 | public void RegisterTimeMachine(ITimeMachine roll){ 25 | if (roll != null && roll != this && _timeMachineHash.Add(roll)) ; 26 | { 27 | _allTimeMachines = null; 28 | } 29 | } 30 | 31 | public void RollbackTo(int tick){ 32 | CurTick = tick; 33 | foreach (var timeMachine in GetAllTimeMachines()) { 34 | timeMachine.RollbackTo(tick); 35 | } 36 | } 37 | 38 | public void Backup(int tick){ 39 | CurTick = tick; 40 | foreach (var timeMachine in GetAllTimeMachines()) { 41 | timeMachine.Backup(tick); 42 | } 43 | } 44 | 45 | public void Clean(int maxVerifiedTick){ 46 | foreach (var timeMachine in GetAllTimeMachines()) { 47 | timeMachine.Clean(maxVerifiedTick); 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/TableReader/TableData.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using Lockstep.Serialization; 6 | 7 | public class TableData : ITableData where T : ITableData, new() { 8 | private static readonly T _instance = new T(); 9 | private static TableInfo _tableInfo; 10 | 11 | public static int RowCount => _tableInfo.RowsCount; 12 | 13 | public static void Load(){ 14 | if (_tableInfo != null) return; 15 | _tableInfo = TableManager.GetTableInfo>(_instance.Name()); 16 | } 17 | 18 | public static void LoadAll(){ 19 | Load(); 20 | _tableInfo.LoadAll(); 21 | } 22 | 23 | public static void UnLoad(bool isRemove = true){ 24 | if (_tableInfo == null) return; 25 | _tableInfo.UnLoad(); 26 | _tableInfo = null; 27 | } 28 | 29 | public static T GetData(int key1){ 30 | ulong keyID = TableHelper.GetKey(key1); 31 | return _tableInfo.GetOrLoad(keyID); 32 | } 33 | 34 | public static T GetData(int key1, int key2){ 35 | ulong keyID = TableHelper.GetKey(key1, key2); 36 | return _tableInfo.GetOrLoad(keyID); 37 | } 38 | 39 | public static T GetData(int key1, int key2, int key3){ 40 | ulong keyID = TableHelper.GetKey(key1, key2, key3); 41 | return _tableInfo.GetOrLoad(keyID); 42 | } 43 | 44 | public static T GetData(int key1, int key2, int key3, int key4){ 45 | ulong keyID = TableHelper.GetKey(key1, key2, key3, key4); 46 | return _tableInfo.GetOrLoad(keyID); 47 | } 48 | 49 | public static bool HasData(int key1){ 50 | ulong keyID = TableHelper.GetKey(key1); 51 | return _tableInfo.HasData(keyID); 52 | } 53 | 54 | public static bool HasData(int key1, int key2){ 55 | ulong keyID = TableHelper.GetKey(key1, key2); 56 | return _tableInfo.HasData(keyID); 57 | } 58 | 59 | public static bool HasData(int key1, int key2, int key3){ 60 | ulong keyID = TableHelper.GetKey(key1, key2, key3); 61 | return _tableInfo.HasData(keyID); 62 | } 63 | 64 | public static bool HasData(int key1, int key2, int key3, int key4){ 65 | ulong keyID = TableHelper.GetKey(key1, key2, key3, key4); 66 | return _tableInfo.HasData(keyID); 67 | } 68 | 69 | public static Dictionary GetAllData(){ 70 | _tableInfo.LoadAll(); 71 | return _tableInfo.GetAllData(); 72 | } 73 | 74 | public void ParseData(Deserializer reader, int offset, ushort len){ 75 | reader.SetPosition(offset); 76 | try { 77 | DoParseData(reader); 78 | } 79 | catch (Exception e) { 80 | throw new Exception( 81 | $" {Name()} DoParseData Data Error offset+Len:{offset} + {len} != Position:{reader.Position}"); 82 | } 83 | 84 | if (reader.Position != offset + len) { 85 | throw new Exception( 86 | $" {Name()} Parse Data Error offset+Len:{offset} + {len} != Position:{reader.Position}"); 87 | } 88 | } 89 | 90 | public virtual string Name(){ 91 | return ""; 92 | } 93 | 94 | protected virtual void DoParseData(Deserializer reader){ } 95 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/TableReader/TableHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | 5 | public class TableHelper 6 | { 7 | public static string GetLanguageValue(string contentCN, string tableName) 8 | { 9 | return ""; 10 | } 11 | 12 | public static ulong GetKey(int key1) 13 | { 14 | return Convert.ToUInt64(key1); 15 | } 16 | 17 | public static ulong GetKey(int key1, int key2) 18 | { 19 | return (((ulong)key1 & 0xffffffff) | (((ulong)key2 & 0xffffffff) << 32)); 20 | } 21 | 22 | public static ulong GetKey(int key1, int key2, int key3) 23 | { 24 | short shortKey2 = Convert.ToInt16(key2); 25 | short shortKey3 = Convert.ToInt16(key3); 26 | return (((ulong)key1 & 0xffffffff) | (((ulong)shortKey2 & 0xffff) << 32) | (((ulong)shortKey3 & 0xffff) << 48)); 27 | } 28 | 29 | 30 | public static ulong GetKey(int key1, int key2, int key3, int key4) 31 | { 32 | short shortKey1 = Convert.ToInt16(key1); 33 | short shortKey2 = Convert.ToInt16(key2); 34 | short shortKey3 = Convert.ToInt16(key3); 35 | short shortKey4 = Convert.ToInt16(key4); 36 | return (((ulong)shortKey1 & 0xffff) | (((ulong)shortKey2 & 0xffff) << 16) | (((ulong)shortKey3 & 0xffff) << 32) | (((ulong)shortKey4 & 0xffff) << 48)); 37 | } 38 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/TableReader/TableInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using Lockstep.Logging; 8 | using Lockstep.Serialization; 9 | 10 | 11 | public class TableInfo : ITableInfo where T : ITableData, new() { 12 | public string Name { get; private set; } 13 | protected Dictionary key2RowInfo; 14 | protected Dictionary key2Data; 15 | protected Deserializer reader; 16 | public ushort RowsCount; 17 | 18 | public Dictionary GetAllData(){ 19 | return key2Data; 20 | } 21 | 22 | public void Init(string name, byte[] bytes){ 23 | Name = name; 24 | key2Data = new Dictionary(); 25 | reader = new Deserializer(bytes); 26 | RowsCount = reader.ReadUInt16(); 27 | var headOffset = reader.ReadInt32(); 28 | key2RowInfo = new Dictionary(RowsCount); 29 | reader.SetPosition(headOffset); 30 | for (int i = 0; i < RowsCount; i++) { 31 | var key = reader.ReadUInt64(); 32 | var offset = reader.ReadInt32(); 33 | var len = reader.ReadUInt16(); 34 | key2RowInfo.Add(key, new TableRowInfo(len, offset)); 35 | } 36 | } 37 | 38 | public void UnLoad(){ 39 | reader = null; 40 | key2RowInfo = null; 41 | key2Data = null; 42 | } 43 | 44 | public void LoadAll(){ 45 | if (RowsCount == key2Data.Count) return; 46 | foreach (var key in key2RowInfo.Keys) { 47 | if (!key2Data.ContainsKey(key)) { 48 | Load(key); 49 | } 50 | } 51 | } 52 | 53 | public bool HasData(ulong key){ 54 | return key2RowInfo.ContainsKey(key); 55 | } 56 | 57 | public T GetOrLoad(ulong key){ 58 | if (key2Data.TryGetValue(key, out T val)) { 59 | return val; 60 | } 61 | return Load(key); 62 | } 63 | 64 | protected T Load(ulong key){ 65 | Debug.Assert(key2RowInfo.ContainsKey(key), "Table do not have key= " + key); 66 | if (key2RowInfo.TryGetValue(key, out var data)) { 67 | T val = new T(); 68 | val.ParseData(reader, data.offset, data.len); 69 | key2Data.Add(key, val); 70 | return val; 71 | } 72 | 73 | return default(T); 74 | } 75 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/TableReader/TableManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | 7 | public class TableManager { 8 | private static string _relPath; 9 | private static string _postfix = ".bytes"; 10 | private static Dictionary _tableInfoDic = new Dictionary(); 11 | 12 | public static void Init(string relPath,string postfix = ".bytes"){ 13 | _relPath = relPath; 14 | _postfix = postfix; 15 | } 16 | 17 | public static T GetTableInfo(string tableName) where T : ITableInfo, new(){ 18 | T tableInfo; 19 | if (_tableInfoDic.ContainsKey(tableName)) { 20 | tableInfo = (T) _tableInfoDic[tableName]; 21 | } 22 | else { 23 | tableInfo = new T(); 24 | byte[] bytes = GetBytes(tableName); 25 | if (bytes == null) { 26 | return default(T); 27 | } 28 | tableInfo.Init(tableName, bytes); 29 | _tableInfoDic.Add(tableName, tableInfo); 30 | } 31 | 32 | return tableInfo; 33 | } 34 | 35 | private static byte[] GetBytes(string tableName){ 36 | return File.ReadAllBytes(_relPath + tableName + _postfix); 37 | } 38 | 39 | public static void UnLoadData(string tableName){ 40 | if (_tableInfoDic.ContainsKey(tableName)) { 41 | _tableInfoDic[tableName].UnLoad(); 42 | _tableInfoDic.Remove(tableName); 43 | } 44 | } 45 | 46 | public static void UnLoadALlTable(){ 47 | foreach (var key in _tableInfoDic.Keys) { 48 | UnLoadData(key); 49 | } 50 | _tableInfoDic.Clear(); 51 | } 52 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/TableReader/TableRowInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Serialization; 4 | 5 | public struct TableRowInfo { 6 | public ushort len; 7 | public int offset; 8 | 9 | public TableRowInfo(ushort len, int offset){ 10 | this.len = len; 11 | this.offset = offset; 12 | } 13 | } 14 | 15 | 16 | public interface ITableInfo { 17 | void Init(string name, byte[] bytes); 18 | void UnLoad(); 19 | } 20 | 21 | 22 | public interface ITableData { 23 | string Name(); 24 | void ParseData(Deserializer reader, int offset, ushort len); 25 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/CodeGenUtil.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | 5 | namespace Lockstep.Util { 6 | public class CodeGenUtil { 7 | private const string CodeGenPrefix = @" 8 | //------------------------------------------------------------------------------ 9 | // 10 | // This code was generated by #TOOL_NAME. 11 | // https://github.com/JiepengTan/LockstepEngine 12 | // Changes to this file may cause incorrect behavior and will be lost if 13 | // the code is regenerated. 14 | // 15 | //------------------------------------------------------------------------------ 16 | "; 17 | 18 | private const string CodeGenPrefixToolNameTag = "#TOOL_NAME"; 19 | 20 | public static string GetCodeGenPrefix(Type toolType){ 21 | return CodeGenPrefix.Replace(CodeGenPrefixToolNameTag, toolType.Assembly.FullName); 22 | 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/ECS.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | 5 | namespace Lockstep { 6 | public partial interface INeedBackup { } 7 | 8 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, 9 | Inherited = true)] 10 | public class NoBackupAttribute : Attribute { } 11 | 12 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, 13 | Inherited = true)] 14 | public class BackupAttribute : Attribute { } 15 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, 16 | Inherited = true)] 17 | public class ReRefBackupAttribute : Attribute { } 18 | } 19 | namespace Lockstep { 20 | public partial interface IBaseEntity:INeedBackup {} 21 | public partial interface IBaseContexts { } 22 | public partial interface IBaseComponent :INeedBackup{ } 23 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/JsonUtil.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using LitJson; 4 | namespace Lockstep.Util { 5 | public static class JsonUtil { 6 | public static string ToJson(object obj){ 7 | return JsonMapper.ToJson(obj); 8 | } 9 | 10 | public static T ToObject(string txt){ 11 | return JsonMapper.ToObject(txt); 12 | } 13 | } 14 | 15 | public static class JsonExtension { 16 | public static string ToJson(this object obj){ 17 | return obj == null ? "null" : JsonMapper.ToJson(obj); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/LTime.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections; 5 | 6 | namespace Lockstep.Util { 7 | public partial class Random { 8 | public ulong randSeed = 1; 9 | public Random(uint seed = 17){ 10 | randSeed = seed; 11 | } 12 | 13 | public uint Next(){ 14 | randSeed = randSeed * 1103515245 + 36153; 15 | return (uint) (randSeed / 65536); 16 | } 17 | // range:[0 ~(max-1)] 18 | public uint Next(uint max){ 19 | return Next() % max; 20 | } 21 | public int Next(int max){ 22 | return (int) (Next() % max); 23 | } 24 | // range:[min~(max-1)] 25 | public uint Range(uint min, uint max){ 26 | if (min > max) 27 | throw new ArgumentOutOfRangeException("minValue", 28 | string.Format("'{0}' cannot be greater than {1}.", min, max)); 29 | 30 | uint num = max - min; 31 | return this.Next(num) + min; 32 | } 33 | public int Range(int min, int max){ 34 | if (min >= max - 1) 35 | return min; 36 | int num = max - min; 37 | 38 | return this.Next(num) + min; 39 | } 40 | 41 | 42 | } 43 | public class LRandom { 44 | private static Random _i = new Random(3274); 45 | 46 | public static void SetSeed(uint seed){ 47 | _i = new Random(seed); 48 | } 49 | public static uint Next(){return _i.Next();} 50 | public static uint Next(uint max){return _i.Next(max);} 51 | public static int Next(int max){return _i.Next(max);} 52 | public static uint Range(uint min, uint max){return _i.Range(min, max);} 53 | public static int Range(int min, int max){return _i.Range(min, max);} 54 | } 55 | 56 | 57 | public class LTime { 58 | /// The total number of frames that have passed (Read Only). 59 | public static int frameCount { get; private set; } 60 | 61 | /// The time in seconds it took to complete the last frame (Read Only). 62 | public static float deltaTime { get; private set; } 63 | 64 | /// The time this frame has started (Read Only). This is the time in seconds since the last level has been loaded. 65 | public static float timeSinceLevelLoad { get; private set; } 66 | 67 | /// The real time in seconds since the game started (Read Only). 68 | public static float realtimeSinceStartup => (float) (DateTime.Now - _initTime).TotalSeconds; 69 | public static long realtimeSinceStartupMS => (long)(DateTime.Now - _initTime).TotalMilliseconds; 70 | 71 | private static DateTime _initTime; 72 | private static DateTime lastFrameTime; 73 | 74 | public static void DoStart(){ 75 | _initTime = DateTime.Now; 76 | } 77 | 78 | public static void DoUpdate(){ 79 | var now = DateTime.Now; 80 | deltaTime = (float) ((now - lastFrameTime).TotalSeconds); 81 | timeSinceLevelLoad = (float) ((now - _initTime).TotalSeconds); 82 | frameCount++; 83 | lastFrameTime = now; 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/LTimer.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using Lockstep.Logging; 7 | using Lockstep.Util; 8 | 9 | 10 | namespace Lockstep.Util { 11 | public static class LTimer { 12 | public delegate void DoneHandler(bool isSuccessful); 13 | /// Event, which is invoked every second 14 | public static event Action OnTickPerSeconds; 15 | public static long CurrentTick { get; private set; } 16 | 17 | private static List _mainThreadActions; 18 | private static readonly object _mainThreadLock = new object(); 19 | 20 | public static void DoStart(){ 21 | _mainThreadActions = new List(); 22 | CoroutineHelper.StartCoroutine(StartTicker()); 23 | } 24 | 25 | public static void DoUpdate(){ 26 | if (_mainThreadActions.Count > 0) { 27 | lock (_mainThreadLock) { 28 | foreach (var actions in _mainThreadActions) { 29 | actions.Invoke(); 30 | } 31 | 32 | _mainThreadActions.Clear(); 33 | } 34 | } 35 | } 36 | 37 | /// 38 | /// Waits while condition is false 39 | /// If timed out, callback will be invoked with false 40 | /// 41 | public static void WaitUntil(Func condiction, DoneHandler doneCallback, float timeoutSeconds){ 42 | CoroutineHelper.StartCoroutine(WaitWhileTrueCoroutine(condiction, doneCallback, timeoutSeconds, true)); 43 | } 44 | 45 | /// 46 | /// Waits while condition is true 47 | /// If timed out, callback will be invoked with false 48 | /// 49 | public static void WaitWhile(Func condiction, DoneHandler doneCallback, float timeoutSeconds){ 50 | CoroutineHelper.StartCoroutine(WaitWhileTrueCoroutine(condiction, doneCallback, timeoutSeconds)); 51 | } 52 | 53 | private static IEnumerator WaitWhileTrueCoroutine(Func condition, DoneHandler callback, 54 | float timeoutSeconds, bool reverseCondition = false){ 55 | while ((timeoutSeconds > 0) && (condition.Invoke() == !reverseCondition)) { 56 | timeoutSeconds -= LTime.deltaTime; 57 | yield return null; 58 | } 59 | 60 | callback.Invoke(timeoutSeconds > 0); 61 | } 62 | 63 | public static void AfterSeconds(float time, Action callback){ 64 | CoroutineHelper.StartCoroutine(StartWaitingSeconds(time, callback)); 65 | } 66 | 67 | public static void ExecuteOnMainThread(Action action){ 68 | OnMainThread(action); 69 | } 70 | 71 | public static void OnMainThread(Action action){ 72 | lock (_mainThreadLock) { 73 | _mainThreadActions.Add(action); 74 | } 75 | } 76 | 77 | private static IEnumerator StartWaitingSeconds(float time, Action callback){ 78 | yield return new WaitForSeconds(time); 79 | callback.Invoke(); 80 | } 81 | 82 | private static IEnumerator StartTicker(){ 83 | CurrentTick = 0; 84 | while (true) { 85 | yield return new WaitForSeconds(1); 86 | CurrentTick++; 87 | try { 88 | if (OnTickPerSeconds != null) 89 | OnTickPerSeconds.Invoke(CurrentTick); 90 | } 91 | catch (Exception e) { 92 | Debug.LogError(e); 93 | } 94 | } 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/LitJson/IJsonWrapper.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | #region Header 4 | /** 5 | * IJsonWrapper.cs 6 | * Interface that represents a type capable of handling all kinds of JSON 7 | * data. This is mainly used when mapping objects through JsonMapper, and 8 | * it's implemented by JsonData. 9 | * 10 | * The authors disclaim copyright to this source code. For more details, see 11 | * the COPYING file included with this distribution. 12 | **/ 13 | #endregion 14 | 15 | 16 | using System.Collections; 17 | using System.Collections.Specialized; 18 | 19 | 20 | namespace LitJson 21 | { 22 | public enum JsonType 23 | { 24 | None, 25 | 26 | Object, 27 | Array, 28 | String, 29 | Int, 30 | Long, 31 | Double, 32 | Boolean 33 | } 34 | 35 | public interface IJsonWrapper : IList, IOrderedDictionary 36 | { 37 | bool IsArray { get; } 38 | bool IsBoolean { get; } 39 | bool IsDouble { get; } 40 | bool IsInt { get; } 41 | bool IsLong { get; } 42 | bool IsObject { get; } 43 | bool IsString { get; } 44 | 45 | bool GetBoolean (); 46 | double GetDouble (); 47 | int GetInt (); 48 | JsonType GetJsonType (); 49 | long GetLong (); 50 | string GetString (); 51 | 52 | void SetBoolean (bool val); 53 | void SetDouble (double val); 54 | void SetInt (int val); 55 | void SetJsonType (JsonType type); 56 | void SetLong (long val); 57 | void SetString (string val); 58 | 59 | string ToJson (); 60 | void ToJson (JsonWriter writer); 61 | } 62 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/LitJson/JsonException.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | #region Header 4 | /** 5 | * JsonException.cs 6 | * Base class throwed by LitJSON when a parsing error occurs. 7 | * 8 | * The authors disclaim copyright to this source code. For more details, see 9 | * the COPYING file included with this distribution. 10 | **/ 11 | #endregion 12 | 13 | 14 | using System; 15 | 16 | 17 | namespace LitJson 18 | { 19 | public class JsonException : 20 | #if NETSTANDARD1_5 21 | Exception 22 | #else 23 | ApplicationException 24 | #endif 25 | { 26 | public JsonException () : base () 27 | { 28 | } 29 | 30 | internal JsonException (ParserToken token) : 31 | base (String.Format ( 32 | "Invalid token '{0}' in input string", token)) 33 | { 34 | } 35 | 36 | internal JsonException (ParserToken token, 37 | Exception inner_exception) : 38 | base (String.Format ( 39 | "Invalid token '{0}' in input string", token), 40 | inner_exception) 41 | { 42 | } 43 | 44 | internal JsonException (int c) : 45 | base (String.Format ( 46 | "Invalid character '{0}' in input string", (char) c)) 47 | { 48 | } 49 | 50 | internal JsonException (int c, Exception inner_exception) : 51 | base (String.Format ( 52 | "Invalid character '{0}' in input string", (char) c), 53 | inner_exception) 54 | { 55 | } 56 | 57 | 58 | public JsonException (string message) : base (message) 59 | { 60 | } 61 | 62 | public JsonException (string message, Exception inner_exception) : 63 | base (message, inner_exception) 64 | { 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/LitJson/Netstandard15Polyfill.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | #if NETSTANDARD1_5 4 | using System; 5 | using System.Reflection; 6 | namespace LitJson 7 | { 8 | internal static class Netstandard15Polyfill 9 | { 10 | internal static Type GetInterface(this Type type, string name) 11 | { 12 | return type.GetTypeInfo().GetInterface(name); 13 | } 14 | 15 | internal static bool IsClass(this Type type) 16 | { 17 | return type.GetTypeInfo().IsClass; 18 | } 19 | 20 | internal static bool IsEnum(this Type type) 21 | { 22 | return type.GetTypeInfo().IsEnum; 23 | } 24 | } 25 | } 26 | #endif -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/LitJson/ParserToken.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | #region Header 4 | /** 5 | * ParserToken.cs 6 | * Internal representation of the tokens used by the lexer and the parser. 7 | * 8 | * The authors disclaim copyright to this source code. For more details, see 9 | * the COPYING file included with this distribution. 10 | **/ 11 | #endregion 12 | 13 | 14 | namespace LitJson 15 | { 16 | internal enum ParserToken 17 | { 18 | // Lexer tokens (see section A.1.1. of the manual) 19 | None = System.Char.MaxValue + 1, 20 | Number, 21 | True, 22 | False, 23 | Null, 24 | CharSeq, 25 | // Single char 26 | Char, 27 | 28 | // Parser Rules (see section A.2.1 of the manual) 29 | Text, 30 | Object, 31 | ObjectPrime, 32 | Pair, 33 | PairRest, 34 | Array, 35 | ArrayPrime, 36 | Value, 37 | ValueRest, 38 | String, 39 | 40 | // End of input 41 | End, 42 | 43 | // The empty rule 44 | Epsilon 45 | } 46 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/NativeUtil/Buffer.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | 7 | namespace Lockstep.Util { 8 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/NativeUtil/NativeHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | 8 | namespace Lockstep.Util { 9 | public unsafe class NativeHelper { 10 | public const int STRUCT_PACK = 4; 11 | 12 | #if DEBUG 13 | public static HashSet _allocedPtrs = new HashSet(); 14 | public static Dictionary _prt2Size = new Dictionary(); 15 | public static long MemSize => _prt2Size.Sum((d) => d.Value); 16 | #endif 17 | public static void Free(IntPtr ptr){ 18 | Free(ptr.ToPointer()); 19 | } 20 | public static void Free(void* ptr){ 21 | #if DEBUG 22 | if (!_allocedPtrs.Contains((long) ptr)) { 23 | throw new NullReferenceException("Try to free a block which did not allocated!"); 24 | } 25 | _prt2Size.Remove((long) ptr); 26 | #endif 27 | 28 | if (ptr == null) throw new NullReferenceException(); 29 | Marshal.FreeHGlobal((IntPtr)ptr); 30 | } 31 | 32 | public static IntPtr Alloc(int size){ 33 | var ptr = Marshal.AllocHGlobal(size); 34 | #if DEBUG 35 | _allocedPtrs.Add((long) ptr); 36 | _prt2Size.Add((long) ptr, size); 37 | #endif 38 | return ptr; 39 | } 40 | 41 | public static void* Resize(void* src, int srcSize, int dstSize){ 42 | var newAry = AllocAndZero(dstSize); 43 | Copy(newAry, src, srcSize); 44 | Free(new IntPtr(src)); 45 | return newAry; 46 | } 47 | 48 | public static unsafe void Zero(void* ptr, int size){ 49 | Zero((byte*) ptr, size); 50 | } 51 | 52 | public static unsafe void Zero(byte* ptr, int size){ 53 | for (; size >= 4; size -= 4) { 54 | *(int*) ptr = 0; 55 | ptr += 4; 56 | } 57 | 58 | for (; size > 0; --size) { 59 | *ptr = 0; 60 | } 61 | } 62 | 63 | public static unsafe void Copy(void* dest, void* src, int size){ 64 | Copy((byte*) dest, (byte*) src, size); 65 | } 66 | 67 | public static unsafe void Copy(byte* dest, byte* src, int size){ 68 | for (; size >= 4; size -= 4) { 69 | *(int*) dest = *(int*) src; 70 | dest += 4; 71 | src += 4; 72 | } 73 | 74 | for (; size > 0; --size) { 75 | *dest = *src; 76 | ++dest; 77 | ++src; 78 | } 79 | } 80 | 81 | public static byte* AllocAndZero(int size){ 82 | var ptr = (byte*) (Alloc(size).ToPointer()); 83 | Zero(ptr, size); 84 | return ptr; 85 | } 86 | 87 | public static void NullPointer(){ 88 | throw new NullReferenceException("Method invoked on null pointer."); 89 | } 90 | 91 | public static void ArrayOutOfRange(){ 92 | throw new ArgumentOutOfRangeException("Array index out of range"); 93 | } 94 | 95 | private class BufferSizeMissMatchException : Exception { 96 | public BufferSizeMissMatchException(string info) : base("Buffer Size miss match!! " + info){ } 97 | } 98 | 99 | public static void BufferSizeMissMatch(string info = ""){ 100 | throw new BufferSizeMissMatchException(info); 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/NativeUtil/NativePool.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace Lockstep.Util { 8 | public unsafe class NativeFactory { 9 | static Dictionary pools = new Dictionary(); 10 | 11 | public static long MemSize => pools.Sum((a) => a.Value.MemSize); 12 | 13 | public static NativePool GetPool(int size,bool isAutoPtr = true){ 14 | if (pools.TryGetValue(size, out var pool)) { 15 | return pool; 16 | } 17 | 18 | var tPool = new NativePool(size,isAutoPtr); 19 | pools[size] = tPool; 20 | return tPool; 21 | } 22 | 23 | public static void Clear(){ 24 | foreach (var pair in pools) { 25 | pair.Value.Clear(); 26 | } 27 | } 28 | } 29 | 30 | public unsafe class NativePool { 31 | private List _autoRefPtrs = new List(); 32 | private bool _isAutoPtr; 33 | private Stack _allPtrs = new Stack(); 34 | private int _typeSize = -1; 35 | public int MemSize => _typeSize * _allPtrs.Count; 36 | 37 | 38 | public NativePool(int typeSize, bool isAutoPtr = true){ 39 | this._typeSize = typeSize; 40 | this._isAutoPtr = isAutoPtr; 41 | if (isAutoPtr) { 42 | _autoRefPtrs = new List(); 43 | } 44 | } 45 | 46 | public void Return(void* ptr){ 47 | if (ptr == null) NativeHelper.NullPointer(); 48 | _allPtrs.Push((long) ptr); 49 | } 50 | 51 | public void* Get(){ 52 | if (_allPtrs.Count == 0) return null; 53 | var ptr = (byte*) _allPtrs.Pop(); 54 | NativeHelper.Zero(ptr, _typeSize); 55 | return ptr; 56 | } 57 | 58 | public void* ForceGet(){ 59 | var ptr = Get(); 60 | if (ptr == null) { 61 | ptr = NativeHelper.AllocAndZero(_typeSize); 62 | if (_isAutoPtr) { 63 | _autoRefPtrs.Add((long) ptr); 64 | } 65 | } 66 | 67 | return ptr; 68 | } 69 | 70 | public void Clear(){ 71 | if (_isAutoPtr) { 72 | foreach (var ptr in _autoRefPtrs) { 73 | NativeHelper.Free((IntPtr) ptr); 74 | } 75 | _autoRefPtrs.Clear(); 76 | _allPtrs.Clear(); 77 | } 78 | else { 79 | while (_allPtrs.Count > 0) { 80 | var ptr = _allPtrs.Pop(); 81 | NativeHelper.Free((IntPtr) ptr); 82 | } 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/NetworkHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Net; 5 | using System.Net.Sockets; 6 | 7 | namespace Lockstep.Util { 8 | public class NetworkHelper { 9 | public static string GetLocalIP(){ 10 | try { 11 | string HostName = Dns.GetHostName(); //得到主机名 12 | IPHostEntry IpEntry = Dns.GetHostEntry(HostName); 13 | for (int i = 0; i < IpEntry.AddressList.Length; i++) { 14 | //从IP地址列表中筛选出IPv4类型的IP地址 15 | //AddressFamily.InterNetwork表示此IP为IPv4, 16 | //AddressFamily.InterNetworkV6表示此地址为IPv6类型 17 | if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork) { 18 | return IpEntry.AddressList[i].ToString(); 19 | } 20 | } 21 | 22 | return ""; 23 | } 24 | catch (Exception ex) { 25 | return ex.Message; 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/PathUtil.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.IO; 5 | using System.Linq; 6 | namespace Lockstep.Util { 7 | 8 | public static partial class PathUtil { 9 | // 遍历所选目录或文件,递归 10 | public static void Walk(string path, string exts, System.Action callback, bool _is_save_assets = false, 11 | bool _is_all_directories = true){ 12 | bool isAll = string.IsNullOrEmpty(exts) || exts == "*" || exts == "*.*"; 13 | string[] extList = exts.Replace("*", "").Split('|'); 14 | 15 | if (Directory.Exists(path)) { 16 | // 如果选择的是文件夹 17 | SearchOption searchOption = 18 | _is_all_directories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; 19 | string[] files = Directory.GetFiles(path, "*.*", searchOption).Where(file => { 20 | if (isAll) 21 | return true; 22 | foreach (var ext in extList) { 23 | if (file.EndsWith(ext, StringComparison.OrdinalIgnoreCase)) { 24 | return true; 25 | } 26 | } 27 | 28 | return false; 29 | }).ToArray(); 30 | 31 | foreach (var item in files) { 32 | if (callback != null) { 33 | callback(item); 34 | } 35 | } 36 | 37 | if (_is_save_assets) { 38 | } 39 | } 40 | else { 41 | if (isAll) { 42 | if (callback != null) { 43 | callback(path); 44 | } 45 | } 46 | else { 47 | // 如果选择的是文件 48 | foreach (var ext in extList) { 49 | if (path.EndsWith(ext, StringComparison.OrdinalIgnoreCase)) { 50 | if (callback != null) { 51 | callback(path); 52 | } 53 | } 54 | } 55 | } 56 | 57 | if (_is_save_assets) { 58 | } 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/Pool.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | namespace Lockstep.Util { 6 | public interface IRecyclable { 7 | void OnReuse(); 8 | void OnRecycle(); 9 | } 10 | 11 | public class BaseRecyclable : IRecyclable { 12 | public virtual void OnReuse(){ } 13 | public virtual void OnRecycle(){ } 14 | public override string ToString(){ 15 | return JsonUtil.ToJson(this); 16 | } 17 | } 18 | 19 | public class Pool { 20 | public static void Return(T val) where T : IRecyclable, new(){ 21 | Pool.Return(val); 22 | } 23 | 24 | public static T Get() where T : IRecyclable, new(){ 25 | return Pool.Get(); 26 | } 27 | } 28 | 29 | public class Pool where T : IRecyclable, new() { 30 | private static Stack pool = new Stack(); 31 | 32 | 33 | public static T Get(){ 34 | if (pool.Count == 0) { 35 | return new T(); 36 | } 37 | else { 38 | return pool.Pop(); 39 | } 40 | } 41 | 42 | public static void Return(T val){ 43 | if (val == null) return; 44 | val.OnRecycle(); 45 | pool.Push(val); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/Profiler.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.Diagnostics; 4 | #if UNITY_5_3_OR_NEWER 5 | using UnityEngine.Profiling; 6 | #endif 7 | namespace Lockstep.Util { 8 | public class Profiler { 9 | [Conditional("DEBUG")] 10 | public static void BeginSample(object obj){ 11 | #if UNITY_5_3_OR_NEWER 12 | UnityEngine.Profiling.Profiler.BeginSample(obj.GetType().Name); 13 | #endif 14 | } 15 | 16 | [Conditional("DEBUG")] 17 | public static void EndSample(object obj){ 18 | #if UNITY_5_3_OR_NEWER 19 | UnityEngine.Profiling.Profiler.EndSample(); 20 | #endif 21 | } 22 | 23 | [Conditional("DEBUG")] 24 | public static void BeginSample(string tag){ 25 | #if UNITY_5_3_OR_NEWER 26 | UnityEngine.Profiling.Profiler.BeginSample(tag); 27 | #endif 28 | } 29 | 30 | [Conditional("DEBUG")] 31 | public static void EndSample(){ 32 | #if UNITY_5_3_OR_NEWER 33 | UnityEngine.Profiling.Profiler.EndSample(); 34 | #endif 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /Engine.LockstepEngine/Src/Util/Src/Util.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System.IO; 4 | using Lockstep.Logging; 5 | 6 | namespace Lockstep.Util { 7 | public class Utils { 8 | public static void StartServices(){ 9 | LTime.DoStart(); 10 | CoroutineHelper.DoStart(); 11 | } 12 | 13 | public static void UpdateServices(){ 14 | LTime.DoUpdate(); 15 | CoroutineHelper.DoUpdate(); 16 | } 17 | 18 | public static void ExecuteCmd(string shellName, string workingDir){ 19 | System.Diagnostics.Process process = new System.Diagnostics.Process(); 20 | process.StartInfo.CreateNoWindow = false; 21 | process.StartInfo.ErrorDialog = true; 22 | process.StartInfo.UseShellExecute = false; 23 | process.StartInfo.FileName = "/bin/bash"; 24 | process.StartInfo.Arguments = shellName; 25 | process.StartInfo.RedirectStandardOutput = true; 26 | process.StartInfo.RedirectStandardInput = true; 27 | process.StartInfo.WorkingDirectory = workingDir; 28 | process.Start(); 29 | Debug.Log($"ExeCmd {process.StartInfo.FileName} {shellName} ##workingDir={process.StartInfo.WorkingDirectory} "); 30 | string output = process.StandardOutput.ReadToEnd(); 31 | process.WaitForExit(); 32 | process.Close(); 33 | Debug.Log(output); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Engine.View/Engine.View.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Engine.View", 3 | "references": [ 4 | "Engine.LockstepEngine" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /Engine.View/Src/Collision2D/ColliderDataMono.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | #if UNITY_5_3_OR_NEWER 4 | 5 | #endif 6 | 7 | namespace Lockstep.Collision2D { 8 | #if UNITY_5_3_OR_NEWER 9 | public class ColliderDataMono : UnityEngine.MonoBehaviour { 10 | public ColliderData colliderData; 11 | } 12 | #endif 13 | } -------------------------------------------------------------------------------- /Engine.View/Src/NavMesh/LVectorExtension.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using Lockstep.Math; 4 | using UnityEngine; 5 | 6 | 7 | public static class LVectorExtension { 8 | public static Vector3[] ToVecArray(this LVector3[] lVecs){ 9 | var vecs = new Vector3[lVecs.Length]; 10 | for (int i = 0; i < lVecs.Length; i++) { 11 | vecs[i] = lVecs[i].ToVector3(); 12 | } 13 | return vecs; 14 | } 15 | public static LVector3[] ToLVecArray(this Vector3[] lVecs){ 16 | var vecs = new LVector3[lVecs.Length]; 17 | for (int i = 0; i < lVecs.Length; i++) { 18 | vecs[i] = lVecs[i].ToLVector3(); 19 | } 20 | return vecs; 21 | } 22 | } -------------------------------------------------------------------------------- /Engine.View/Src/NavMesh/NavMeshTool.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | using System; 4 | using UnityEngine; 5 | using System.Collections; 6 | using Lockstep.PathFinding; 7 | 8 | [Serializable] 9 | public class NavMeshTool : MonoBehaviour { 10 | public int mapId; 11 | public GameObject mapRoot; 12 | public TriangleData data = new TriangleData(); 13 | } -------------------------------------------------------------------------------- /Engine.View/Src/UnityLogHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 谭杰鹏. All Rights Reserved //https://github.com/JiepengTan 2 | 3 | 4 | using Lockstep.Logging; 5 | 6 | namespace Lockstep.Game { 7 | public class UnityLogHandler { 8 | public static void OnLog(object sender, LogEventArgs args){ 9 | switch (args.LogSeverity) { 10 | case LogSeverity.Info: 11 | UnityEngine.Debug.Log(args.Message); 12 | break; 13 | case LogSeverity.Warn: 14 | UnityEngine.Debug.LogWarning(args.Message); 15 | break; 16 | case LogSeverity.Error: 17 | UnityEngine.Debug.LogError(args.Message); 18 | break; 19 | case LogSeverity.Exception: 20 | UnityEngine.Debug.LogError(args.Message); 21 | break; 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LockstepEngine 2 | 3 | #### **Tutorial** 4 | 5 | - [Tutorial Project ][20][https://github.com/JiepengTan/Lockstep-Tutorial][20] 6 | - [Tutorial Video (Chinese)][21] 7 | 8 | #### **References:** 9 | - ECS prototype UnityLockstep:[https://github.com/proepkes/UnityLockstep][1] 10 | - Network library: LiteNetLib: [https://github.com/RevenantX/LiteNetLib][2] (v0.8.3 .NetCore) 11 | - ECS Framework Entitas: [https://github.com/sschmid/Entitas-CSharp][3] (v1.13.0) 12 | - Deterministic Math library : [https://github.com/JiepengTan/LockstepMath][4] 13 | - Deterministic Collision library: [https://github.com/JiepengTan/LockstepCollision][5] 14 | - Deterministic NavMesh library: [https://github.com/JiepengTan/LockstepPathFinding][8] 15 | - Fast and Memory friendly BehaviourTree library: [https://github.com/JiepengTan/LockstepBehaviorTree][9] 16 | - CodeGenerator ME : [https://github.com/JiepengTan/ME][10] 17 | - new NetworkLib is Comefrom ET 3.0 [https://github.com/egametang/ET][16] 18 | - Libs all_in_one [https://github.com/JiepengTan/LockstepEngine][11] 19 | 20 | Setup Video link: [https://www.bilibili.com/video/av64460304/][15] 21 | 22 | 23 | [1]: https://github.com/proepkes/UnityLockstep 24 | [2]: https://github.com/RevenantX/LiteNetLib 25 | [3]: https://github.com/sschmid/Entitas-CSharp 26 | [4]: https://github.com/JiepengTan/LockstepMath 27 | [5]: https://github.com/JiepengTan/LockstepCollision 28 | [6]: https://github.com/JiepengTan/LockstepPlatform/releases 29 | [7]: https://github.com/sschmid/Entitas-CSharp/releases 30 | [8]: https://github.com/JiepengTan/LockstepPathFinding 31 | [9]: https://github.com/JiepengTan/LockstepBehaviorTree 32 | [10]: https://github.com/JiepengTan/ME 33 | [11]: https://github.com/JiepengTan/LockstepEngine 34 | [12]: https://www.bilibili.com/video/av55450233 35 | [13]: https://github.com/JiepengTan/LockstepEngine_ARPGDemo/releases/tag/v0.1.0 36 | [14]: https://github.com/JiepengTan/Lockstep_Demo2D_Tank 37 | [15]: https://www.bilibili.com/video/av58401872/ 38 | [16]: https://github.com/egametang/ET 39 | [17]: https://github.com/JiepengTan/LockstepEngine_ARPGDemo 40 | [18]: https://github.com/JiepengTan/LockstepEngine_ARPGDemo 41 | [19]: https://github.com/JiepengTan/LockstepEngine_ARPGDemo 42 | [20]: https://github.com/JiepengTan/Lockstep-Tutorial 43 | [21]: https://www.bilibili.com/video/av70422751/ 44 | [22]: https://github.com/JiepengTan/LockstepPlatform 45 | -------------------------------------------------------------------------------- /Test.Unity/.gitignore: -------------------------------------------------------------------------------- 1 | [Ll]ibrary/ 2 | [Tt]emp/ 3 | [Oo]bj/ 4 | [Ll]og/ 5 | [Ll]ogs/ 6 | [Bb]uild/ 7 | [Bb]uilds/ 8 | CoreEditor/ 9 | __ECSOutput/ 10 | Assets/* 11 | Assets/AssetStoreTools* 12 | [Aa]ssets/StreamingAssets/ 13 | [Aa]ssets/TempRes 14 | [Aa]ssets/Plugins/Editor/JetBrains/ 15 | [Aa]ssets/Plugins/Game/ 16 | [Aa]ssets/Plugins/Entitas/ 17 | [Aa]ssets/Plugins/LockstepEngine/ 18 | .idea/ 19 | #不要重复提交相同的Dlls 20 | # Visual Studio cache directory 21 | .vs/ 22 | # Autogenerated VS/MD/Consulo solution and project files 23 | ExportedObj/ 24 | .consulo/ 25 | *.csproj 26 | *.unityproj 27 | *.sln 28 | *.suo 29 | *.tmp 30 | *.user 31 | *.userprefs 32 | *.pidb 33 | *.booproj 34 | *.svd 35 | *.pdb 36 | *.opendb 37 | 38 | # Unity3D generated meta files 39 | *.pidb.meta 40 | *.pdb.meta 41 | 42 | # Unity3D Generated File On Crash Reports 43 | sysinfo.txt 44 | 45 | # Builds 46 | *.apk 47 | *.unitypackage 48 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!11 &1 4 | AudioManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Volume: 1 8 | Rolloff Scale: 1 9 | Doppler Factor: 1 10 | Default Speaker Mode: 2 11 | m_SampleRate: 0 12 | m_DSPBufferSize: 1024 13 | m_VirtualVoiceCount: 512 14 | m_RealVoiceCount: 32 15 | m_SpatializerPlugin: 16 | m_AmbisonicDecoderPlugin: 17 | m_DisableAudio: 0 18 | m_VirtualizeEffects: 1 19 | m_RequestedDSPBufferSize: 0 20 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!236 &1 4 | ClusterInputManager: 5 | m_ObjectHideFlags: 0 6 | m_Inputs: [] 7 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!55 &1 4 | PhysicsManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 13 7 | m_Gravity: {x: 0, y: -9.81, z: 0} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_BounceThreshold: 2 10 | m_SleepThreshold: 0.005 11 | m_DefaultContactOffset: 0.01 12 | m_DefaultSolverIterations: 6 13 | m_DefaultSolverVelocityIterations: 1 14 | m_QueriesHitBackfaces: 0 15 | m_QueriesHitTriggers: 1 16 | m_EnableAdaptiveForce: 0 17 | m_ClothInterCollisionDistance: 0.1 18 | m_ClothInterCollisionStiffness: 0.2 19 | m_ContactsGeneration: 1 20 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 21 | m_AutoSimulation: 1 22 | m_AutoSyncTransforms: 0 23 | m_ReuseCollisionCallbacks: 0 24 | m_ClothInterCollisionSettingsToggle: 0 25 | m_ClothGravity: {x: 0, y: -9.81, z: 0} 26 | m_ContactPairsMode: 0 27 | m_BroadphaseType: 0 28 | m_WorldBounds: 29 | m_Center: {x: 0, y: 0, z: 0} 30 | m_Extent: {x: 250, y: 250, z: 250} 31 | m_WorldSubdivisions: 8 32 | m_FrictionType: 0 33 | m_EnableEnhancedDeterminism: 0 34 | m_EnableUnifiedHeightmaps: 1 35 | m_DefaultMaxAngularSpeed: 50 36 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1045 &1 4 | EditorBuildSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Scenes: [] 8 | m_configObjects: {} 9 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 8 7 | m_ExternalVersionControlSupport: Hidden Meta Files 8 | m_SerializationMode: 2 9 | m_LineEndingsForNewScripts: 1 10 | m_DefaultBehaviorMode: 0 11 | m_PrefabRegularEnvironment: {fileID: 0} 12 | m_PrefabUIEnvironment: {fileID: 0} 13 | m_SpritePackerMode: 0 14 | m_SpritePackerPaddingPower: 1 15 | m_EtcTextureCompressorBehavior: 1 16 | m_EtcTextureFastCompressor: 1 17 | m_EtcTextureNormalCompressor: 2 18 | m_EtcTextureBestCompressor: 4 19 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;asmref;rsp 20 | m_ProjectGenerationRootNamespace: 21 | m_CollabEditorSettings: 22 | inProgressEnabled: 1 23 | m_EnableTextureStreamingInEditMode: 1 24 | m_EnableTextureStreamingInPlayMode: 1 25 | m_AsyncShaderCompilation: 1 26 | m_ShowLightmapResolutionOverlay: 1 27 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!30 &1 4 | GraphicsSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 12 7 | m_Deferred: 8 | m_Mode: 1 9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} 10 | m_DeferredReflections: 11 | m_Mode: 1 12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} 13 | m_ScreenSpaceShadows: 14 | m_Mode: 1 15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} 16 | m_LegacyDeferred: 17 | m_Mode: 1 18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} 19 | m_DepthNormals: 20 | m_Mode: 1 21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} 22 | m_MotionVectors: 23 | m_Mode: 1 24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} 25 | m_LightHalo: 26 | m_Mode: 1 27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} 28 | m_LensFlare: 29 | m_Mode: 1 30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} 31 | m_AlwaysIncludedShaders: 32 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} 33 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} 34 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} 35 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} 36 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} 37 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} 38 | - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} 39 | m_PreloadedShaders: [] 40 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, 41 | type: 0} 42 | m_CustomRenderPipeline: {fileID: 0} 43 | m_TransparencySortMode: 0 44 | m_TransparencySortAxis: {x: 0, y: 0, z: 1} 45 | m_DefaultRenderingPath: 1 46 | m_DefaultMobileRenderingPath: 1 47 | m_TierSettings: [] 48 | m_LightmapStripping: 0 49 | m_FogStripping: 0 50 | m_InstancingStripping: 0 51 | m_LightmapKeepPlain: 1 52 | m_LightmapKeepDirCombined: 1 53 | m_LightmapKeepDynamicPlain: 1 54 | m_LightmapKeepDynamicDirCombined: 1 55 | m_LightmapKeepShadowMask: 1 56 | m_LightmapKeepSubtractive: 1 57 | m_FogKeepLinear: 1 58 | m_FogKeepExp: 1 59 | m_FogKeepExp2: 1 60 | m_AlbedoSwatchInfos: [] 61 | m_LightsUseLinearIntensity: 0 62 | m_LightsUseColorTemperature: 0 63 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshProjectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | areas: 8 | - name: Walkable 9 | cost: 1 10 | - name: Not Walkable 11 | cost: 1 12 | - name: Jump 13 | cost: 2 14 | - name: 15 | cost: 1 16 | - name: 17 | cost: 1 18 | - name: 19 | cost: 1 20 | - name: 21 | cost: 1 22 | - name: 23 | cost: 1 24 | - name: 25 | cost: 1 26 | - name: 27 | cost: 1 28 | - name: 29 | cost: 1 30 | - name: 31 | cost: 1 32 | - name: 33 | cost: 1 34 | - name: 35 | cost: 1 36 | - name: 37 | cost: 1 38 | - name: 39 | cost: 1 40 | - name: 41 | cost: 1 42 | - name: 43 | cost: 1 44 | - name: 45 | cost: 1 46 | - name: 47 | cost: 1 48 | - name: 49 | cost: 1 50 | - name: 51 | cost: 1 52 | - name: 53 | cost: 1 54 | - name: 55 | cost: 1 56 | - name: 57 | cost: 1 58 | - name: 59 | cost: 1 60 | - name: 61 | cost: 1 62 | - name: 63 | cost: 1 64 | - name: 65 | cost: 1 66 | - name: 67 | cost: 1 68 | - name: 69 | cost: 1 70 | - name: 71 | cost: 1 72 | m_LastAgentTypeID: -887442657 73 | m_Settings: 74 | - serializedVersion: 2 75 | agentTypeID: 0 76 | agentRadius: 0.5 77 | agentHeight: 2 78 | agentSlope: 45 79 | agentClimb: 0.75 80 | ledgeDropHeight: 0 81 | maxJumpAcrossDistance: 0 82 | minRegionArea: 2 83 | manualCellSize: 0 84 | cellSize: 0.16666667 85 | manualTileSize: 0 86 | tileSize: 256 87 | accuratePlacement: 0 88 | debug: 89 | m_Flags: 0 90 | m_SettingNames: 91 | - Humanoid 92 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!19 &1 4 | Physics2DSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 4 7 | m_Gravity: {x: 0, y: -9.81} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_VelocityIterations: 8 10 | m_PositionIterations: 3 11 | m_VelocityThreshold: 1 12 | m_MaxLinearCorrection: 0.2 13 | m_MaxAngularCorrection: 8 14 | m_MaxTranslationSpeed: 100 15 | m_MaxRotationSpeed: 360 16 | m_BaumgarteScale: 0.2 17 | m_BaumgarteTimeOfImpactScale: 0.75 18 | m_TimeToSleep: 0.5 19 | m_LinearSleepTolerance: 0.01 20 | m_AngularSleepTolerance: 2 21 | m_DefaultContactOffset: 0.01 22 | m_JobOptions: 23 | serializedVersion: 2 24 | useMultithreading: 0 25 | useConsistencySorting: 0 26 | m_InterpolationPosesPerJob: 100 27 | m_NewContactsPerJob: 30 28 | m_CollideContactsPerJob: 100 29 | m_ClearFlagsPerJob: 200 30 | m_ClearBodyForcesPerJob: 200 31 | m_SyncDiscreteFixturesPerJob: 50 32 | m_SyncContinuousFixturesPerJob: 50 33 | m_FindNearestContactsPerJob: 100 34 | m_UpdateTriggerContactsPerJob: 100 35 | m_IslandSolverCostThreshold: 100 36 | m_IslandSolverBodyCostScale: 1 37 | m_IslandSolverContactCostScale: 10 38 | m_IslandSolverJointCostScale: 10 39 | m_IslandSolverBodiesPerJob: 50 40 | m_IslandSolverContactsPerJob: 50 41 | m_AutoSimulation: 1 42 | m_QueriesHitTriggers: 1 43 | m_QueriesStartInColliders: 1 44 | m_CallbacksOnDisable: 1 45 | m_ReuseCollisionCallbacks: 0 46 | m_AutoSyncTransforms: 0 47 | m_AlwaysShowColliders: 0 48 | m_ShowColliderSleep: 1 49 | m_ShowColliderContacts: 0 50 | m_ShowColliderAABB: 0 51 | m_ContactArrowScale: 0.2 52 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} 53 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} 54 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} 55 | m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} 56 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 57 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/PresetManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1386491679 &1 4 | PresetManager: 5 | m_ObjectHideFlags: 0 6 | m_DefaultList: [] 7 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2019.2.3f1 2 | m_EditorVersionWithRevision: 2019.2.3f1 (8e55c27a4621) 3 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!78 &1 4 | TagManager: 5 | serializedVersion: 2 6 | tags: [] 7 | layers: 8 | - Default 9 | - TransparentFX 10 | - Ignore Raycast 11 | - 12 | - Water 13 | - UI 14 | - 15 | - 16 | - 17 | - 18 | - 19 | - 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | - 27 | - 28 | - 29 | - 30 | - 31 | - 32 | - 33 | - 34 | - 35 | - 36 | - 37 | - 38 | - 39 | - 40 | m_SortingLayers: 41 | - name: Default 42 | uniqueID: 0 43 | locked: 0 44 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!5 &1 4 | TimeManager: 5 | m_ObjectHideFlags: 0 6 | Fixed Timestep: 0.02 7 | Maximum Allowed Timestep: 0.33333334 8 | m_TimeScale: 1 9 | Maximum Particle Timestep: 0.03 10 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!310 &1 4 | UnityConnectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 1 7 | m_Enabled: 0 8 | m_TestMode: 0 9 | m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events 10 | m_EventUrl: https://cdp.cloud.unity3d.com/v1/events 11 | m_ConfigUrl: https://config.uca.cloud.unity3d.com 12 | m_TestInitMode: 0 13 | CrashReportingSettings: 14 | m_EventUrl: https://perf-events.cloud.unity3d.com 15 | m_Enabled: 0 16 | m_LogBufferSize: 10 17 | m_CaptureEditorExceptions: 1 18 | UnityPurchasingSettings: 19 | m_Enabled: 0 20 | m_TestMode: 0 21 | UnityAnalyticsSettings: 22 | m_Enabled: 0 23 | m_TestMode: 0 24 | m_InitializeOnStartup: 1 25 | UnityAdsSettings: 26 | m_Enabled: 0 27 | m_InitializeOnStartup: 1 28 | m_TestMode: 0 29 | m_IosGameId: 30 | m_AndroidGameId: 31 | m_GameIds: {} 32 | m_GameId: 33 | PerformanceReportingSettings: 34 | m_Enabled: 0 35 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/VFXManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!937362698 &1 4 | VFXManager: 5 | m_ObjectHideFlags: 0 6 | m_IndirectShader: {fileID: 0} 7 | m_CopyBufferShader: {fileID: 0} 8 | m_SortShader: {fileID: 0} 9 | m_RenderPipeSettingsPath: 10 | m_FixedTimeStep: 0.016666668 11 | m_MaxDeltaTime: 0.05 12 | -------------------------------------------------------------------------------- /Test.Unity/ProjectSettings/XRSettings.asset: -------------------------------------------------------------------------------- 1 | { 2 | "m_SettingKeys": [ 3 | "VR Device Disabled", 4 | "VR Device User Alert" 5 | ], 6 | "m_SettingValues": [ 7 | "False", 8 | "False" 9 | ] 10 | } --------------------------------------------------------------------------------