Client LuaCsForBarotrauma
Rand.cs
2 using Microsoft.Xna.Framework;
3 using System;
4 using System.Collections.Generic;
5 using System.Collections.Immutable;
6 using System.Diagnostics;
7 using System.Linq;
8 using Barotrauma.IO;
9 using Voronoi2;
10 
11 namespace Barotrauma
12 {
13  public static class Rand
14  {
15  public enum RandSync
16  {
17  Unsynced, //not synced, used for unimportant details like minor particle properties
18  ServerAndClient, //synced with the server (used for gameplay elements that the players can interact with)
19 #if CLIENT
20  ClientOnly //set to match between clients (used for misc elements that the server doesn't track, but clients want to match anyway)
21 #endif
22  }
23 
24  private static Random localRandom = new Random();
25  private static readonly Dictionary<RandSync, Random> syncedRandom = new Dictionary<RandSync, Random> {
26  { RandSync.ServerAndClient, new MTRandom() },
27 #if CLIENT
28  { RandSync.ClientOnly, new MTRandom() }
29 #endif
30  };
31 
32  public static Random GetRNG(RandSync randSync)
33  {
34  CheckRandThreadSafety(randSync);
35  return randSync == RandSync.Unsynced ? localRandom : syncedRandom[randSync];
36  }
37 
38  public static void SetLocalRandom(int seed)
39  {
40  localRandom = new Random(seed);
41  }
42 
43  public static void SetSyncedSeed(int seed)
44  {
45  syncedRandom[RandSync.ServerAndClient] = new MTRandom(seed);
46 #if CLIENT
47  syncedRandom[RandSync.ClientOnly] = new MTRandom(seed);
48 #endif
49  }
50 
51  public static int ThreadId = 0;
52  private static void CheckRandThreadSafety(RandSync sync)
53  {
54  if (ThreadId != 0 && sync == RandSync.Unsynced)
55  {
56  if (System.Threading.Thread.CurrentThread.ManagedThreadId != ThreadId)
57  {
58  Debug.WriteLine($"Unsynced rand used in synced thread! {Environment.StackTrace}");
59  }
60  }
61  if (ThreadId != 0 && sync == RandSync.ServerAndClient)
62  {
63  if (System.Threading.Thread.CurrentThread.ManagedThreadId != ThreadId)
64  {
65 #if DEBUG
66  throw new Exception("Unauthorized multithreaded access to RandSync.ServerAndClient");
67 #else
68  DebugConsole.ThrowError("Unauthorized multithreaded access to RandSync.ServerAndClient\n" + Environment.StackTrace.CleanupStackTrace());
69 #endif
70  }
71  }
72  }
73 
74  public static float Range(float minimum, float maximum, RandSync sync=RandSync.Unsynced)
75  => GetRNG(sync).Range(minimum, maximum);
76 
77  public static double Range(double minimum, double maximum, RandSync sync = RandSync.Unsynced)
78  => GetRNG(sync).Range(minimum, maximum);
79 
83  public static int Range(int minimum, int maximum, RandSync sync = RandSync.Unsynced)
84  {
85  CheckRandThreadSafety(sync);
86  return (sync == RandSync.Unsynced ? localRandom : (syncedRandom[sync])).Next(maximum - minimum) + minimum;
87  }
88 
89  public static int Int(int max, RandSync sync = RandSync.Unsynced)
90  {
91  CheckRandThreadSafety(sync);
92  return (sync == RandSync.Unsynced ? localRandom : (syncedRandom[sync])).Next(max);
93  }
94 
95  public static Vector2 Vector(float length, RandSync sync = RandSync.Unsynced)
96  {
97  Vector2 randomVector = new Vector2(Range(-1.0f, 1.0f, sync), Range(-1.0f, 1.0f, sync));
98 
99  if (randomVector.LengthSquared() < 0.001f) return new Vector2(0.0f, length);
100 
101  return Vector2.Normalize(randomVector) * length;
102  }
103 
107  public static float Value(RandSync sync = RandSync.Unsynced)
108  {
109  return Range(0f, 1f, sync);
110  }
111 
112  public static Color Color(bool randomAlpha = false, RandSync sync = RandSync.Unsynced)
113  {
114  if (randomAlpha)
115  {
116  return new Color(Value(sync), Value(sync), Value(sync), Value(sync));
117  }
118  else
119  {
120  return new Color(Value(sync), Value(sync), Value(sync));
121  }
122  }
123 
124  public static DoubleVector2 Vector(double length, RandSync sync = RandSync.Unsynced)
125  {
126  double x = Range(-1.0, 1.0, sync);
127  double y = Range(-1.0, 1.0, sync);
128 
129  double len = Math.Sqrt(x * x + y * y);
130  if (len < 0.00001) return new DoubleVector2(0.0, length);
131 
132  return new DoubleVector2(x / len * length, y / len * length);
133  }
134  }
135 }