Server LuaCsForBarotrauma
GameScreen.cs
1 //#define RUN_PHYSICS_IN_SEPARATE_THREAD
2 
3 using Microsoft.Xna.Framework;
4 using System.Threading;
5 using FarseerPhysics.Dynamics;
6 #if DEBUG && CLIENT
7 using System;
8 using Microsoft.Xna.Framework.Input;
9 #endif
10 
11 namespace Barotrauma
12 {
13  partial class GameScreen : Screen
14  {
15  private object updateLock = new object();
16  private double physicsTime;
17 
18 #if CLIENT
19  private readonly Camera cam;
20 
21  public override Camera Cam
22  {
23  get { return cam; }
24  }
25 #elif SERVER
26  public override Camera Cam
27  {
28  get { return Camera.Instance; }
29  }
30 #endif
31 
32  public double GameTime
33  {
34  get;
35  private set;
36  }
37 
38  public GameScreen()
39  {
40 #if CLIENT
41  cam = new Camera();
42  cam.Translate(new Vector2(-10.0f, 50.0f));
43 #endif
44  }
45 
46  public override void Select()
47  {
48  base.Select();
49 
50 #if CLIENT
51  if (Character.Controlled != null)
52  {
53  cam.Position = Character.Controlled.WorldPosition;
54  cam.UpdateTransform(true);
55  }
56  else if (Submarine.MainSub != null)
57  {
58  cam.Position = Submarine.MainSub.WorldPosition;
59  cam.UpdateTransform(true);
60  }
61  GameMain.GameSession?.CrewManager?.AutoShowCrewList();
62 #endif
63 
65 
66 #if RUN_PHYSICS_IN_SEPARATE_THREAD
67  var physicsThread = new Thread(ExecutePhysics)
68  {
69  Name = "Physics thread",
70  IsBackground = true
71  };
72  physicsThread.Start();
73 #endif
74  }
75 
76  public override void Deselect()
77  {
78  base.Deselect();
79 #if CLIENT
80  var config = GameSettings.CurrentConfig;
81  config.CrewMenuOpen = CrewManager.PreferCrewMenuOpen;
82  config.ChatOpen = ChatBox.PreferChatBoxOpen;
83  GameSettings.SetCurrentConfig(config);
84  GameSettings.SaveCurrentConfig();
85  GameMain.SoundManager.SetCategoryMuffle("default", false);
86  GUI.ClearMessages();
87 #if !DEBUG
89  {
90  DebugConsole.DeactivateCheats();
91  }
92 #endif
93 #endif
94  }
99  public override void Update(double deltaTime)
100  {
101 #if RUN_PHYSICS_IN_SEPARATE_THREAD
102  physicsTime += deltaTime;
103  lock (updateLock)
104  {
105 #endif
106 
107 
108 #if DEBUG && CLIENT
109  if (GameMain.GameSession != null && !DebugConsole.IsOpen && GUI.KeyboardDispatcher.Subscriber == null)
110  {
111  if (GameMain.GameSession.Level != null && GameMain.GameSession.Submarine != null)
112  {
113  Submarine closestSub = Submarine.FindClosest(cam.WorldViewCenter) ?? GameMain.GameSession.Submarine;
114 
115  Vector2 targetMovement = Vector2.Zero;
116  if (PlayerInput.KeyDown(Keys.I)) { targetMovement.Y += 1.0f; }
117  if (PlayerInput.KeyDown(Keys.K)) { targetMovement.Y -= 1.0f; }
118  if (PlayerInput.KeyDown(Keys.J)) { targetMovement.X -= 1.0f; }
119  if (PlayerInput.KeyDown(Keys.L)) { targetMovement.X += 1.0f; }
120 
121  if (targetMovement != Vector2.Zero)
122  {
123  closestSub.ApplyForce(targetMovement * closestSub.SubBody.Body.Mass * 100.0f);
124  }
125  }
126  }
127 #endif
128 
129 #if CLIENT
130  GameMain.LightManager?.Update((float)deltaTime);
131 #endif
132 
133  GameTime += deltaTime;
134 
135  foreach (PhysicsBody body in PhysicsBody.List)
136  {
137  if (body.Enabled && body.BodyType != FarseerPhysics.BodyType.Static) { body.Update(); }
138  }
140 
141 #if CLIENT
142  var sw = new System.Diagnostics.Stopwatch();
143  sw.Start();
144 #endif
145 
146  GameMain.GameSession?.Update((float)deltaTime);
147 
148 #if CLIENT
149  sw.Stop();
150  GameMain.PerformanceCounter.AddElapsedTicks("Update:GameSession", sw.ElapsedTicks);
151  sw.Restart();
152 
153  GameMain.ParticleManager.Update((float)deltaTime);
154 
155  sw.Stop();
156  GameMain.PerformanceCounter.AddElapsedTicks("Update:Particles", sw.ElapsedTicks);
157  sw.Restart();
158 
159  if (Level.Loaded != null) Level.Loaded.Update((float)deltaTime, cam);
160 
161  sw.Stop();
162  GameMain.PerformanceCounter.AddElapsedTicks("Update:Level", sw.ElapsedTicks);
163 
164  if (Character.Controlled is { } controlled)
165  {
166  if (controlled.SelectedItem != null && controlled.CanInteractWith(controlled.SelectedItem))
167  {
168  controlled.SelectedItem.UpdateHUD(cam, controlled, (float)deltaTime);
169  }
170  if (controlled.Inventory != null)
171  {
172  foreach (Item item in controlled.Inventory.AllItems)
173  {
174  if (controlled.HasEquippedItem(item))
175  {
176  item.UpdateHUD(cam, controlled, (float)deltaTime);
177  }
178  }
179  }
180  }
181 
182  sw.Restart();
183 
184  Character.UpdateAll((float)deltaTime, cam);
185 #elif SERVER
186  if (Level.Loaded != null) Level.Loaded.Update((float)deltaTime, Camera.Instance);
187  Character.UpdateAll((float)deltaTime, Camera.Instance);
188 #endif
189 
190 
191 #if CLIENT
192  sw.Stop();
193  GameMain.PerformanceCounter.AddElapsedTicks("Update:Character", sw.ElapsedTicks);
194  sw.Restart();
195 #endif
196 
197  StatusEffect.UpdateAll((float)deltaTime);
198 
199 #if CLIENT
200  sw.Stop();
201  GameMain.PerformanceCounter.AddElapsedTicks("Update:StatusEffects", sw.ElapsedTicks);
202  sw.Restart();
203 
204  if (Character.Controlled != null &&
205  Lights.LightManager.ViewTarget != null)
206  {
207  Vector2 targetPos = Lights.LightManager.ViewTarget.WorldPosition;
208  if (Lights.LightManager.ViewTarget == Character.Controlled &&
209  (CharacterHealth.OpenHealthWindow != null || CrewManager.IsCommandInterfaceOpen || ConversationAction.IsDialogOpen))
210  {
211  Vector2 screenTargetPos = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) * 0.5f;
212  if (CharacterHealth.OpenHealthWindow != null)
213  {
214  screenTargetPos.X = GameMain.GraphicsWidth * (CharacterHealth.OpenHealthWindow.Alignment == Alignment.Left ? 0.6f : 0.4f);
215  }
216  else if (ConversationAction.IsDialogOpen)
217  {
218  screenTargetPos.Y = GameMain.GraphicsHeight * 0.4f;
219  }
220  Vector2 screenOffset = screenTargetPos - new Vector2(GameMain.GraphicsWidth / 2, GameMain.GraphicsHeight / 2);
221  screenOffset.Y = -screenOffset.Y;
222  targetPos -= screenOffset / cam.Zoom;
223  }
224  cam.TargetPos = targetPos;
225  }
226 
227  cam.MoveCamera((float)deltaTime, allowZoom: GUI.MouseOn == null && !Inventory.IsMouseOnInventory);
228 
229  Character.Controlled?.UpdateLocalCursor(cam);
230 #endif
231 
232  foreach (Submarine sub in Submarine.Loaded)
233  {
234  sub.SetPrevTransform(sub.Position);
235  }
236 
237  foreach (PhysicsBody body in PhysicsBody.List)
238  {
239  if (body.Enabled && body.BodyType != FarseerPhysics.BodyType.Static)
240  {
241  body.SetPrevTransform(body.SimPosition, body.Rotation);
242  }
243  }
244 
245 #if CLIENT
246  MapEntity.UpdateAll((float)deltaTime, cam);
247 #elif SERVER
248  MapEntity.UpdateAll((float)deltaTime, Camera.Instance);
249 #endif
250 
251 #if CLIENT
252  sw.Stop();
253  GameMain.PerformanceCounter.AddElapsedTicks("Update:MapEntity", sw.ElapsedTicks);
254  sw.Restart();
255 #endif
256  Character.UpdateAnimAll((float)deltaTime);
257 
258 #if CLIENT
259  Ragdoll.UpdateAll((float)deltaTime, cam);
260 #elif SERVER
261  Ragdoll.UpdateAll((float)deltaTime, Camera.Instance);
262 #endif
263 
264 #if CLIENT
265  sw.Stop();
266  GameMain.PerformanceCounter.AddElapsedTicks("Update:Ragdolls", sw.ElapsedTicks);
267  sw.Restart();
268 #endif
269 
270  foreach (Submarine sub in Submarine.Loaded)
271  {
272  sub.Update((float)deltaTime);
273  }
274 
275 #if CLIENT
276  sw.Stop();
277  GameMain.PerformanceCounter.AddElapsedTicks("Update:Submarine", sw.ElapsedTicks);
278  sw.Restart();
279 #endif
280 
281 #if !RUN_PHYSICS_IN_SEPARATE_THREAD
282  try
283  {
284  GameMain.World.Step((float)Timing.Step);
285  }
286  catch (WorldLockedException e)
287  {
288  string errorMsg = "Attempted to modify the state of the physics simulation while a time step was running.";
289  DebugConsole.ThrowError(errorMsg, e);
290  GameAnalyticsManager.AddErrorEventOnce("GameScreen.Update:WorldLockedException" + e.Message, GameAnalyticsManager.ErrorSeverity.Critical, errorMsg);
291  }
292 #endif
293 
294 
295 #if CLIENT
296  sw.Stop();
297  GameMain.PerformanceCounter.AddElapsedTicks("Update:Physics", sw.ElapsedTicks);
298 #endif
299  UpdateProjSpecific(deltaTime);
300 
301 #if RUN_PHYSICS_IN_SEPARATE_THREAD
302  }
303 #endif
304  }
305 
306  partial void UpdateProjSpecific(double deltaTime);
307 
308  private void ExecutePhysics()
309  {
310  while (true)
311  {
312  while (physicsTime >= Timing.Step)
313  {
314  lock (updateLock)
315  {
316  GameMain.World.Step((float)Timing.Step);
317  physicsTime -= Timing.Step;
318  }
319  }
320  }
321  }
322  }
323 }
static Camera Instance
Definition: Camera.cs:9
static void UpdateAll(float deltaTime, Camera cam)
Triggers a "conversation popup" with text and support for different branching options.
Responsible for keeping track of the characters in the player crew, saving and loading their orders,...
virtual Vector2 WorldPosition
Definition: Entity.cs:49
static World World
Definition: GameMain.cs:28
static GameSession GameSession
Definition: GameMain.cs:45
override void Update(double deltaTime)
Allows the game to run logic such as updating the world, checking for collisions, gathering input,...
Definition: GameScreen.cs:99
override Camera Cam
Definition: GameScreen.cs:27
override void Deselect()
Definition: GameScreen.cs:76
override void Select()
Definition: GameScreen.cs:46
void Update(float deltaTime)
CrewManager? CrewManager
Definition: GameSession.cs:75
void Update(float deltaTime, Camera cam)
static void UpdateAll(float deltaTime, Camera cam)
Call Update() on every object in Entity.list
Definition: MapEntity.cs:616
static void ClearHighlightedEntities()
Definition: MapEntity.cs:413
void SetPrevTransform(Vector2 simPosition, float rotation)
static void UpdateAll(float deltaTime, Camera cam)
Definition: Ragdoll.cs:1042
StatusEffects can be used to execute various kinds of effects: modifying the state of some entity in ...
Definition: StatusEffect.cs:72
static void UpdateAll(float deltaTime)
readonly PhysicsBody Body
static Submarine MainSub
Note that this can be null in some situations, e.g. editors and missions that don't load a submarine.
static Submarine FindClosest(Vector2 worldPosition, bool ignoreOutposts=false, bool ignoreOutsideLevel=true, bool ignoreRespawnShuttle=false, CharacterTeamType? teamType=null)
If has value, the sub must match the team type.