GameSession.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using MineCase.Protocol.Play;
  7. using MineCase.Server.Network.Play;
  8. using MineCase.Server.User;
  9. using MineCase.Server.World;
  10. using Orleans;
  11. namespace MineCase.Server.Game
  12. {
  13. internal class GameSession : Grain, IGameSession
  14. {
  15. private IWorld _world;
  16. private IChunkSender _chunkSender;
  17. private readonly Dictionary<IUser, UserContext> _users = new Dictionary<IUser, UserContext>();
  18. private IDisposable _gameTick;
  19. private DateTime _lastGameTickTime;
  20. private HashSet<ITickable> _tickables;
  21. public override async Task OnActivateAsync()
  22. {
  23. _world = await GrainFactory.GetGrain<IWorldAccessor>(0).GetWorld(this.GetPrimaryKeyString());
  24. _chunkSender = GrainFactory.GetGrain<IChunkSender>(this.GetPrimaryKeyString());
  25. _lastGameTickTime = DateTime.UtcNow;
  26. _tickables = new HashSet<ITickable>();
  27. _gameTick = RegisterTimer(OnGameTick, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(50));
  28. }
  29. public async Task JoinGame(IUser user)
  30. {
  31. var sink = await user.GetClientPacketSink();
  32. var generator = new ClientPlayPacketGenerator(sink);
  33. _users[user] = new UserContext
  34. {
  35. Generator = generator
  36. };
  37. await user.JoinGame();
  38. await generator.JoinGame(
  39. (await user.GetPlayer()).GetEntityId(),
  40. new GameMode { ModeClass = GameMode.Class.Survival },
  41. Dimension.Overworld,
  42. Difficulty.Easy,
  43. 10,
  44. LevelTypes.Default,
  45. false);
  46. await user.NotifyLoggedIn();
  47. }
  48. public Task LeaveGame(IUser player)
  49. {
  50. _users.Remove(player);
  51. return Task.CompletedTask;
  52. }
  53. public async Task SendChatMessage(IUser sender, string message)
  54. {
  55. var senderName = await sender.GetName();
  56. // TODO command parser
  57. // construct name
  58. Chat jsonData = await CreateStandardChatMessage(senderName, message);
  59. byte position = 0; // It represents user message in chat box
  60. foreach (var item in _users.Keys)
  61. {
  62. await item.SendChatMessage(jsonData, position);
  63. }
  64. }
  65. public async Task SendChatMessage(IUser sender, IUser receiver, string message)
  66. {
  67. var senderName = await sender.GetName();
  68. var receiverName = await receiver.GetName();
  69. Chat jsonData = await CreateStandardChatMessage(senderName, message);
  70. byte position = 0; // It represents user message in chat box
  71. foreach (var item in _users.Keys)
  72. {
  73. if (await item.GetName() == receiverName ||
  74. await item.GetName() == senderName)
  75. await item.SendChatMessage(jsonData, position);
  76. }
  77. }
  78. private async Task OnGameTick(object state)
  79. {
  80. var now = DateTime.UtcNow;
  81. var deltaTime = now - _lastGameTickTime;
  82. _lastGameTickTime = now;
  83. var worldAge = await _world.GetAge();
  84. await _world.OnGameTick(deltaTime);
  85. await Task.WhenAll(from u in _users.Keys
  86. select u.OnGameTick(deltaTime));
  87. await Task.WhenAll(from u in _tickables
  88. select u.OnGameTick(deltaTime, worldAge));
  89. }
  90. private Task<Chat> CreateStandardChatMessage(string name, string message)
  91. {
  92. StringComponent nameComponent = new StringComponent(name);
  93. nameComponent.ClickEvent = new ChatClickEvent(ClickEventType.SuggestCommand, "/msg " + name);
  94. nameComponent.HoverEvent = new ChatHoverEvent(HoverEventType.ShowEntity, name);
  95. nameComponent.Insertion = name;
  96. // construct message
  97. StringComponent messageComponent = new StringComponent(message);
  98. // list
  99. List<ChatComponent> list = new List<ChatComponent>();
  100. list.Add(nameComponent);
  101. list.Add(messageComponent);
  102. Chat jsonData = new Chat(new TranslationComponent("chat.type.text", list));
  103. return Task.FromResult(jsonData);
  104. }
  105. public Task Subscribe(ITickable tickable)
  106. {
  107. _tickables.Add(tickable);
  108. return Task.CompletedTask;
  109. }
  110. public Task Unsubscribe(ITickable tickable)
  111. {
  112. _tickables.Remove(tickable);
  113. return Task.CompletedTask;
  114. }
  115. private class UserContext
  116. {
  117. public ClientPlayPacketGenerator Generator { get; set; }
  118. }
  119. }
  120. }