diff options
Very Preliminary local teleporting added (currently only can teleport within the current region).
Now need to add teleporting between regions and use of the dynamic texture for the terrain.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/OpenSim.Region/Scenes/Avatar.Update.cs | 71 | ||||
-rw-r--r-- | OpenSim/OpenSim.Region/Scenes/Avatar.cs | 42 | ||||
-rw-r--r-- | OpenSim/OpenSim.Region/Scenes/Scene.cs | 148 | ||||
-rw-r--r-- | OpenSim/OpenSim.Region/Scenes/SceneBase.cs | 2 |
4 files changed, 180 insertions, 83 deletions
diff --git a/OpenSim/OpenSim.Region/Scenes/Avatar.Update.cs b/OpenSim/OpenSim.Region/Scenes/Avatar.Update.cs index d46bf0f..5d70bc1 100644 --- a/OpenSim/OpenSim.Region/Scenes/Avatar.Update.cs +++ b/OpenSim/OpenSim.Region/Scenes/Avatar.Update.cs | |||
@@ -43,36 +43,24 @@ namespace OpenSim.Region.Scenes | |||
43 | /// </summary> | 43 | /// </summary> |
44 | public override void update() | 44 | public override void update() |
45 | { | 45 | { |
46 | if (this.newForce) | 46 | if (this.childAvatar == false) |
47 | { | 47 | { |
48 | this.SendTerseUpdateToALLClients(); | 48 | if (this.newForce) |
49 | _updateCount = 0; | ||
50 | } | ||
51 | else if (movementflag != 0) | ||
52 | { | ||
53 | _updateCount++; | ||
54 | if (_updateCount > 3) | ||
55 | { | 49 | { |
56 | this.SendTerseUpdateToALLClients(); | 50 | this.SendTerseUpdateToALLClients(); |
57 | _updateCount = 0; | 51 | _updateCount = 0; |
58 | } | 52 | } |
59 | } | 53 | else if (movementflag != 0) |
60 | 54 | { | |
61 | LLVector3 pos2 = this.Pos; | 55 | _updateCount++; |
62 | LLVector3 vel = this.Velocity; | 56 | if (_updateCount > 3) |
63 | 57 | { | |
64 | float timeStep = 0.3f; | 58 | this.SendTerseUpdateToALLClients(); |
65 | pos2.X = pos2.X + (vel.X * timeStep); | 59 | _updateCount = 0; |
66 | pos2.Y = pos2.Y + (vel.Y * timeStep); | 60 | } |
67 | pos2.Z = pos2.Z + (vel.Z * timeStep); | 61 | } |
68 | if ((pos2.X < 0) || (pos2.X > 256)) | ||
69 | { | ||
70 | this.CrossToNewRegion(); | ||
71 | } | ||
72 | 62 | ||
73 | if ((pos2.Y < 0) || (pos2.Y > 256)) | 63 | this.CheckBorderCrossing(); |
74 | { | ||
75 | this.CrossToNewRegion(); | ||
76 | } | 64 | } |
77 | } | 65 | } |
78 | 66 | ||
@@ -165,10 +153,35 @@ namespace OpenSim.Region.Scenes | |||
165 | 153 | ||
166 | } | 154 | } |
167 | 155 | ||
168 | private void CrossToNewRegion() | 156 | /// <summary> |
157 | /// | ||
158 | /// </summary> | ||
159 | protected void CheckBorderCrossing() | ||
160 | { | ||
161 | LLVector3 pos2 = this.Pos; | ||
162 | LLVector3 vel = this.Velocity; | ||
163 | |||
164 | float timeStep = 0.3f; | ||
165 | pos2.X = pos2.X + (vel.X * timeStep); | ||
166 | pos2.Y = pos2.Y + (vel.Y * timeStep); | ||
167 | pos2.Z = pos2.Z + (vel.Z * timeStep); | ||
168 | |||
169 | if ((pos2.X < 0) || (pos2.X > 256)) | ||
170 | { | ||
171 | this.CrossToNewRegion(); | ||
172 | } | ||
173 | |||
174 | if ((pos2.Y < 0) || (pos2.Y > 256)) | ||
175 | { | ||
176 | this.CrossToNewRegion(); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | /// <summary> | ||
181 | /// | ||
182 | /// </summary> | ||
183 | protected void CrossToNewRegion() | ||
169 | { | 184 | { |
170 | |||
171 | // Console.WriteLine("crossing to new region from region " + this.m_regionInfo.RegionLocX + " , "+ this.m_regionInfo.RegionLocY); | ||
172 | LLVector3 pos = this.Pos; | 185 | LLVector3 pos = this.Pos; |
173 | LLVector3 newpos = new LLVector3(pos.X, pos.Y, pos.Z); | 186 | LLVector3 newpos = new LLVector3(pos.X, pos.Y, pos.Z); |
174 | uint neighbourx = this.m_regionInfo.RegionLocX; | 187 | uint neighbourx = this.m_regionInfo.RegionLocX; |
@@ -196,14 +209,14 @@ namespace OpenSim.Region.Scenes | |||
196 | } | 209 | } |
197 | 210 | ||
198 | LLVector3 vel = this.velocity; | 211 | LLVector3 vel = this.velocity; |
199 | // Console.WriteLine("new region should be " + neighbourx + " , " + neighboury); | ||
200 | ulong neighbourHandle = Helpers.UIntsToLong((uint)(neighbourx * 256), (uint)(neighboury* 256)); | 212 | ulong neighbourHandle = Helpers.UIntsToLong((uint)(neighbourx * 256), (uint)(neighboury* 256)); |
201 | RegionInfo neighbourRegion = this.m_world.RequestNeighbouringRegionInfo(neighbourHandle); | 213 | RegionInfo neighbourRegion = this.m_world.RequestNeighbouringRegionInfo(neighbourHandle); |
202 | if (neighbourRegion != null) | 214 | if (neighbourRegion != null) |
203 | { | 215 | { |
204 | // Console.WriteLine("current region port is "+ this.m_regionInfo.IPListenPort + " now crossing to new region with port " + neighbourRegion.IPListenPort); | ||
205 | this.m_world.InformNeighbourOfCrossing(neighbourHandle, this.ControllingClient.AgentId, newpos); | 216 | this.m_world.InformNeighbourOfCrossing(neighbourHandle, this.ControllingClient.AgentId, newpos); |
217 | this.DownGradeAvatar(); | ||
206 | this.ControllingClient.CrossRegion(neighbourHandle, newpos, vel, System.Net.IPAddress.Parse(neighbourRegion.IPListenAddr), (ushort)neighbourRegion.IPListenPort); | 218 | this.ControllingClient.CrossRegion(neighbourHandle, newpos, vel, System.Net.IPAddress.Parse(neighbourRegion.IPListenAddr), (ushort)neighbourRegion.IPListenPort); |
219 | |||
207 | } | 220 | } |
208 | } | 221 | } |
209 | 222 | ||
diff --git a/OpenSim/OpenSim.Region/Scenes/Avatar.cs b/OpenSim/OpenSim.Region/Scenes/Avatar.cs index 98d7564..d40e213 100644 --- a/OpenSim/OpenSim.Region/Scenes/Avatar.cs +++ b/OpenSim/OpenSim.Region/Scenes/Avatar.cs | |||
@@ -103,7 +103,7 @@ namespace OpenSim.Region.Scenes | |||
103 | ControllingClient.OnCompleteMovementToRegion += new GenericCall2(this.SendInitialPosition); | 103 | ControllingClient.OnCompleteMovementToRegion += new GenericCall2(this.SendInitialPosition); |
104 | ControllingClient.OnAgentUpdate += new UpdateAgent(this.HandleAgentUpdate); | 104 | ControllingClient.OnAgentUpdate += new UpdateAgent(this.HandleAgentUpdate); |
105 | // ControllingClient.OnStartAnim += new StartAnim(this.SendAnimPack); | 105 | // ControllingClient.OnStartAnim += new StartAnim(this.SendAnimPack); |
106 | ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); | 106 | // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); |
107 | //ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); | 107 | //ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); |
108 | 108 | ||
109 | } | 109 | } |
@@ -138,7 +138,34 @@ namespace OpenSim.Region.Scenes | |||
138 | 138 | ||
139 | } | 139 | } |
140 | } | 140 | } |
141 | 141 | ||
142 | /// <summary> | ||
143 | /// | ||
144 | /// </summary> | ||
145 | /// <param name="pos"></param> | ||
146 | public void UpGradeAvatar(LLVector3 pos) | ||
147 | { | ||
148 | //this.childAvatar = false; | ||
149 | this.Pos = pos; | ||
150 | } | ||
151 | |||
152 | protected void DownGradeAvatar() | ||
153 | { | ||
154 | this.Velocity = new LLVector3(0, 0, 0); | ||
155 | this.Pos = new LLVector3(128, 128, 70); | ||
156 | this.childAvatar = true; | ||
157 | } | ||
158 | |||
159 | /// <summary> | ||
160 | /// | ||
161 | /// </summary> | ||
162 | /// <param name="pos"></param> | ||
163 | public void Teleport(LLVector3 pos) | ||
164 | { | ||
165 | this.Pos = pos; | ||
166 | this.SendTerseUpdateToALLClients(); | ||
167 | } | ||
168 | |||
142 | /// <summary> | 169 | /// <summary> |
143 | /// | 170 | /// |
144 | /// </summary> | 171 | /// </summary> |
@@ -189,7 +216,16 @@ namespace OpenSim.Region.Scenes | |||
189 | /// </summary> | 216 | /// </summary> |
190 | public void CompleteMovement() | 217 | public void CompleteMovement() |
191 | { | 218 | { |
192 | this.ControllingClient.MoveAgentIntoRegion(m_regionInfo, Pos); | 219 | LLVector3 look = this.Velocity; |
220 | if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) | ||
221 | { | ||
222 | look = new LLVector3(0.99f, 0.042f, 0); | ||
223 | } | ||
224 | this.ControllingClient.MoveAgentIntoRegion(m_regionInfo, Pos, look); | ||
225 | if (this.childAvatar) | ||
226 | { | ||
227 | this.childAvatar = false; | ||
228 | } | ||
193 | } | 229 | } |
194 | 230 | ||
195 | /// <summary> | 231 | /// <summary> |
diff --git a/OpenSim/OpenSim.Region/Scenes/Scene.cs b/OpenSim/OpenSim.Region/Scenes/Scene.cs index c0eebd4..eb942c2 100644 --- a/OpenSim/OpenSim.Region/Scenes/Scene.cs +++ b/OpenSim/OpenSim.Region/Scenes/Scene.cs | |||
@@ -42,7 +42,7 @@ using OpenSim.Framework; | |||
42 | using OpenSim.Region.Scripting; | 42 | using OpenSim.Region.Scripting; |
43 | using OpenSim.Terrain; | 43 | using OpenSim.Terrain; |
44 | using OpenGrid.Framework.Communications; | 44 | using OpenGrid.Framework.Communications; |
45 | 45 | using OpenSim.Caches; | |
46 | 46 | ||
47 | namespace OpenSim.Region.Scenes | 47 | namespace OpenSim.Region.Scenes |
48 | { | 48 | { |
@@ -64,8 +64,9 @@ namespace OpenSim.Region.Scenes | |||
64 | private Mutex updateLock; | 64 | private Mutex updateLock; |
65 | public string m_datastore; | 65 | public string m_datastore; |
66 | protected AuthenticateSessionsBase authenticateHandler; | 66 | protected AuthenticateSessionsBase authenticateHandler; |
67 | protected RegionCommsHostBase regionCommsHost; | 67 | protected RegionCommsListener regionCommsHost; |
68 | protected CommunicationsManager commsManager; | 68 | protected CommunicationsManager commsManager; |
69 | |||
69 | 70 | ||
70 | public ParcelManager parcelManager; | 71 | public ParcelManager parcelManager; |
71 | public EstateManager estateManager; | 72 | public EstateManager estateManager; |
@@ -95,13 +96,14 @@ namespace OpenSim.Region.Scenes | |||
95 | /// <param name="clientThreads">Dictionary to contain client threads</param> | 96 | /// <param name="clientThreads">Dictionary to contain client threads</param> |
96 | /// <param name="regionHandle">Region Handle for this region</param> | 97 | /// <param name="regionHandle">Region Handle for this region</param> |
97 | /// <param name="regionName">Region Name for this region</param> | 98 | /// <param name="regionName">Region Name for this region</param> |
98 | public Scene(Dictionary<uint, IClientAPI> clientThreads, RegionInfo regInfo, AuthenticateSessionsBase authen, CommunicationsManager commsMan) | 99 | public Scene(Dictionary<uint, IClientAPI> clientThreads, RegionInfo regInfo, AuthenticateSessionsBase authen, CommunicationsManager commsMan, AssetCache assetCach) |
99 | { | 100 | { |
100 | try | 101 | try |
101 | { | 102 | { |
102 | updateLock = new Mutex(false); | 103 | updateLock = new Mutex(false); |
103 | this.authenticateHandler = authen; | 104 | this.authenticateHandler = authen; |
104 | this.commsManager = commsMan; | 105 | this.commsManager = commsMan; |
106 | this.assetCache = assetCach; | ||
105 | m_clientThreads = clientThreads; | 107 | m_clientThreads = clientThreads; |
106 | m_regInfo = regInfo; | 108 | m_regInfo = regInfo; |
107 | m_regionHandle = m_regInfo.RegionHandle; | 109 | m_regionHandle = m_regInfo.RegionHandle; |
@@ -507,8 +509,10 @@ namespace OpenSim.Region.Scenes | |||
507 | remoteClient.OnRequestWearables += new GenericCall(this.InformClientOfNeighbours); | 509 | remoteClient.OnRequestWearables += new GenericCall(this.InformClientOfNeighbours); |
508 | remoteClient.OnAddPrim += new GenericCall4(this.AddNewPrim); | 510 | remoteClient.OnAddPrim += new GenericCall4(this.AddNewPrim); |
509 | remoteClient.OnUpdatePrimPosition += new UpdatePrimVector(this.UpdatePrimPosition); | 511 | remoteClient.OnUpdatePrimPosition += new UpdatePrimVector(this.UpdatePrimPosition); |
510 | 512 | remoteClient.OnRequestMapBlocks += new RequestMapBlocks(this.RequestMapBlocks); | |
511 | /* remoteClient.OnParcelPropertiesRequest += new ParcelPropertiesRequest(parcelManager.handleParcelPropertiesRequest); | 513 | remoteClient.OnTeleportLocationRequest += new TeleportLocationRequest(this.RequestTeleportLocation); |
514 | |||
515 | /* remoteClient.OnParcelPropertiesRequest += new ParcelPropertiesRequest(parcelManager.handleParcelPropertiesRequest); | ||
512 | remoteClient.OnParcelDivideRequest += new ParcelDivideRequest(parcelManager.handleParcelDivideRequest); | 516 | remoteClient.OnParcelDivideRequest += new ParcelDivideRequest(parcelManager.handleParcelDivideRequest); |
513 | remoteClient.OnParcelJoinRequest += new ParcelJoinRequest(parcelManager.handleParcelJoinRequest); | 517 | remoteClient.OnParcelJoinRequest += new ParcelJoinRequest(parcelManager.handleParcelJoinRequest); |
514 | remoteClient.OnParcelPropertiesUpdateRequest += new ParcelPropertiesUpdateRequest(parcelManager.handleParcelPropertiesUpdateRequest); | 518 | remoteClient.OnParcelPropertiesUpdateRequest += new ParcelPropertiesUpdateRequest(parcelManager.handleParcelPropertiesUpdateRequest); |
@@ -562,51 +566,7 @@ namespace OpenSim.Region.Scenes | |||
562 | return; | 566 | return; |
563 | } | 567 | } |
564 | 568 | ||
565 | /// <summary> | 569 | |
566 | /// | ||
567 | /// </summary> | ||
568 | protected void InformClientOfNeighbours(IClientAPI remoteClient) | ||
569 | { | ||
570 | // Console.WriteLine("informing client of neighbouring regions"); | ||
571 | List<RegionInfo> neighbours = this.commsManager.GridServer.RequestNeighbours(this.m_regInfo); | ||
572 | |||
573 | //Console.WriteLine("we have " + neighbours.Count + " neighbouring regions"); | ||
574 | if (neighbours != null) | ||
575 | { | ||
576 | for (int i = 0; i < neighbours.Count; i++) | ||
577 | { | ||
578 | // Console.WriteLine("sending neighbours data"); | ||
579 | AgentCircuitData agent = remoteClient.RequestClientInfo(); | ||
580 | agent.BaseFolder = LLUUID.Zero; | ||
581 | agent.InventoryFolder = LLUUID.Zero; | ||
582 | agent.startpos = new LLVector3(128, 128, 70); | ||
583 | agent.child = true; | ||
584 | this.commsManager.InterSims.InformNeighbourOfChildAgent(neighbours[i].RegionHandle, agent); | ||
585 | remoteClient.InformClientOfNeighbour(neighbours[i].RegionHandle, System.Net.IPAddress.Parse(neighbours[i].IPListenAddr), (ushort)neighbours[i].IPListenPort); | ||
586 | } | ||
587 | } | ||
588 | } | ||
589 | |||
590 | /// <summary> | ||
591 | /// | ||
592 | /// </summary> | ||
593 | /// <param name="regionHandle"></param> | ||
594 | /// <returns></returns> | ||
595 | public RegionInfo RequestNeighbouringRegionInfo(ulong regionHandle) | ||
596 | { | ||
597 | return this.commsManager.GridServer.RequestNeighbourInfo(regionHandle); | ||
598 | } | ||
599 | |||
600 | /// <summary> | ||
601 | /// | ||
602 | /// </summary> | ||
603 | /// <param name="regionhandle"></param> | ||
604 | /// <param name="agentID"></param> | ||
605 | /// <param name="position"></param> | ||
606 | public void InformNeighbourOfCrossing(ulong regionhandle, LLUUID agentID, LLVector3 position) | ||
607 | { | ||
608 | this.commsManager.InterSims.ExpectAvatarCrossing(regionhandle, agentID, position); | ||
609 | } | ||
610 | 570 | ||
611 | /// <summary> | 571 | /// <summary> |
612 | /// | 572 | /// |
@@ -725,9 +685,95 @@ namespace OpenSim.Region.Scenes | |||
725 | { | 685 | { |
726 | if (this.Avatars.ContainsKey(agentID)) | 686 | if (this.Avatars.ContainsKey(agentID)) |
727 | { | 687 | { |
728 | this.Avatars[agentID].Pos = position; | 688 | this.Avatars[agentID].UpGradeAvatar(position); |
689 | } | ||
690 | } | ||
691 | } | ||
692 | |||
693 | /// <summary> | ||
694 | /// | ||
695 | /// </summary> | ||
696 | protected void InformClientOfNeighbours(IClientAPI remoteClient) | ||
697 | { | ||
698 | // Console.WriteLine("informing client of neighbouring regions"); | ||
699 | List<RegionInfo> neighbours = this.commsManager.GridServer.RequestNeighbours(this.m_regInfo); | ||
700 | |||
701 | //Console.WriteLine("we have " + neighbours.Count + " neighbouring regions"); | ||
702 | if (neighbours != null) | ||
703 | { | ||
704 | for (int i = 0; i < neighbours.Count; i++) | ||
705 | { | ||
706 | // Console.WriteLine("sending neighbours data"); | ||
707 | AgentCircuitData agent = remoteClient.RequestClientInfo(); | ||
708 | agent.BaseFolder = LLUUID.Zero; | ||
709 | agent.InventoryFolder = LLUUID.Zero; | ||
710 | agent.startpos = new LLVector3(128, 128, 70); | ||
711 | agent.child = true; | ||
712 | this.commsManager.InterRegion.InformNeighbourOfChildAgent(neighbours[i].RegionHandle, agent); | ||
713 | remoteClient.InformClientOfNeighbour(neighbours[i].RegionHandle, System.Net.IPAddress.Parse(neighbours[i].IPListenAddr), (ushort)neighbours[i].IPListenPort); | ||
714 | } | ||
715 | } | ||
716 | } | ||
717 | |||
718 | /// <summary> | ||
719 | /// | ||
720 | /// </summary> | ||
721 | /// <param name="regionHandle"></param> | ||
722 | /// <returns></returns> | ||
723 | public RegionInfo RequestNeighbouringRegionInfo(ulong regionHandle) | ||
724 | { | ||
725 | return this.commsManager.GridServer.RequestNeighbourInfo(regionHandle); | ||
726 | } | ||
727 | |||
728 | /// <summary> | ||
729 | /// | ||
730 | /// </summary> | ||
731 | /// <param name="minX"></param> | ||
732 | /// <param name="minY"></param> | ||
733 | /// <param name="maxX"></param> | ||
734 | /// <param name="maxY"></param> | ||
735 | public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY) | ||
736 | { | ||
737 | List<MapBlockData> mapBlocks; | ||
738 | mapBlocks = this.commsManager.GridServer.RequestNeighbourMapBlocks(minX, minY, maxX, maxY); | ||
739 | |||
740 | remoteClient.SendMapBlock(mapBlocks); | ||
741 | } | ||
742 | |||
743 | /// <summary> | ||
744 | /// | ||
745 | /// </summary> | ||
746 | /// <param name="remoteClient"></param> | ||
747 | /// <param name="RegionHandle"></param> | ||
748 | /// <param name="position"></param> | ||
749 | /// <param name="lookAt"></param> | ||
750 | /// <param name="flags"></param> | ||
751 | public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, LLVector3 position, LLVector3 lookAt, uint flags) | ||
752 | { | ||
753 | if (regionHandle == this.m_regionHandle) | ||
754 | { | ||
755 | if (this.Avatars.ContainsKey(remoteClient.AgentId)) | ||
756 | { | ||
757 | remoteClient.SendTeleportLocationStart(); | ||
758 | remoteClient.SendLocalTeleport(position, lookAt, flags); | ||
759 | this.Avatars[remoteClient.AgentId].Teleport(position); | ||
729 | } | 760 | } |
730 | } | 761 | } |
762 | else | ||
763 | { | ||
764 | remoteClient.SendTeleportCancel(); | ||
765 | } | ||
766 | } | ||
767 | |||
768 | /// <summary> | ||
769 | /// | ||
770 | /// </summary> | ||
771 | /// <param name="regionhandle"></param> | ||
772 | /// <param name="agentID"></param> | ||
773 | /// <param name="position"></param> | ||
774 | public void InformNeighbourOfCrossing(ulong regionhandle, LLUUID agentID, LLVector3 position) | ||
775 | { | ||
776 | this.commsManager.InterRegion.ExpectAvatarCrossing(regionhandle, agentID, position); | ||
731 | } | 777 | } |
732 | 778 | ||
733 | #endregion | 779 | #endregion |
diff --git a/OpenSim/OpenSim.Region/Scenes/SceneBase.cs b/OpenSim/OpenSim.Region/Scenes/SceneBase.cs index d9d07b0..05c2aba 100644 --- a/OpenSim/OpenSim.Region/Scenes/SceneBase.cs +++ b/OpenSim/OpenSim.Region/Scenes/SceneBase.cs | |||
@@ -39,6 +39,7 @@ using OpenSim.Framework.Types; | |||
39 | using OpenSim.Framework.Inventory; | 39 | using OpenSim.Framework.Inventory; |
40 | using OpenSim.Region.Scripting; | 40 | using OpenSim.Region.Scripting; |
41 | using OpenSim.Terrain; | 41 | using OpenSim.Terrain; |
42 | using OpenSim.Caches; | ||
42 | 43 | ||
43 | namespace OpenSim.Region.Scenes | 44 | namespace OpenSim.Region.Scenes |
44 | { | 45 | { |
@@ -54,6 +55,7 @@ namespace OpenSim.Region.Scenes | |||
54 | protected libsecondlife.TerrainManager TerrainManager; // To be referenced via TerrainEngine | 55 | protected libsecondlife.TerrainManager TerrainManager; // To be referenced via TerrainEngine |
55 | protected object m_syncRoot = new object(); | 56 | protected object m_syncRoot = new object(); |
56 | private uint m_nextLocalId = 8880000; | 57 | private uint m_nextLocalId = 8880000; |
58 | protected AssetCache assetCache; | ||
57 | 59 | ||
58 | #region Update Methods | 60 | #region Update Methods |
59 | /// <summary> | 61 | /// <summary> |