aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
authorMW2007-03-02 18:24:54 +0000
committerMW2007-03-02 18:24:54 +0000
commitacc98fca7b3890ce865fb440737865aa7765a671 (patch)
treec0f56f7ea5c6bd98a15a65fcc1fb508523b982ec /src
parentA example of how the physics plugins might work (diff)
downloadopensim-SC_OLD-acc98fca7b3890ce865fb440737865aa7765a671.zip
opensim-SC_OLD-acc98fca7b3890ce865fb440737865aa7765a671.tar.gz
opensim-SC_OLD-acc98fca7b3890ce865fb440737865aa7765a671.tar.bz2
opensim-SC_OLD-acc98fca7b3890ce865fb440737865aa7765a671.tar.xz
r105 somehow got put in wrong place, so replacing files
Diffstat (limited to 'src')
-rw-r--r--src/world/Avatar.cs347
-rw-r--r--src/world/Entity.cs14
-rw-r--r--src/world/World.cs30
3 files changed, 138 insertions, 253 deletions
diff --git a/src/world/Avatar.cs b/src/world/Avatar.cs
index ec51c01..bcf79a8 100644
--- a/src/world/Avatar.cs
+++ b/src/world/Avatar.cs
@@ -4,231 +4,148 @@ using System.IO;
4using System.Text; 4using System.Text;
5using libsecondlife; 5using libsecondlife;
6using libsecondlife.Packets; 6using libsecondlife.Packets;
7using PhysicsManager;
8 7
9namespace OpenSim.world 8namespace OpenSim.world
10{ 9{
11 public class Avatar : Entity 10 public class Avatar : Entity
12 { 11 {
13 public string firstname; 12 public string firstname;
14 public string lastname; 13 public string lastname;
15 public OpenSimClient ControllingClient; 14 public OpenSimClient ControllingClient;
16 private PhysicsActor _physActor; 15 private libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock AvatarTemplate;
17 private libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock AvatarTemplate; 16
18 private bool updateflag; 17 public Avatar(OpenSimClient TheClient) {
19 private bool walking; 18 Console.WriteLine("Avatar.cs - Loading details from grid (DUMMY)");
20 private List<NewForce> forcesList = new List<NewForce>(); 19 ControllingClient=TheClient;
21 20 SetupTemplate("avatar-template.dat");
22 public Avatar(OpenSimClient TheClient) { 21 }
23 Console.WriteLine("Avatar.cs - Loading details from grid (DUMMY)"); 22
24 ControllingClient=TheClient; 23 private void SetupTemplate(string name)
25 SetupTemplate("avatar-template.dat");
26 }
27
28 public PhysicsActor PhysActor
29 {
30 set
31 {
32 this._physActor = value;
33 }
34 }
35 public override void addFroces()
36 { 24 {
37 if(this.forcesList.Count>0) 25
38 { 26 int i = 0;
39 for(int i=0 ; i < this.forcesList.Count; i++) 27 FileInfo fInfo = new FileInfo(name);
40 { 28 long numBytes = fInfo.Length;
41 NewForce force = this.forcesList[i]; 29 FileStream fStream = new FileStream(name, FileMode.Open, FileAccess.Read);
42 PhysicsVector phyVector = new PhysicsVector(force.X, force.Y, force.Z); 30 BinaryReader br = new BinaryReader(fStream);
43 this.PhysActor.Velocity = phyVector; 31 byte [] data1 = br.ReadBytes((int)numBytes);
44 this.updateflag = true; 32 br.Close();
45 this.velocity = new Axiom.MathLib.Vector3(force.X, force.Y, force.Z); //shouldn't really be doing this 33 fStream.Close();
46 // but as we are setting the velocity (rather than using real forces) at the moment it is okay. 34
47 35 libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock objdata = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i);
48 } 36
49 } 37 System.Text.Encoding enc = System.Text.Encoding.ASCII;
38 libsecondlife.LLVector3 pos = new LLVector3(objdata.ObjectData, 16);
39 pos.X = 100f;
40 objdata.ID = 8880000;
41 objdata.NameValue = enc.GetBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User \0");
42 libsecondlife.LLVector3 pos2 = new LLVector3(100f,100f,23f);
43 //objdata.FullID=user.AgentID;
44 byte[] pb = pos.GetBytes();
45 Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length);
46
47 AvatarTemplate = objdata;
48
50 } 49 }
51
52 public override void update()
53 {
54 if(this.updateflag)
55 {
56 //need to send movement info
57 //so create the improvedterseobjectupdate packet
58 }
59 }
60 50
61 private void SetupTemplate(string name) 51 public void CompleteMovement(World RegionInfo) {
62 { 52 Console.WriteLine("Avatar.cs:CompleteMovement() - Constructing AgentMovementComplete packet");
63 53 AgentMovementCompletePacket mov = new AgentMovementCompletePacket();
64 int i = 0; 54 mov.AgentData.SessionID = this.ControllingClient.SessionID;
65 FileInfo fInfo = new FileInfo(name); 55 mov.AgentData.AgentID = this.ControllingClient.AgentID;
66 long numBytes = fInfo.Length; 56 mov.Data.RegionHandle = OpenSim_Main.cfg.RegionHandle;
67 FileStream fStream = new FileStream(name, FileMode.Open, FileAccess.Read); 57 // TODO - dynamicalise this stuff
68 BinaryReader br = new BinaryReader(fStream); 58 mov.Data.Timestamp = 1172750370;
69 byte [] data1 = br.ReadBytes((int)numBytes); 59 mov.Data.Position = new LLVector3(100f, 100f, 23f);
70 br.Close(); 60 mov.Data.LookAt = new LLVector3(0.99f, 0.042f, 0);
71 fStream.Close(); 61
72 62 Console.WriteLine("Sending AgentMovementComplete packet");
73 libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock objdata = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); 63 ControllingClient.OutPacket(mov);
74 64 }
75 System.Text.Encoding enc = System.Text.Encoding.ASCII;
76 libsecondlife.LLVector3 pos = new LLVector3(objdata.ObjectData, 16);
77 pos.X = 100f;
78 objdata.ID = 8880000;
79 objdata.NameValue = enc.GetBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User \0");
80 libsecondlife.LLVector3 pos2 = new LLVector3(100f,100f,23f);
81 //objdata.FullID=user.AgentID;
82 byte[] pb = pos.GetBytes();
83 Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length);
84
85 AvatarTemplate = objdata;
86
87 }
88 65
89 public void CompleteMovement(World RegionInfo) { 66 public void SendInitialPosition() {
90 Console.WriteLine("Avatar.cs:CompleteMovement() - Constructing AgentMovementComplete packet"); 67 System.Text.Encoding _enc = System.Text.Encoding.ASCII;
91 AgentMovementCompletePacket mov = new AgentMovementCompletePacket(); 68
92 mov.AgentData.SessionID = this.ControllingClient.SessionID;
93 mov.AgentData.AgentID = this.ControllingClient.AgentID;
94 mov.Data.RegionHandle = OpenSim_Main.cfg.RegionHandle;
95 // TODO - dynamicalise this stuff
96 mov.Data.Timestamp = 1172750370;
97 mov.Data.Position = new LLVector3(100f, 100f, 23f);
98 mov.Data.LookAt = new LLVector3(0.99f, 0.042f, 0);
99
100 Console.WriteLine("Sending AgentMovementComplete packet");
101 ControllingClient.OutPacket(mov);
102 }
103 69
104 public void SendInitialPosition() { 70 //send a objectupdate packet with information about the clients avatar
105 System.Text.Encoding _enc = System.Text.Encoding.ASCII; 71 ObjectUpdatePacket objupdate = new ObjectUpdatePacket();
106 72 objupdate.RegionData.RegionHandle = OpenSim_Main.cfg.RegionHandle;
73 objupdate.RegionData.TimeDilation = 64096;
74 objupdate.ObjectData = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock[1];
75
76 objupdate.ObjectData[0] = AvatarTemplate;
77 //give this avatar object a local id and assign the user a name
78 objupdate.ObjectData[0].ID = 8880000 + OpenSim_Main.local_world._localNumber;
79 //User_info.name="Test"+this.local_numer+" User";
80 objupdate.ObjectData[0].FullID = ControllingClient.AgentID;
81 objupdate.ObjectData[0].NameValue = _enc.GetBytes("FirstName STRING RW SV " + firstname + "\nLastName STRING RW SV " + lastname + " \0");
82
83 libsecondlife.LLVector3 pos2 = new LLVector3(100f, 100.0f, 23.0f);
84
85 byte[] pb = pos2.GetBytes();
86
87 Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length);
88 OpenSim_Main.local_world._localNumber++;
89 this.ControllingClient.OutPacket(objupdate);
90 }
91
92 public void SendInitialAppearance() {
93 AgentWearablesUpdatePacket aw = new AgentWearablesUpdatePacket();
94 aw.AgentData.AgentID = this.ControllingClient.AgentID;
95 aw.AgentData.SerialNum = 0;
96 aw.AgentData.SessionID = ControllingClient.SessionID;
97
98 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13];
99 AgentWearablesUpdatePacket.WearableDataBlock awb = new AgentWearablesUpdatePacket.WearableDataBlock();
100 awb.WearableType = (byte)0;
101 awb.AssetID = new LLUUID("66c41e39-38f9-f75a-024e-585989bfab73");
102 awb.ItemID = LLUUID.Random();
103 aw.WearableData[0] = awb;
104
105 for(int i=1; i<13; i++) {
106 awb = new AgentWearablesUpdatePacket.WearableDataBlock();
107 awb.WearableType = (byte)i;
108 awb.AssetID = new LLUUID("00000000-0000-0000-0000-000000000000");
109 awb.ItemID = new LLUUID("00000000-0000-0000-0000-000000000000");
110 aw.WearableData[i] = awb;
111 }
112
113 ControllingClient.OutPacket(aw);
114 }
107 115
108 //send a objectupdate packet with information about the clients avatar 116 public void SendRegionHandshake(World RegionInfo) {
109 ObjectUpdatePacket objupdate = new ObjectUpdatePacket(); 117 Console.WriteLine("Avatar.cs:SendRegionHandshake() - Creating empty RegionHandshake packet");
110 objupdate.RegionData.RegionHandle = OpenSim_Main.cfg.RegionHandle; 118 System.Text.Encoding _enc = System.Text.Encoding.ASCII;
111 objupdate.RegionData.TimeDilation = 64096; 119 RegionHandshakePacket handshake = new RegionHandshakePacket();
112 objupdate.ObjectData = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock[1]; 120
113 121 Console.WriteLine("Avatar.cs:SendRegionhandshake() - Filling in RegionHandshake details");
114 objupdate.ObjectData[0] = AvatarTemplate; 122 handshake.RegionInfo.BillableFactor = 0;
115 //give this avatar object a local id and assign the user a name 123 handshake.RegionInfo.IsEstateManager = false;
116 objupdate.ObjectData[0].ID = 8880000 + OpenSim_Main.local_world._localNumber; 124 handshake.RegionInfo.TerrainHeightRange00 = 60;
117 //User_info.name="Test"+this.local_numer+" User"; 125 handshake.RegionInfo.TerrainHeightRange01 = 60;
118 objupdate.ObjectData[0].FullID = ControllingClient.AgentID; 126 handshake.RegionInfo.TerrainHeightRange10 = 60;
119 objupdate.ObjectData[0].NameValue = _enc.GetBytes("FirstName STRING RW SV " + firstname + "\nLastName STRING RW SV " + lastname + " \0"); 127 handshake.RegionInfo.TerrainHeightRange11 = 60;
120 128 handshake.RegionInfo.TerrainStartHeight00 = 10;
121 libsecondlife.LLVector3 pos2 = new LLVector3(100f, 100.0f, 23.0f); 129 handshake.RegionInfo.TerrainStartHeight01 = 10;
122 130 handshake.RegionInfo.TerrainStartHeight10 = 10;
123 byte[] pb = pos2.GetBytes(); 131 handshake.RegionInfo.TerrainStartHeight11 = 10;
124 132 handshake.RegionInfo.SimAccess = 13;
125 Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); 133 handshake.RegionInfo.WaterHeight = 5;
126 OpenSim_Main.local_world._localNumber++; 134 handshake.RegionInfo.RegionFlags = 72458694;
127 this.ControllingClient.OutPacket(objupdate); 135 handshake.RegionInfo.SimName = _enc.GetBytes(OpenSim_Main.cfg.RegionName + "\0");
128 } 136 handshake.RegionInfo.SimOwner = new LLUUID("00000000-0000-0000-0000-000000000000");
129 137 handshake.RegionInfo.TerrainBase0 = new LLUUID("b8d3965a-ad78-bf43-699b-bff8eca6c975");
130 public void SendInitialAppearance() { 138 handshake.RegionInfo.TerrainBase1 = new LLUUID("abb783e6-3e93-26c0-248a-247666855da3");
131 AgentWearablesUpdatePacket aw = new AgentWearablesUpdatePacket(); 139 handshake.RegionInfo.TerrainBase2 = new LLUUID("179cdabd-398a-9b6b-1391-4dc333ba321f");
132 aw.AgentData.AgentID = this.ControllingClient.AgentID; 140 handshake.RegionInfo.TerrainBase3 = new LLUUID("beb169c7-11ea-fff2-efe5-0f24dc881df2");
133 aw.AgentData.SerialNum = 0; 141 handshake.RegionInfo.TerrainDetail0 = new LLUUID("00000000-0000-0000-0000-000000000000");
134 aw.AgentData.SessionID = ControllingClient.SessionID; 142 handshake.RegionInfo.TerrainDetail1 = new LLUUID("00000000-0000-0000-0000-000000000000");
135 143 handshake.RegionInfo.TerrainDetail2 = new LLUUID("00000000-0000-0000-0000-000000000000");
136 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13]; 144 handshake.RegionInfo.TerrainDetail3 = new LLUUID("00000000-0000-0000-0000-000000000000");
137 AgentWearablesUpdatePacket.WearableDataBlock awb = new AgentWearablesUpdatePacket.WearableDataBlock(); 145 handshake.RegionInfo.CacheID = new LLUUID("545ec0a5-5751-1026-8a0b-216e38a7ab37");
138 awb.WearableType = (byte)0; 146
139 awb.AssetID = new LLUUID("66c41e39-38f9-f75a-024e-585989bfab73"); 147 Console.WriteLine("Avatar.cs:SendRegionHandshake() - Sending RegionHandshake packet");
140 awb.ItemID = LLUUID.Random(); 148 this.ControllingClient.OutPacket(handshake);
141 aw.WearableData[0] = awb; 149 }
142
143 for(int i=1; i<13; i++) {
144 awb = new AgentWearablesUpdatePacket.WearableDataBlock();
145 awb.WearableType = (byte)i;
146 awb.AssetID = new LLUUID("00000000-0000-0000-0000-000000000000");
147 awb.ItemID = new LLUUID("00000000-0000-0000-0000-000000000000");
148 aw.WearableData[i] = awb;
149 }
150
151 ControllingClient.OutPacket(aw);
152 }
153
154 public void HandleUpdate(AgentUpdatePacket pack) {
155 if(((uint)pack.AgentData.ControlFlags & (uint)MainAvatar.AgentUpdateFlags.AGENT_CONTROL_AT_POS) !=0) {
156 if(!walking)
157 {
158 //we should add a new force to the list
159 // but for now we will deal with velocities
160 NewFoce newVelocity = new NewForce();
161 Axiom.MathLib.Vector3 v3 = new Axiom.MathLib.Vector3(1, 0, 0);
162 Axiom.MathLib.Quaternion q = new Axiom.MathLib.Quaternion(pack.AgentData.BodyRotation.W, pack.AgentData.BodyRotation.X, pack.AgentData.BodyRotation.Y, pack.AgentData.BodyRotation.Z);
163 Axiom.MathLib.Vector3 direc = q * v3;
164 direc.Normalize();
165
166 Axiom.MathLib.Vector3 internDirec = new Vector3(direc.x, direc.y, direc.z);
167
168 //work out velocity for sim physics system
169 direc = direc * ((0.03f) * 128f);
170 newVelocity.X = direc.x;
171 newVelocity.Y = direc.y;
172 newVelocity.Z = direc.z;
173 this.forcesList.Add(newVelocity);
174 walking=true;
175 }
176 }
177 else
178 {
179 if(walking)
180 {
181
182 }
183 }
184 }
185
186 //should be moved somewhere else
187 public void SendRegionHandshake(World RegionInfo) {
188 Console.WriteLine("Avatar.cs:SendRegionHandshake() - Creating empty RegionHandshake packet");
189 System.Text.Encoding _enc = System.Text.Encoding.ASCII;
190 RegionHandshakePacket handshake = new RegionHandshakePacket();
191
192 Console.WriteLine("Avatar.cs:SendRegionhandshake() - Filling in RegionHandshake details");
193 handshake.RegionInfo.BillableFactor = 0;
194 handshake.RegionInfo.IsEstateManager = false;
195 handshake.RegionInfo.TerrainHeightRange00 = 60;
196 handshake.RegionInfo.TerrainHeightRange01 = 60;
197 handshake.RegionInfo.TerrainHeightRange10 = 60;
198 handshake.RegionInfo.TerrainHeightRange11 = 60;
199 handshake.RegionInfo.TerrainStartHeight00 = 10;
200 handshake.RegionInfo.TerrainStartHeight01 = 10;
201 handshake.RegionInfo.TerrainStartHeight10 = 10;
202 handshake.RegionInfo.TerrainStartHeight11 = 10;
203 handshake.RegionInfo.SimAccess = 13;
204 handshake.RegionInfo.WaterHeight = 5;
205 handshake.RegionInfo.RegionFlags = 72458694;
206 handshake.RegionInfo.SimName = _enc.GetBytes(OpenSim_Main.cfg.RegionName + "\0");
207 handshake.RegionInfo.SimOwner = new LLUUID("00000000-0000-0000-0000-000000000000");
208 handshake.RegionInfo.TerrainBase0 = new LLUUID("b8d3965a-ad78-bf43-699b-bff8eca6c975");
209 handshake.RegionInfo.TerrainBase1 = new LLUUID("abb783e6-3e93-26c0-248a-247666855da3");
210 handshake.RegionInfo.TerrainBase2 = new LLUUID("179cdabd-398a-9b6b-1391-4dc333ba321f");
211 handshake.RegionInfo.TerrainBase3 = new LLUUID("beb169c7-11ea-fff2-efe5-0f24dc881df2");
212 handshake.RegionInfo.TerrainDetail0 = new LLUUID("00000000-0000-0000-0000-000000000000");
213 handshake.RegionInfo.TerrainDetail1 = new LLUUID("00000000-0000-0000-0000-000000000000");
214 handshake.RegionInfo.TerrainDetail2 = new LLUUID("00000000-0000-0000-0000-000000000000");
215 handshake.RegionInfo.TerrainDetail3 = new LLUUID("00000000-0000-0000-0000-000000000000");
216 handshake.RegionInfo.CacheID = new LLUUID("545ec0a5-5751-1026-8a0b-216e38a7ab37");
217
218 Console.WriteLine("Avatar.cs:SendRegionHandshake() - Sending RegionHandshake packet");
219 this.ControllingClient.OutPacket(handshake);
220 }
221 }
222
223 public class NewForce
224 {
225 public float X;
226 public float Y;
227 public float Z;
228
229 public NewForce()
230 {
231
232 }
233 } 150 }
234} 151}
diff --git a/src/world/Entity.cs b/src/world/Entity.cs
index 72e4e83..ab07fd6 100644
--- a/src/world/Entity.cs
+++ b/src/world/Entity.cs
@@ -9,9 +9,9 @@ namespace OpenSim.world
9 public class Entity 9 public class Entity
10 { 10 {
11 protected libsecondlife.LLUUID uuid; 11 protected libsecondlife.LLUUID uuid;
12 public Vector3 position; 12 protected Vector3 position;
13 public Vector3 velocity; 13 protected Vector3 velocity;
14 public Quaternion rotation; 14 protected Quaternion rotation;
15 protected string name; 15 protected string name;
16 protected List<Entity> children; 16 protected List<Entity> children;
17 17
@@ -24,13 +24,7 @@ namespace OpenSim.world
24 name = "(basic entity)"; 24 name = "(basic entity)";
25 children = new List<Entity>(); 25 children = new List<Entity>();
26 } 26 }
27 public virtual void addFroces() 27
28 {
29 foreach (Entity child in children)
30 {
31 child.addFroces();
32 }
33 }
34 public virtual void update() { 28 public virtual void update() {
35 // Do any per-frame updates needed that are applicable to every type of entity 29 // Do any per-frame updates needed that are applicable to every type of entity
36 foreach (Entity child in children) 30 foreach (Entity child in children)
diff --git a/src/world/World.cs b/src/world/World.cs
index 920220f..ebbd61e 100644
--- a/src/world/World.cs
+++ b/src/world/World.cs
@@ -3,7 +3,6 @@ using libsecondlife;
3using libsecondlife.Packets; 3using libsecondlife.Packets;
4using System.Collections.Generic; 4using System.Collections.Generic;
5using System.Text; 5using System.Text;
6using PhysicsManager;
7 6
8namespace OpenSim.world 7namespace OpenSim.world
9{ 8{
@@ -14,8 +13,6 @@ namespace OpenSim.world
14 public ScriptEngine Scripts; 13 public ScriptEngine Scripts;
15 public TerrainDecode terrainengine = new TerrainDecode(); 14 public TerrainDecode terrainengine = new TerrainDecode();
16 public uint _localNumber=0; 15 public uint _localNumber=0;
17 private PhysicsScene phyScene;
18 private float timeStep= 0.1f;
19 16
20 private Random Rand = new Random(); 17 private Random Rand = new Random();
21 18
@@ -35,30 +32,9 @@ namespace OpenSim.world
35 // Initialise this only after the world has loaded 32 // Initialise this only after the world has loaded
36 Scripts = new ScriptEngine(this); 33 Scripts = new ScriptEngine(this);
37 } 34 }
38 35
39 public PhysicsScene PhysScene
40 {
41 set
42 {
43 this.phyScene = value;
44 }
45 }
46
47 public void Update() 36 public void Update()
48 { 37 {
49 if(this.phyScene.IsThreaded)
50 {
51 this.phyScene.GetResults();
52
53 }
54
55 foreach (libsecondlife.LLUUID UUID in Entities.Keys)
56 {
57 Entities[UUID].addFroces();
58 }
59
60 this.phyScene.Simulate(timeStep);
61
62 foreach (libsecondlife.LLUUID UUID in Entities.Keys) 38 foreach (libsecondlife.LLUUID UUID in Entities.Keys)
63 { 39 {
64 Entities[UUID].update(); 40 Entities[UUID].update();
@@ -79,9 +55,7 @@ namespace OpenSim.world
79 this.Entities.Add(AgentClient.AgentID, NewAvatar); 55 this.Entities.Add(AgentClient.AgentID, NewAvatar);
80 Console.WriteLine("World.cs:AddViewerAgent() - Starting RegionHandshake "); 56 Console.WriteLine("World.cs:AddViewerAgent() - Starting RegionHandshake ");
81 NewAvatar.SendRegionHandshake(this); 57 NewAvatar.SendRegionHandshake(this);
82 58 this.Update(); // will work for now, but needs to be optimised so we don't update everything in the sim for each new user
83 NewAvatar.PhysActor = this.phyScene.AddAvatar(new PhysicsVector(NewAvatar.position.x, NewAvatar.position.y, NewAvatar.position.z));
84 //this.Update(); // will work for now, but needs to be optimised so we don't update everything in the sim for each new user
85 } 59 }
86 60
87 public bool Backup() { 61 public bool Backup() {