app.hypergames.hypersdk 1.4.12 → 1.4.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -42,7 +42,7 @@ namespace Hyper.Internal.Managers
42
42
 
43
43
  #region Public Properties (Internal API)
44
44
 
45
- public int scoreSubmissionTimeout { get; private set; } = 3;
45
+ public int scoreSubmissionTimeout { get; private set; } = 4;
46
46
  public int CurrentRetryCount => _currentRetryCount;
47
47
  public bool isSocketConnected { get; private set; }
48
48
  public bool tutorialFetchSuccess { get; private set; }
@@ -373,6 +373,7 @@ namespace Hyper.Internal.Managers
373
373
  };
374
374
 
375
375
  string json = JsonConvert.SerializeObject(message);
376
+ HyperDebug.Log($"Sending game resumed message: {json}");
376
377
  SendWebSocketMessage(json);
377
378
  }
378
379
  catch (Exception ex)
@@ -381,7 +382,7 @@ namespace Hyper.Internal.Managers
381
382
  }
382
383
 
383
384
  float elapsed = 0f;
384
- const float timeout = 2f;
385
+ const float timeout = 1f;
385
386
 
386
387
  while (!_gameResumed && elapsed < timeout)
387
388
  {
@@ -390,7 +391,7 @@ namespace Hyper.Internal.Managers
390
391
  }
391
392
  }
392
393
 
393
- yield return new WaitForSecondsRealtime(2f);
394
+ yield return new WaitForSecondsRealtime(1.5f);
394
395
 
395
396
  _sendGameResumedCoroutine = null;
396
397
  }
@@ -529,6 +530,12 @@ namespace Hyper.Internal.Managers
529
530
  _eventManager?.InvokeWebSocketScoreSubmitted(_lastScoreData);
530
531
  }
531
532
 
533
+ if (_isFinalScoreSubmission)
534
+ {
535
+ _finalScoreSubmitted = true;
536
+ _isFinalScoreSubmission = false;
537
+ }
538
+
532
539
  TryUpdateCSRFToken(message);
533
540
  }
534
541
 
@@ -621,22 +628,22 @@ namespace Hyper.Internal.Managers
621
628
 
622
629
  #endregion
623
630
 
624
- #region Score Submission (HTTPS)
631
+ #region Final Score Submission
625
632
 
626
- private Coroutine _endGameCoroutine;
633
+ private Coroutine _finalScoreSubmissionCoroutine;
627
634
 
628
635
  public void SubmitScore()
629
636
  {
630
- if (_endGameCoroutine != null)
637
+ if (_finalScoreSubmissionCoroutine != null)
631
638
  {
632
639
  HyperDebug.LogError("Score submission already in progress");
633
640
  return;
634
641
  }
635
642
 
636
643
  #if UNITY_WEBGL && !UNITY_EDITOR
637
- _endGameCoroutine = StartCoroutine(SubmitScoreCoroutine());
644
+ _finalScoreSubmissionCoroutine = StartCoroutine(FinalScoreSubmissionCoroutine());
638
645
  #else
639
- _endGameCoroutine = StartCoroutine(SubmitScoreCoroutineDemo());
646
+ _finalScoreSubmissionCoroutine = StartCoroutine(FinalScoreSubmissionCoroutineDemo());
640
647
  #endif
641
648
  }
642
649
 
@@ -649,27 +656,34 @@ namespace Hyper.Internal.Managers
649
656
  return;
650
657
  }
651
658
 
652
- if (_endGameCoroutine != null)
659
+ if (_finalScoreSubmissionCoroutine != null)
653
660
  {
654
- StopCoroutine(_endGameCoroutine);
661
+ StopCoroutine(_finalScoreSubmissionCoroutine);
655
662
  }
656
663
 
657
- _endGameCoroutine = null;
664
+ _finalScoreSubmissionCoroutine = null;
658
665
 
659
666
  #if UNITY_WEBGL && !UNITY_EDITOR
660
- _endGameCoroutine = StartCoroutine(SubmitScoreCoroutine());
667
+ _finalScoreSubmissionCoroutine = StartCoroutine(FinalScoreSubmissionCoroutine());
661
668
  #else
662
- _endGameCoroutine = StartCoroutine(SubmitScoreCoroutineDemo());
669
+ _finalScoreSubmissionCoroutine = StartCoroutine(FinalScoreSubmissionCoroutineDemo());
663
670
  #endif
664
671
  }
665
672
 
666
- private IEnumerator SubmitScoreCoroutine()
673
+ private IEnumerator FinalScoreSubmissionCoroutine()
667
674
  {
668
675
  _gameManager?.GameOverModalComponent?.Init();
669
676
  _currentRetryCount = 0;
670
677
 
671
678
  while (_currentRetryCount < MAX_RETRY_COUNT)
672
679
  {
680
+ if (_hasSessionEnded)
681
+ {
682
+ _gameManager?.ShowRetryTimeExpiredModal();
683
+ _finalScoreSubmissionCoroutine = null;
684
+ yield break;
685
+ }
686
+
673
687
  var finalScoreData = _dataManager?.CurrentScoreData;
674
688
  finalScoreData.isFinal = true;
675
689
 
@@ -698,55 +712,100 @@ namespace Hyper.Internal.Managers
698
712
  yield return _sendGameResumedCoroutine;
699
713
  }
700
714
 
701
- object encryptedObject = JsonConvert.DeserializeObject(encryptedScoreData);
702
- var payload = new { encryptedData = encryptedObject };
703
- string jsonData = JsonConvert.SerializeObject(payload);
715
+ if (!isSocketConnected)
716
+ {
717
+ HyperDebug.LogError("WebSocket not connected - cannot submit final score");
718
+ _currentRetryCount++;
719
+ _gameManager?.GameOverModalComponent?.UpdateAttemptCount(_currentRetryCount, MAX_RETRY_COUNT);
704
720
 
705
- string url = GetServerURL($"sessions/{_cachedSessionId}/scores");
721
+ if (_currentRetryCount < MAX_RETRY_COUNT)
722
+ {
723
+ yield return new WaitForSecondsRealtime(1f);
724
+ }
725
+ continue;
726
+ }
706
727
 
707
- using (UnityWebRequest request = new UnityWebRequest(url, "POST"))
728
+ // Sending final score via WebSocket
729
+ _finalScoreSubmitted = false;
730
+ _isFinalScoreSubmission = true;
731
+ _lastSentBatch = new List<ScoreData> { finalScoreData };
732
+
733
+ bool sendFailed = false;
734
+ try
708
735
  {
709
- byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonData);
710
- request.uploadHandler = new UploadHandlerRaw(bodyRaw);
711
- request.downloadHandler = new DownloadHandlerBuffer();
712
- request.SetRequestHeader("Content-Type", "application/json");
713
- request.SetRequestHeader("x-csrf-token", _csrfToken);
714
- request.timeout = scoreSubmissionTimeout;
736
+ var message = new WebSocketScoreMessage(_cachedSessionId, _csrfToken, encryptedScoreData);
737
+ string json = JsonConvert.SerializeObject(message);
738
+ SendWebSocketMessage(json);
739
+ }
740
+ catch (Exception ex)
741
+ {
742
+ HyperDebug.LogError($"Failed to send final score via WebSocket: {ex.Message}");
743
+ _isFinalScoreSubmission = false;
744
+ sendFailed = true;
745
+ }
715
746
 
716
- yield return request.SendWebRequest();
747
+ if (sendFailed)
748
+ {
749
+ _currentRetryCount++;
750
+ _gameManager?.GameOverModalComponent?.UpdateAttemptCount(_currentRetryCount, MAX_RETRY_COUNT);
717
751
 
718
- if (request.result == UnityWebRequest.Result.Success)
752
+ if (_currentRetryCount < MAX_RETRY_COUNT)
719
753
  {
720
- _gameManager?.GameOverModalComponent?.ScoreHasBeenSubmitted();
721
- // TryUpdateCSRFToken(request.downloadHandler.text);
722
- StopWebSocket();
723
- _endGameCoroutine = null;
724
- yield break;
754
+ yield return new WaitForSecondsRealtime(1f);
725
755
  }
726
- else if (_hasSessionEnded)
756
+ continue;
757
+ }
758
+
759
+ // Waiting for WebSocket response
760
+ float elapsed = 0f;
761
+ float timeout = scoreSubmissionTimeout;
762
+
763
+ while (!_finalScoreSubmitted && elapsed < timeout)
764
+ {
765
+ if (_hasSessionEnded)
727
766
  {
728
767
  _gameManager?.ShowRetryTimeExpiredModal();
729
- _endGameCoroutine = null;
768
+ _isFinalScoreSubmission = false;
769
+ _finalScoreSubmissionCoroutine = null;
730
770
  yield break;
731
771
  }
732
- else
733
- {
734
- _currentRetryCount++;
735
- _gameManager?.GameOverModalComponent?.UpdateAttemptCount(_currentRetryCount, MAX_RETRY_COUNT);
772
+ yield return null;
773
+ elapsed += Time.unscaledDeltaTime;
774
+ }
736
775
 
737
- if (_currentRetryCount < MAX_RETRY_COUNT)
738
- {
739
- yield return new WaitForSecondsRealtime(1f);
740
- }
776
+ if (_finalScoreSubmitted)
777
+ {
778
+ _gameManager?.GameOverModalComponent?.ScoreHasBeenSubmitted();
779
+ StopWebSocket();
780
+ _finalScoreSubmissionCoroutine = null;
781
+ yield break;
782
+ }
783
+ else if (_hasSessionEnded)
784
+ {
785
+ _gameManager?.ShowRetryTimeExpiredModal();
786
+ _isFinalScoreSubmission = false;
787
+ _finalScoreSubmissionCoroutine = null;
788
+ yield break;
789
+ }
790
+ else
791
+ {
792
+ _isFinalScoreSubmission = false;
793
+ _currentRetryCount++;
794
+ _gameManager?.GameOverModalComponent?.UpdateAttemptCount(_currentRetryCount, MAX_RETRY_COUNT);
795
+
796
+ if (_currentRetryCount < MAX_RETRY_COUNT)
797
+ {
798
+ yield return new WaitForSecondsRealtime(1f);
741
799
  }
742
800
  }
743
801
  }
744
802
 
803
+ _isFinalScoreSubmission = false;
745
804
  _gameManager?.GameOverModalComponent?.AllAttemptsHaveFailed();
746
- _endGameCoroutine = null;
805
+ _finalScoreSubmissionCoroutine = null;
747
806
  }
748
807
 
749
- private IEnumerator SubmitScoreCoroutineDemo()
808
+ private IEnumerator FinalScoreSubmissionCoroutineDemo()
750
809
  {
751
810
  if (_dataManager == null) _dataManager = HyperRuntime.DataManager;
752
811
  if (_eventManager == null) _eventManager = HyperRuntime.EventManager;
@@ -761,7 +820,7 @@ namespace Hyper.Internal.Managers
761
820
 
762
821
  _gameManager.GameOverModalComponent.ScoreHasBeenSubmitted();
763
822
  StopWebSocket();
764
- _endGameCoroutine = null;
823
+ _finalScoreSubmissionCoroutine = null;
765
824
  }
766
825
 
767
826
  #endregion
@@ -772,6 +831,8 @@ namespace Hyper.Internal.Managers
772
831
  private List<ScoreData> _lastSentBatch = new List<ScoreData>();
773
832
  private ScoreData _lastScoreData;
774
833
  private readonly WaitForSeconds _scoreSendInterval = new WaitForSeconds(1f);
834
+ private bool _isFinalScoreSubmission;
835
+ private bool _finalScoreSubmitted;
775
836
 
776
837
  public void StartSendingScores()
777
838
  {
@@ -45,6 +45,8 @@ namespace Hyper.Internal.Managers
45
45
  internal event Action OnTutorialFetchFailed;
46
46
  internal event Action OnTutorialDoesNotExist;
47
47
  internal event Action<ScoreData> OnLastSubmittedScoreReceived;
48
+ internal event Action OnTimeScaleFrozen; // Fired when Time.timeScale becomes 0
49
+ internal event Action OnTimeScaleResumed; // Fired when Time.timeScale becomes 1 (from any value)
48
50
 
49
51
  #endregion
50
52
 
@@ -68,6 +70,8 @@ namespace Hyper.Internal.Managers
68
70
  internal void InvokeTutorialFetchFailedEvent() => OnTutorialFetchFailed?.Invoke();
69
71
  internal void InvokeTutorialNotExistsEvent() => OnTutorialDoesNotExist?.Invoke();
70
72
  internal void InvokeWebSocketScoreSubmitted(ScoreData scoreData) => OnLastSubmittedScoreReceived?.Invoke(scoreData);
73
+ internal void InvokeTimeScaleFrozenEvent() => OnTimeScaleFrozen?.Invoke();
74
+ internal void InvokeTimeScaleResumedEvent() => OnTimeScaleResumed?.Invoke();
71
75
 
72
76
  #endregion
73
77
  }
@@ -158,12 +158,6 @@ namespace Hyper.Internal.Managers
158
158
  {
159
159
  if (!_hasGameStarted || _isPaused || _hasGameEnded) return;
160
160
 
161
- if (_backendManager.isSocketConnected)
162
- {
163
- _dataManager.StopCapturingScores();
164
- _backendManager.StopSendingScores();
165
- }
166
-
167
161
  _isPaused = true;
168
162
  _isFrozenBeforePause = Time.timeScale == 0;
169
163
  Time.timeScale = 0;
@@ -177,11 +171,6 @@ namespace Hyper.Internal.Managers
177
171
 
178
172
  internal void ResumeGame()
179
173
  {
180
- if (_backendManager.isSocketConnected)
181
- {
182
- _backendManager.SendGameResumed();
183
- }
184
-
185
174
  _isPaused = false;
186
175
 
187
176
  if (!_isFrozenBeforePause)
@@ -212,9 +201,37 @@ namespace Hyper.Internal.Managers
212
201
  {
213
202
  PauseGame();
214
203
  }
215
- else if (!shouldPause && _isPaused)
204
+ }
205
+
206
+ void Update()
207
+ {
208
+ float currentTimeScale = Time.timeScale;
209
+ if (currentTimeScale != _previousTimeScale)
216
210
  {
217
- // ResumeGame();
211
+ // detect intentional game-freeze states
212
+ if (currentTimeScale == 0f && _previousTimeScale != 0f)
213
+ {
214
+ _eventManager.InvokeTimeScaleFrozenEvent();
215
+ HyperDebug.Log("Time scale frozen event invoked");
216
+
217
+ if (_backendManager.isSocketConnected)
218
+ {
219
+ _dataManager.StopCapturingScores();
220
+ _backendManager.StopSendingScores();
221
+ }
222
+ }
223
+ else if (currentTimeScale == 1f && _previousTimeScale != 1f)
224
+ {
225
+ _eventManager.InvokeTimeScaleResumedEvent();
226
+ HyperDebug.Log("Time scale resumed event invoked");
227
+
228
+ if (_backendManager.isSocketConnected && !_hasGameEnded && _hasGameStarted)
229
+ {
230
+ _backendManager.SendGameResumed();
231
+ }
232
+ }
233
+
234
+ _previousTimeScale = currentTimeScale;
218
235
  }
219
236
  }
220
237
 
@@ -459,6 +476,8 @@ namespace Hyper.Internal.Managers
459
476
 
460
477
  internal void ShowGameOverModal()
461
478
  {
479
+ HidePauseModals();
480
+
462
481
  if (IsBattleMode)
463
482
  {
464
483
  EnsureBattleGameOverModal();
@@ -469,7 +488,7 @@ namespace Hyper.Internal.Managers
469
488
  EnsurePracticeGameOverModal();
470
489
  _practiceGameOverModal.SetActive(true);
471
490
  }
472
-
491
+
473
492
  SetBlockerActive(true);
474
493
  }
475
494
 
@@ -558,6 +577,7 @@ namespace Hyper.Internal.Managers
558
577
  private bool _hasGameEnded;
559
578
  private bool _isFrozenBeforePause;
560
579
  private bool _isPortrait;
580
+ private float _previousTimeScale = 1f;
561
581
 
562
582
  #endregion
563
583
 
@@ -769,6 +789,7 @@ namespace Hyper.Internal.Managers
769
789
  private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
770
790
  {
771
791
  Time.timeScale = 1;
792
+ _previousTimeScale = 1f; // Sync tracking on scene load
772
793
  _dataManager.ConfigurePlayerSoundSetting();
773
794
 
774
795
  string menuSceneName = HyperRuntime.GameContent.IsPracticeMenu ?
@@ -808,6 +829,7 @@ namespace Hyper.Internal.Managers
808
829
  _hasGameEnded = false;
809
830
  _isPaused = false;
810
831
  _isFrozenBeforePause = false;
832
+ _previousTimeScale = Time.timeScale; // Sync with actual time scale on scene load
811
833
  }
812
834
 
813
835
  private void InitializeSceneUI()
@@ -83,7 +83,7 @@ namespace Hyper.Internal
83
83
 
84
84
  // Animate to original position
85
85
  rectTransform.DOAnchorPosY(originalAnchoredPosition.y, 0.5f)
86
- .SetEase(Animation.HyperTween.Ease.OutQuad)
86
+ .SetEase(HyperTween.Ease.OutQuad)
87
87
  .SetUpdate(true);
88
88
  }
89
89
 
@@ -103,7 +103,7 @@ namespace Hyper.Internal
103
103
 
104
104
  // Animate to off-screen position
105
105
  rectTransform.DOAnchorPosY(offScreenY, 0.5f)
106
- .SetEase(Animation.HyperTween.Ease.InQuad)
106
+ .SetEase(HyperTween.Ease.InQuad)
107
107
  .SetUpdate(true)
108
108
  .OnComplete(() =>
109
109
  {
@@ -5,6 +5,10 @@ using TMPro;
5
5
  using UnityEngine;
6
6
  using UnityEngine.UI;
7
7
 
8
+ #if ENABLE_INPUT_SYSTEM
9
+ using UnityEngine.InputSystem;
10
+ #endif
11
+
8
12
  namespace Hyper.Internal
9
13
  {
10
14
  internal class StartingInstructionModal : MonoBehaviour
@@ -93,6 +97,8 @@ namespace Hyper.Internal
93
97
  {
94
98
  bool tapDetected = false;
95
99
 
100
+ #if ENABLE_LEGACY_INPUT_MANAGER
101
+ // Old Input System
96
102
  // Check mouse input (works in editor and desktop)
97
103
  if (Input.GetMouseButtonDown(0))
98
104
  {
@@ -108,6 +114,20 @@ namespace Hyper.Internal
108
114
  tapDetected = true;
109
115
  }
110
116
  }
117
+ #elif ENABLE_INPUT_SYSTEM
118
+ // New Input System
119
+ // Check mouse input (works in editor and desktop)
120
+ if (Mouse.current != null && Mouse.current.leftButton.wasPressedThisFrame)
121
+ {
122
+ tapDetected = true;
123
+ }
124
+
125
+ // Check touch input (works on mobile and WebGL)
126
+ if (Touchscreen.current != null && Touchscreen.current.primaryTouch.press.wasPressedThisFrame)
127
+ {
128
+ tapDetected = true;
129
+ }
130
+ #endif
111
131
 
112
132
  if (tapDetected)
113
133
  {
@@ -123,6 +143,8 @@ namespace Hyper.Internal
123
143
  bool swipeDetected = false;
124
144
  Vector2 currentPosition = Vector2.zero;
125
145
 
146
+ #if ENABLE_LEGACY_INPUT_MANAGER
147
+ // Old Input System
126
148
  // Check mouse input (works in editor and desktop)
127
149
  if (Input.GetMouseButtonDown(0))
128
150
  {
@@ -171,6 +193,60 @@ namespace Hyper.Internal
171
193
  _isTrackingSwipe = false;
172
194
  }
173
195
  }
196
+ #elif ENABLE_INPUT_SYSTEM
197
+ // New Input System
198
+ // Check mouse input (works in editor and desktop)
199
+ if (Mouse.current != null)
200
+ {
201
+ if (Mouse.current.leftButton.wasPressedThisFrame)
202
+ {
203
+ _swipeStartPosition = Mouse.current.position.ReadValue();
204
+ _isTrackingSwipe = true;
205
+ }
206
+ else if (Mouse.current.leftButton.isPressed && _isTrackingSwipe)
207
+ {
208
+ currentPosition = Mouse.current.position.ReadValue();
209
+ Vector2 delta = currentPosition - _swipeStartPosition;
210
+
211
+ if (IsSwipeDirectionValid(delta))
212
+ {
213
+ swipeDetected = true;
214
+ _isTrackingSwipe = false;
215
+ }
216
+ }
217
+ else if (Mouse.current.leftButton.wasReleasedThisFrame)
218
+ {
219
+ _isTrackingSwipe = false;
220
+ }
221
+ }
222
+
223
+ // Check touch input (works on mobile and WebGL)
224
+ if (Touchscreen.current != null)
225
+ {
226
+ var touch = Touchscreen.current.primaryTouch;
227
+
228
+ if (touch.press.wasPressedThisFrame)
229
+ {
230
+ _swipeStartPosition = touch.position.ReadValue();
231
+ _isTrackingSwipe = true;
232
+ }
233
+ else if (touch.press.isPressed && _isTrackingSwipe)
234
+ {
235
+ currentPosition = touch.position.ReadValue();
236
+ Vector2 delta = currentPosition - _swipeStartPosition;
237
+
238
+ if (IsSwipeDirectionValid(delta))
239
+ {
240
+ swipeDetected = true;
241
+ _isTrackingSwipe = false;
242
+ }
243
+ }
244
+ else if (touch.press.wasReleasedThisFrame)
245
+ {
246
+ _isTrackingSwipe = false;
247
+ }
248
+ }
249
+ #endif
174
250
 
175
251
  if (swipeDetected)
176
252
  {
@@ -87,8 +87,8 @@ Material:
87
87
  - _StencilOp: 0
88
88
  - _StencilReadMask: 255
89
89
  - _StencilWriteMask: 255
90
- - _TextureHeight: 256
91
- - _TextureWidth: 256
90
+ - _TextureHeight: 512
91
+ - _TextureWidth: 512
92
92
  - _UnderlayDilate: 1
93
93
  - _UnderlayOffsetX: 0
94
94
  - _UnderlayOffsetY: -0.85
@@ -87,8 +87,8 @@ Material:
87
87
  - _StencilOp: 0
88
88
  - _StencilReadMask: 255
89
89
  - _StencilWriteMask: 255
90
- - _TextureHeight: 256
91
- - _TextureWidth: 256
90
+ - _TextureHeight: 512
91
+ - _TextureWidth: 512
92
92
  - _UnderlayDilate: 0.05
93
93
  - _UnderlayOffsetX: 0
94
94
  - _UnderlayOffsetY: -1