A stable modding interface between Techblox and mods https://mod.exmods.org/
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

436 行
12KB

  1. using System;
  2. using Unity.Mathematics;
  3. using RobocraftX.Common;
  4. using RobocraftX.Common.Players;
  5. using Svelto.ECS;
  6. using GamecraftModdingAPI.Players;
  7. using GamecraftModdingAPI.Blocks;
  8. namespace GamecraftModdingAPI
  9. {
  10. /// <summary>
  11. /// An in-game player character. Any Leo you see is a player.
  12. /// </summary>
  13. public class Player : IEquatable<Player>, IEquatable<EGID>
  14. {
  15. // static functionality
  16. private static PlayerEngine playerEngine = new PlayerEngine();
  17. private static Player localPlayer;
  18. /// <summary>
  19. /// Checks if the specified player exists.
  20. /// </summary>
  21. /// <returns>Whether the player exists.</returns>
  22. /// <param name="player">Player type.</param>
  23. public static bool Exists(PlayerType player)
  24. {
  25. switch (player)
  26. {
  27. case PlayerType.Remote:
  28. return playerEngine.GetRemotePlayer() != uint.MaxValue;
  29. case PlayerType.Local:
  30. return playerEngine.GetLocalPlayer() != uint.MaxValue;
  31. }
  32. return false;
  33. }
  34. /// <summary>
  35. /// Checks if the specified player exists.
  36. /// </summary>
  37. /// <returns>Whether the player exists.</returns>
  38. /// <param name="player">The player's unique identifier.</param>
  39. public static bool Exists(uint player)
  40. {
  41. return playerEngine.ExistsById(player);
  42. }
  43. /// <summary>
  44. /// The amount of Players in the current game.
  45. /// </summary>
  46. /// <returns>The count.</returns>
  47. public static uint Count()
  48. {
  49. return (uint) playerEngine.GetAllPlayerCount();
  50. }
  51. /// <summary>
  52. /// Returns the current player belonging to this client.
  53. /// </summary>
  54. public static Player LocalPlayer
  55. {
  56. get
  57. {
  58. if (localPlayer == null || localPlayer.Id != playerEngine.GetLocalPlayer())
  59. localPlayer = new Player(PlayerType.Local);
  60. return localPlayer;
  61. }
  62. }
  63. /// <summary>
  64. /// Initializes a new instance of the <see cref="T:GamecraftModdingAPI.Player"/> class.
  65. /// </summary>
  66. /// <param name="id">The player's unique identifier.</param>
  67. public Player(uint id)
  68. {
  69. this.Id = id;
  70. if (!Exists(id))
  71. {
  72. throw new PlayerNotFoundException($"No player with id {id} exists");
  73. }
  74. this.Type = playerEngine.GetLocalPlayer() == id ? PlayerType.Local : PlayerType.Remote;
  75. }
  76. /// <summary>
  77. /// Initializes a new instance of the <see cref="T:GamecraftModdingAPI.Player"/> class.
  78. /// </summary>
  79. /// <param name="player">The player type. Chooses the first available player matching the criteria.</param>
  80. public Player(PlayerType player)
  81. {
  82. switch (player)
  83. {
  84. case PlayerType.Local:
  85. this.Id = playerEngine.GetLocalPlayer();
  86. break;
  87. case PlayerType.Remote:
  88. this.Id = playerEngine.GetRemotePlayer();
  89. break;
  90. }
  91. if (this.Id == uint.MaxValue)
  92. {
  93. throw new PlayerNotFoundException($"No player of {player} type exists");
  94. }
  95. this.Type = player;
  96. }
  97. // object fields & properties
  98. /// <summary>
  99. /// The player's type.
  100. /// The player type is always relative to the current client, not the game host.
  101. /// </summary>
  102. /// <value>The enumerated player type.</value>
  103. public PlayerType Type { get; }
  104. /// <summary>
  105. /// The player's unique identifier.
  106. /// </summary>
  107. /// <value>The identifier.</value>
  108. public uint Id { get; }
  109. /// <summary>
  110. /// The player's current position.
  111. /// </summary>
  112. /// <value>The position.</value>
  113. public float3 Position
  114. {
  115. get
  116. {
  117. return playerEngine.GetLocation(Id);
  118. }
  119. set
  120. {
  121. playerEngine.SetLocation(Id, value, false);
  122. }
  123. }
  124. /// <summary>
  125. /// The player's current rotation.
  126. /// </summary>
  127. /// <value>The rotation.</value>
  128. public float3 Rotation
  129. {
  130. get
  131. {
  132. return playerEngine.GetRotation(Id);
  133. }
  134. set
  135. {
  136. playerEngine.SetRotation(Id, value);
  137. }
  138. }
  139. /// <summary>
  140. /// The player's current velocity.
  141. /// </summary>
  142. /// <value>The velocity.</value>
  143. public float3 Velocity
  144. {
  145. get
  146. {
  147. return playerEngine.GetLinearVelocity(Id);
  148. }
  149. set
  150. {
  151. playerEngine.SetLinearVelocity(Id, value);
  152. }
  153. }
  154. /// <summary>
  155. /// The player's current angular velocity.
  156. /// </summary>
  157. /// <value>The angular velocity.</value>
  158. public float3 AngularVelocity
  159. {
  160. get
  161. {
  162. return playerEngine.GetAngularVelocity(Id);
  163. }
  164. set
  165. {
  166. playerEngine.SetAngularVelocity(Id, value);
  167. }
  168. }
  169. /// <summary>
  170. /// The player's mass.
  171. /// </summary>
  172. /// <value>The mass.</value>
  173. public float Mass
  174. {
  175. get
  176. {
  177. return 1f / playerEngine.GetMass(Id).InverseMass;
  178. }
  179. // FIXME: Setting mass doesn't do anything
  180. /*set
  181. {
  182. playerEngine.SetInverseMass(Id, 1f / value);
  183. }*/
  184. }
  185. private float _ping = -1f;
  186. /// <summary>
  187. /// The player's latest network ping time.
  188. /// </summary>
  189. /// <value>The ping (s).</value>
  190. public float Ping
  191. {
  192. get
  193. {
  194. float? temp = playerEngine.GetLastPingTime(Id, Type);
  195. if (temp.HasValue)
  196. {
  197. _ping = temp.Value;
  198. }
  199. return _ping;
  200. }
  201. }
  202. /// <summary>
  203. /// The player's initial health when entering Simulation (aka Time Running) mode.
  204. /// </summary>
  205. /// <value>The initial health.</value>
  206. public float InitialHealth
  207. {
  208. get => playerEngine.GetInitialHealth(Id);
  209. set
  210. {
  211. playerEngine.SetInitialHealth(Id, value);
  212. }
  213. }
  214. /// <summary>
  215. /// The player's current health in Simulation (aka Time Running) mode.
  216. /// </summary>
  217. /// <value>The current health.</value>
  218. public float CurrentHealth
  219. {
  220. get => playerEngine.GetCurrentHealth(Id);
  221. set
  222. {
  223. playerEngine.DamagePlayer(Id, CurrentHealth - value);
  224. }
  225. }
  226. /// <summary>
  227. /// Whether this <see cref="T:GamecraftModdingAPI.Player"/> is damageable.
  228. /// </summary>
  229. /// <value><c>true</c> if damageable; otherwise, <c>false</c>.</value>
  230. public bool Damageable
  231. {
  232. get => playerEngine.GetDamageable(Id);
  233. set
  234. {
  235. playerEngine.SetDamageable(Id, value);
  236. }
  237. }
  238. /// <summary>
  239. /// The player's lives when initially entering Simulation (aka Time Running) mode.
  240. /// </summary>
  241. /// <value>The initial lives.</value>
  242. public uint InitialLives
  243. {
  244. get => playerEngine.GetInitialLives(Id);
  245. set => playerEngine.SetInitialLives(Id, value);
  246. }
  247. /// <summary>
  248. /// The player's current lives in Simulation (aka Time Running) mode.
  249. /// </summary>
  250. /// <value>The current lives.</value>
  251. public uint CurrentLives
  252. {
  253. get => playerEngine.GetCurrentLives(Id);
  254. set => playerEngine.SetCurrentLives(Id, value);
  255. }
  256. /// <summary>
  257. /// Whether the Game Over screen is displayed for the player.
  258. /// </summary>
  259. /// <value><c>true</c> if game over; otherwise, <c>false</c>.</value>
  260. public bool GameOver
  261. {
  262. get => playerEngine.GetGameOverScreen(Id);
  263. }
  264. /// <summary>
  265. /// Whether the player is dead.
  266. /// If <c>true</c>, hopefully it was quick.
  267. /// </summary>
  268. /// <value><c>true</c> if dead; otherwise, <c>false</c>.</value>
  269. public bool Dead
  270. {
  271. get => playerEngine.IsDead(Id);
  272. }
  273. /// <summary>
  274. /// The player's selected block ID in their hand.
  275. /// </summary>
  276. /// <value>The selected block.</value>
  277. public BlockIDs SelectedBlock
  278. {
  279. get
  280. {
  281. return (BlockIDs)playerEngine.GetSelectedBlock(Id);
  282. }
  283. }
  284. /// <summary>
  285. /// The player's selected block color in their hand.
  286. /// </summary>
  287. /// <value>The selected block's color.</value>
  288. public BlockColor SelectedColor
  289. {
  290. get
  291. {
  292. return new BlockColor(playerEngine.GetSelectedColor(Id));
  293. }
  294. }
  295. /// <summary>
  296. /// The player's selected block colour in their hand.
  297. /// </summary>
  298. /// <value>The selected block's colour.</value>
  299. public BlockColor SelectedColour
  300. {
  301. get
  302. {
  303. return new BlockColor(playerEngine.GetSelectedColor(Id));
  304. }
  305. }
  306. // object methods
  307. /// <summary>
  308. /// Teleport the player to the specified coordinates.
  309. /// </summary>
  310. /// <param name="x">The x coordinate.</param>
  311. /// <param name="y">The y coordinate.</param>
  312. /// <param name="z">The z coordinate.</param>
  313. /// <param name="relative">If set to <c>true</c> teleport relative to the player's current position.</param>
  314. /// <param name="exitSeat">If set to <c>true</c> exit any seat the player is in.</param>
  315. public void Teleport(float x, float y, float z, bool relative = true, bool exitSeat = true)
  316. {
  317. float3 location = new float3(x, y, z);
  318. if (relative)
  319. {
  320. location += playerEngine.GetLocation(Id);
  321. }
  322. playerEngine.SetLocation(Id, location, exitSeat: exitSeat);
  323. }
  324. /// <summary>
  325. /// Returns the block the player is currently looking at in build mode.
  326. /// </summary>
  327. /// <param name="maxDistance">The maximum distance from the player (default is the player's building reach)</param>
  328. /// <returns>The block or null if not found</returns>
  329. public Block GetBlockLookedAt(float maxDistance = -1f)
  330. {
  331. var egid = playerEngine.GetThingLookedAt(Id, maxDistance);
  332. return egid.HasValue && egid.Value.groupID != CommonExclusiveGroups.SIMULATION_BODIES_GROUP
  333. ? new Block(egid.Value)
  334. : null;
  335. }
  336. /// <summary>
  337. /// Returns the rigid body the player is currently looking at during simulation.
  338. /// </summary>
  339. /// <param name="maxDistance">The maximum distance from the player (default is the player's building reach)</param>
  340. /// <returns>The block or null if not found</returns>
  341. public SimBody GetSimBodyLookedAt(float maxDistance = -1f)
  342. {
  343. var egid = playerEngine.GetThingLookedAt(Id, maxDistance);
  344. return egid.HasValue && egid.Value.groupID == CommonExclusiveGroups.SIMULATION_BODIES_GROUP
  345. ? new SimBody(egid.Value)
  346. : null;
  347. }
  348. /// <summary>
  349. /// Returns the blocks that are in the player's current selection.
  350. /// </summary>
  351. /// <returns>An array of blocks or an empty array</returns>
  352. public Block[] GetSelectedBlocks()
  353. {
  354. return playerEngine.GetSelectedBlocks(Id);
  355. }
  356. public bool Equals(Player other)
  357. {
  358. if (ReferenceEquals(null, other)) return false;
  359. if (ReferenceEquals(this, other)) return true;
  360. return Id == other.Id;
  361. }
  362. public bool Equals(EGID other)
  363. {
  364. return Id == other.entityID && other.groupID == (Type == PlayerType.Local
  365. ? PlayersExclusiveGroups.LocalPlayers
  366. : PlayersExclusiveGroups.RemotePlayers);
  367. }
  368. public override bool Equals(object obj)
  369. {
  370. if (ReferenceEquals(null, obj)) return false;
  371. if (ReferenceEquals(this, obj)) return true;
  372. if (obj.GetType() != this.GetType()) return false;
  373. return Equals((Player) obj);
  374. }
  375. public override int GetHashCode()
  376. {
  377. return (int) Id;
  378. }
  379. // internal methods
  380. internal static void Init()
  381. {
  382. Utility.GameEngineManager.AddGameEngine(playerEngine);
  383. }
  384. }
  385. }