Client LuaCsForBarotrauma
BarotraumaShared/SharedSource/Screens/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  }
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 &&
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  }
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 
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 void UpdateAll(float deltaTime, Camera cam)
static bool PreferChatBoxOpen
Definition: ChatBox.cs:34
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 int GraphicsWidth
Definition: GameMain.cs:162
static GameSession?? GameSession
Definition: GameMain.cs:88
static PerformanceCounter PerformanceCounter
Definition: GameMain.cs:37
static int GraphicsHeight
Definition: GameMain.cs:168
static Lights.LightManager LightManager
Definition: GameMain.cs:78
static World World
Definition: GameMain.cs:105
static ParticleManager ParticleManager
Definition: GameMain.cs:101
static Sounds.SoundManager SoundManager
Definition: GameMain.cs:80
override void Update(double deltaTime)
Allows the game to run logic such as updating the world, checking for collisions, gathering input,...
void UpdateHUD(Camera cam, Character character, float deltaTime)
void Update(float deltaTime, Camera cam)
static void UpdateAll(float deltaTime, Camera cam)
Call Update() on every object in Entity.list
void AddElapsedTicks(string identifier, long ticks)
void SetPrevTransform(Vector2 simPosition, float rotation)
static bool KeyDown(InputType inputType)
StatusEffects can be used to execute various kinds of effects: modifying the state of some entity in ...
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.