Initial commit: Unity WordConnect project
This commit is contained in:
@ -0,0 +1,27 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
|
||||
namespace WordsToolkit.Scripts.System
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class CustomSerializeTypePropertyAttribute : SerializeTypePropertyAttribute
|
||||
{
|
||||
public Type Description { get; }
|
||||
|
||||
public CustomSerializeTypePropertyAttribute(Type description)
|
||||
{
|
||||
Description = description;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e66ea3b1ddb14e0eadf46ab45a15b166
|
||||
timeCreated: 1725704837
|
||||
36
Assets/WordConnectGameToolkit/Scripts/System/Event.cs
Normal file
36
Assets/WordConnectGameToolkit/Scripts/System/Event.cs
Normal file
@ -0,0 +1,36 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
|
||||
namespace WordsToolkit.Scripts.System
|
||||
{
|
||||
public class Event<T>
|
||||
{
|
||||
private event Action<T> _event;
|
||||
|
||||
public void Subscribe(Action<T> subscriber)
|
||||
{
|
||||
_event += subscriber;
|
||||
}
|
||||
|
||||
public void Unsubscribe(Action<T> subscriber)
|
||||
{
|
||||
_event -= subscriber;
|
||||
}
|
||||
|
||||
public void Invoke(T arg)
|
||||
{
|
||||
_event?.Invoke(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4b49765164a41378a96bfa5418a423e
|
||||
timeCreated: 1725698172
|
||||
89
Assets/WordConnectGameToolkit/Scripts/System/EventManager.cs
Normal file
89
Assets/WordConnectGameToolkit/Scripts/System/EventManager.cs
Normal file
@ -0,0 +1,89 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using WordsToolkit.Scripts.Enums;
|
||||
|
||||
namespace WordsToolkit.Scripts.System
|
||||
{
|
||||
public static class EventManager
|
||||
{
|
||||
// A dictionary to hold all events
|
||||
private static readonly Dictionary<EGameEvent, object> events = new();
|
||||
|
||||
public static Event<T> GetEvent<T>(EGameEvent eventName)
|
||||
{
|
||||
if (events.TryGetValue(eventName, out var e) && e is Event<T> typedEvent)
|
||||
{
|
||||
return typedEvent;
|
||||
}
|
||||
|
||||
var newEvent = new Event<T>();
|
||||
events[eventName] = newEvent;
|
||||
return newEvent;
|
||||
}
|
||||
|
||||
// no generic event
|
||||
public static Event GetEvent(EGameEvent eventName)
|
||||
{
|
||||
if (events.TryGetValue(eventName, out var e) && e is Event typedEvent)
|
||||
{
|
||||
return typedEvent;
|
||||
}
|
||||
|
||||
var newEvent = new Event();
|
||||
events[eventName] = newEvent;
|
||||
return newEvent;
|
||||
}
|
||||
|
||||
public static Dictionary<EGameEvent, object> GetSubscribedEvents()
|
||||
{
|
||||
return events;
|
||||
}
|
||||
|
||||
public static Action<EGameState> OnGameStateChanged;
|
||||
private static EGameState gameStatus;
|
||||
|
||||
public static EGameState GameStatus
|
||||
{
|
||||
get => gameStatus;
|
||||
set
|
||||
{
|
||||
if (gameStatus == value)
|
||||
return;
|
||||
gameStatus = value;
|
||||
OnGameStateChanged?.Invoke(gameStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Event
|
||||
{
|
||||
private event Action _event;
|
||||
|
||||
public void Subscribe(Action subscriber)
|
||||
{
|
||||
_event += subscriber;
|
||||
}
|
||||
|
||||
public void Unsubscribe(Action subscriber)
|
||||
{
|
||||
_event -= subscriber;
|
||||
}
|
||||
|
||||
public void Invoke()
|
||||
{
|
||||
_event?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8edb0b4c22b94346afdc11a697e6b4d2
|
||||
timeCreated: 1725698126
|
||||
58
Assets/WordConnectGameToolkit/Scripts/System/FPSCounter.cs
Normal file
58
Assets/WordConnectGameToolkit/Scripts/System/FPSCounter.cs
Normal file
@ -0,0 +1,58 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace WordsToolkit.Scripts.System
|
||||
{
|
||||
public class FPSCounter : MonoBehaviour
|
||||
{
|
||||
private readonly float updateInterval = 0.5f;
|
||||
private float accum;
|
||||
private int frames;
|
||||
private float timeLeft;
|
||||
private float fps;
|
||||
|
||||
private readonly GUIStyle textStyle = new();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
timeLeft = updateInterval;
|
||||
|
||||
// Set up the GUI style
|
||||
textStyle.fontStyle = FontStyle.Bold;
|
||||
textStyle.normal.textColor = Color.white;
|
||||
textStyle.fontSize = 24; // Adjust this value to change the text size
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
timeLeft -= Time.deltaTime;
|
||||
accum += Time.timeScale / Time.deltaTime;
|
||||
frames++;
|
||||
|
||||
if (timeLeft <= 0f)
|
||||
{
|
||||
fps = accum / frames;
|
||||
timeLeft = updateInterval;
|
||||
accum = 0f;
|
||||
frames = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
// Display FPS in the top-left corner
|
||||
UnityEngine.GUI.Label(new Rect(10, 10, 100, 30), "FPS: " + fps.ToString("F2"), textStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01dcce784a6940748924d2909c70ad22
|
||||
timeCreated: 1726665435
|
||||
162
Assets/WordConnectGameToolkit/Scripts/System/GameDataManager.cs
Normal file
162
Assets/WordConnectGameToolkit/Scripts/System/GameDataManager.cs
Normal file
@ -0,0 +1,162 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using WordsToolkit.Scripts.Data;
|
||||
using WordsToolkit.Scripts.Enums;
|
||||
using WordsToolkit.Scripts.Levels;
|
||||
|
||||
|
||||
namespace WordsToolkit.Scripts.System
|
||||
{
|
||||
public static class GameDataManager
|
||||
{
|
||||
// Note: We're removing the static _level cache to avoid state issues
|
||||
|
||||
public static bool isTestPlay = false;
|
||||
|
||||
// Track if we're in test mode and which level is being tested
|
||||
private static Level _testLevel;
|
||||
|
||||
public static void ClearPlayerProgress()
|
||||
{
|
||||
PlayerPrefs.DeleteKey("Level");
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
|
||||
public static void ClearALlData()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// clear variables ResourceObject from Resources/Variables
|
||||
var resourceObjects = Resources.LoadAll<ResourceObject>("Variables");
|
||||
foreach (var resourceObject in resourceObjects)
|
||||
{
|
||||
resourceObject.Set(0);
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
PlayerPrefs.DeleteAll();
|
||||
PlayerPrefs.DeleteAll();
|
||||
PlayerPrefs.Save();
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void UnlockLevel(int currentLevel)
|
||||
{
|
||||
isTestPlay = false;
|
||||
// Store the level number in PlayerPrefs
|
||||
PlayerPrefs.SetInt("Level", currentLevel);
|
||||
PlayerPrefs.Save();
|
||||
|
||||
// No need to load and cache the level here
|
||||
}
|
||||
|
||||
public static int GetLevelNum()
|
||||
{
|
||||
// Always get the current level from PlayerPrefs
|
||||
return PlayerPrefs.GetInt("Level", 1);
|
||||
}
|
||||
|
||||
public static Level GetLevel()
|
||||
{
|
||||
// For test play, return the test level if it exists
|
||||
if (isTestPlay && _testLevel != null)
|
||||
{
|
||||
return _testLevel;
|
||||
}
|
||||
|
||||
// Get current level number from PlayerPrefs
|
||||
int currentLevelNum = GetLevelNum();
|
||||
|
||||
// Load the level directly from Resources
|
||||
Level level = Resources.LoadAll<Level>("Levels").FirstOrDefault(i=>i.number == currentLevelNum);
|
||||
|
||||
// Debug level loading
|
||||
if (level == null)
|
||||
{
|
||||
Debug.LogWarning($"Level 'Levels/level_{currentLevelNum}' not found");
|
||||
}
|
||||
|
||||
// If level is null, LevelManager's fallback logic will handle finding a previous level
|
||||
return level;
|
||||
}
|
||||
|
||||
public static void SetLevel(Level level)
|
||||
{
|
||||
if (isTestPlay)
|
||||
{
|
||||
// In test mode, we store the level reference
|
||||
_testLevel = level;
|
||||
return;
|
||||
}
|
||||
|
||||
// In normal mode, find the level number and store it in PlayerPrefs
|
||||
if (level != null)
|
||||
{
|
||||
// Try to find the level's index in the Resources folder
|
||||
Level[] allLevels = Resources.LoadAll<Level>("Levels").OrderBy(i => i.number).ToArray();
|
||||
for (int i = 0; i < allLevels.Length; i++)
|
||||
{
|
||||
if (allLevels[i] == level)
|
||||
{
|
||||
// Found the level, store its index+1 as the level number
|
||||
SetLevelNum(i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static EGameMode GetGameMode()
|
||||
{
|
||||
return (EGameMode)PlayerPrefs.GetInt("GameMode");
|
||||
}
|
||||
|
||||
public static void SetGameMode(EGameMode gameMode)
|
||||
{
|
||||
PlayerPrefs.SetInt("GameMode", (int)gameMode);
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
|
||||
public static void SetAllLevelsCompleted()
|
||||
{
|
||||
var levels = Resources.LoadAll<Level>("Levels").Length;
|
||||
PlayerPrefs.SetInt("Level", levels);
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
|
||||
internal static bool HasMoreLevels()
|
||||
{
|
||||
int currentLevel = GetLevelNum();
|
||||
int totalLevels = Resources.LoadAll<Level>("Levels").Length;
|
||||
return currentLevel < totalLevels;
|
||||
}
|
||||
|
||||
public static void SetLevelNum(int stateCurrentLevel)
|
||||
{
|
||||
// Store the level in PlayerPrefs immediately
|
||||
PlayerPrefs.SetInt("Level", stateCurrentLevel);
|
||||
PlayerPrefs.Save();
|
||||
|
||||
// No need to clear cached level since we don't cache it anymore
|
||||
}
|
||||
|
||||
public static void CleanupAfterTest()
|
||||
{
|
||||
isTestPlay = false;
|
||||
_testLevel = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ce0e28edfd14522abd162492d80e2a6
|
||||
timeCreated: 1725699092
|
||||
292
Assets/WordConnectGameToolkit/Scripts/System/GameManager.cs
Normal file
292
Assets/WordConnectGameToolkit/Scripts/System/GameManager.cs
Normal file
@ -0,0 +1,292 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using DG.Tweening;
|
||||
using UnityEngine;
|
||||
using VContainer;
|
||||
using VContainer.Unity;
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
using Awaitable = UnityEngine.Awaitable;
|
||||
#else
|
||||
using Awaitable = System.Threading.Tasks.Task;
|
||||
#endif
|
||||
using WordsToolkit.Scripts.Audio;
|
||||
using WordsToolkit.Scripts.Enums;
|
||||
using WordsToolkit.Scripts.Gameplay.Managers;
|
||||
using WordsToolkit.Scripts.GUI;
|
||||
using WordsToolkit.Scripts.GUI.Buttons;
|
||||
using WordsToolkit.Scripts.Popups;
|
||||
using WordsToolkit.Scripts.Popups.Daily;
|
||||
using WordsToolkit.Scripts.Services;
|
||||
using WordsToolkit.Scripts.Services.IAP;
|
||||
using WordsToolkit.Scripts.Settings;
|
||||
using WordsToolkit.Scripts.Utils;
|
||||
using ResourceManager = WordsToolkit.Scripts.Data.ResourceManager;
|
||||
|
||||
namespace WordsToolkit.Scripts.System
|
||||
{
|
||||
public class GameManager : IInitializable, IDisposable, IAsyncStartable
|
||||
{
|
||||
public Action<string> purchaseSucceded;
|
||||
|
||||
private (string id, ProductTypeWrapper.ProductType productType)[] products;
|
||||
private int lastBackgroundIndex = -1;
|
||||
private bool isTutorialMode;
|
||||
private MainMenu mainMenu;
|
||||
public Action<bool, List<string>> OnPurchasesRestored;
|
||||
public ProductID noAdsProduct;
|
||||
public string language = "en";
|
||||
public int Score { get=> resourceManager.GetResource("Score").GetValue(); set => resourceManager.GetResource("Score").Set(value); }
|
||||
|
||||
private readonly StateManager stateManager;
|
||||
private readonly SceneLoader sceneLoader;
|
||||
private readonly MenuManager menuManager;
|
||||
private readonly GameSettings gameSettings;
|
||||
private readonly DailyBonusSettings dailyBonusSettings;
|
||||
private readonly IIAPManager iapManager;
|
||||
private readonly IInitializeGamingServices gamingServices;
|
||||
private readonly ResourceManager resourceManager;
|
||||
private readonly ILanguageService languageService;
|
||||
|
||||
public GameManager(
|
||||
StateManager stateManager,
|
||||
SceneLoader sceneLoader,
|
||||
MenuManager menuManager,
|
||||
GameSettings gameSettings,
|
||||
DailyBonusSettings dailyBonusSettings,
|
||||
IIAPManager iapManager,
|
||||
IInitializeGamingServices gamingServices,
|
||||
ResourceManager resourceManager,
|
||||
ILanguageService languageService)
|
||||
{
|
||||
this.stateManager = stateManager;
|
||||
this.sceneLoader = sceneLoader;
|
||||
this.menuManager = menuManager;
|
||||
this.gameSettings = gameSettings;
|
||||
this.dailyBonusSettings = dailyBonusSettings;
|
||||
this.iapManager = iapManager;
|
||||
this.gamingServices = gamingServices;
|
||||
this.resourceManager = resourceManager;
|
||||
this.languageService = languageService;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
mainMenu = menuManager.GetMainMenu();
|
||||
if (mainMenu != null)
|
||||
{
|
||||
CustomButton.BlockInput(CheckDailyBonusConditions());
|
||||
mainMenu.OnAnimationEnded += OnMainMenuAnimationEnded;
|
||||
}
|
||||
else
|
||||
{
|
||||
CustomButton.BlockInput(false);
|
||||
}
|
||||
|
||||
// Get current language from LanguageService (already initialized as EntryPoint)
|
||||
var langName = languageService.GetCurrentLanguageCode();
|
||||
language = langName;
|
||||
EventManager.GetEvent<string>(EGameEvent.LanguageChanged).Subscribe(LanguageChanged);
|
||||
iapManager.SubscribeToPurchaseEvent(PurchaseSucceeded);
|
||||
|
||||
stateManager.OnStateChanged.AddListener((state) => {
|
||||
if (state != EScreenStates.MainMenu)
|
||||
CustomButton.BlockInput(false);
|
||||
});
|
||||
|
||||
if (!IsTutorialShown() && !GameDataManager.isTestPlay)
|
||||
{
|
||||
SetTutorialMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void LanguageChanged(string obj)
|
||||
{
|
||||
language = obj;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
EventManager.GetEvent<string>(EGameEvent.LanguageChanged).Unsubscribe(LanguageChanged);
|
||||
iapManager.UnsubscribeFromPurchaseEvent(PurchaseSucceeded);
|
||||
if (mainMenu != null)
|
||||
{
|
||||
mainMenu.OnAnimationEnded -= OnMainMenuAnimationEnded;
|
||||
}
|
||||
if (GameDataManager.isTestPlay)
|
||||
{
|
||||
GameDataManager.CleanupAfterTest();
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsTutorialShown()
|
||||
{
|
||||
return PlayerPrefs.GetInt("tutorial", 0) == 1;
|
||||
}
|
||||
|
||||
public void SetTutorialCompleted()
|
||||
{
|
||||
PlayerPrefs.SetInt("tutorial", 1);
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
|
||||
async Awaitable IAsyncStartable.StartAsync(CancellationToken cancellation)
|
||||
{
|
||||
Application.targetFrameRate = 60;
|
||||
DOTween.SetTweensCapacity(1250, 512);
|
||||
|
||||
if (gameSettings.enableInApps) {
|
||||
products = Resources.LoadAll<ProductID>("ProductIDs")
|
||||
.Select(p => (p.ID, p.productType))
|
||||
.ToArray();
|
||||
|
||||
// Initialize gaming services
|
||||
await gamingServices.Initialize(
|
||||
OnInitializeSuccess,
|
||||
OnInitializeError
|
||||
);
|
||||
// Initialize IAP directly if InitializeGamingServices is not used
|
||||
await iapManager.InitializePurchasing(products);
|
||||
}
|
||||
|
||||
|
||||
if (GameDataManager.isTestPlay)
|
||||
{
|
||||
GameDataManager.SetLevel(GameDataManager.GetLevel());
|
||||
}
|
||||
}
|
||||
|
||||
private void OnInitializeSuccess()
|
||||
{
|
||||
Debug.Log("Gaming services initialized successfully");
|
||||
}
|
||||
|
||||
private void OnInitializeError(string errorMessage)
|
||||
{
|
||||
Debug.LogError($"Failed to initialize gaming services: {errorMessage}");
|
||||
}
|
||||
|
||||
private void HandleDailyBonus()
|
||||
{
|
||||
if (stateManager.CurrentState != EScreenStates.MainMenu || !dailyBonusSettings.dailyBonusEnabled || !gameSettings.enableInApps || !CheckDailyBonusConditions())
|
||||
{
|
||||
CustomButton.BlockInput(false);
|
||||
return;
|
||||
}
|
||||
|
||||
menuManager.ShowPopup<DailyBonus>();
|
||||
DOVirtual.DelayedCall(0.5f, () => { CustomButton.BlockInput(false); });
|
||||
}
|
||||
|
||||
private bool CheckDailyBonusConditions()
|
||||
{
|
||||
var today = DateTime.Today;
|
||||
var lastRewardDate = DateTime.Parse(PlayerPrefs.GetString("DailyBonusDay", today.Subtract(TimeSpan.FromDays(1)).ToString(CultureInfo.CurrentCulture)));
|
||||
return today.Date > lastRewardDate.Date && dailyBonusSettings.dailyBonusEnabled;
|
||||
}
|
||||
|
||||
public void RestartLevel()
|
||||
{
|
||||
DOTween.KillAll();
|
||||
menuManager.CloseAllPopups();
|
||||
EventManager.GetEvent(EGameEvent.RestartLevel).Invoke();
|
||||
}
|
||||
|
||||
public void RemoveAds()
|
||||
{
|
||||
if (gameSettings.enableAds) {
|
||||
menuManager.ShowPopup<NoAds>();
|
||||
}
|
||||
}
|
||||
|
||||
public void MainMenu()
|
||||
{
|
||||
DOTween.KillAll();
|
||||
sceneLoader.GoMain();
|
||||
}
|
||||
|
||||
public void OpenGame()
|
||||
{
|
||||
sceneLoader.StartGameScene();
|
||||
}
|
||||
|
||||
public void PurchaseSucceeded(string id)
|
||||
{
|
||||
EventManager.GetEvent<string>(EGameEvent.PurchaseSucceeded).Invoke(id);
|
||||
}
|
||||
|
||||
public void SetGameMode(EGameMode gameMode)
|
||||
{
|
||||
GameDataManager.SetGameMode(gameMode);
|
||||
}
|
||||
|
||||
private EGameMode GetGameMode()
|
||||
{
|
||||
return GameDataManager.GetGameMode();
|
||||
}
|
||||
|
||||
public int GetLastBackgroundIndex()
|
||||
{
|
||||
return lastBackgroundIndex;
|
||||
}
|
||||
|
||||
public void SetLastBackgroundIndex(int index)
|
||||
{
|
||||
lastBackgroundIndex = index;
|
||||
}
|
||||
|
||||
public void NextLevel()
|
||||
{
|
||||
// Get current level and increment it
|
||||
int currentLevel = GameDataManager.GetLevelNum();
|
||||
GameDataManager.SetLevelNum(currentLevel + 1);
|
||||
OpenGame();
|
||||
RestartLevel();
|
||||
}
|
||||
|
||||
public void SetTutorialMode(bool tutorial)
|
||||
{
|
||||
Debug.Log("Tutorial mode set to " + tutorial);
|
||||
isTutorialMode = tutorial;
|
||||
}
|
||||
|
||||
public bool IsTutorialMode()
|
||||
{
|
||||
return isTutorialMode;
|
||||
}
|
||||
|
||||
private void OnMainMenuAnimationEnded()
|
||||
{
|
||||
HandleDailyBonus();
|
||||
}
|
||||
|
||||
internal void RestorePurchases(Action<bool, List<string>> OnPurchasesRestored)
|
||||
{
|
||||
if (!gameSettings.enableInApps) return;
|
||||
|
||||
this.OnPurchasesRestored = OnPurchasesRestored;
|
||||
iapManager.RestorePurchases(OnPurchasesRestored);
|
||||
}
|
||||
|
||||
public bool IsPurchased(string id)
|
||||
{
|
||||
if (!gameSettings.enableInApps) return false;
|
||||
return iapManager.IsProductPurchased(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ed7b1949c0148d69891d98d5bf2e85f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: -20
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3
Assets/WordConnectGameToolkit/Scripts/System/Haptic.meta
Normal file
3
Assets/WordConnectGameToolkit/Scripts/System/Haptic.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4fd5e5bff174179b5a5cd2603914f8a
|
||||
timeCreated: 1729849601
|
||||
@ -0,0 +1,86 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Android;
|
||||
|
||||
namespace WordsToolkit.Scripts.System.Haptic
|
||||
{
|
||||
public class HapticFeedback : MonoBehaviour
|
||||
{
|
||||
public enum HapticForce
|
||||
{
|
||||
Light,
|
||||
Medium,
|
||||
Heavy
|
||||
}
|
||||
|
||||
private const string VibrationPrefKey = "VibrationLevel";
|
||||
|
||||
#if UNITY_IOS
|
||||
[DllImport("__Internal")]
|
||||
private static extern void _TriggerHapticFeedback(int force);
|
||||
#endif
|
||||
|
||||
private static bool IsSystemSupported()
|
||||
{
|
||||
#if UNITY_IOS
|
||||
return SystemInfo.supportsVibration;
|
||||
#elif UNITY_ANDROID
|
||||
return SystemInfo.supportsVibration && Permission.HasUserAuthorizedPermission("android.permission.VIBRATE");
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
private static bool TryHapticFeedback(HapticForce force)
|
||||
{
|
||||
if (!IsSystemSupported())
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
#if UNITY_IOS
|
||||
_TriggerHapticFeedback((int)force);
|
||||
#elif UNITY_ANDROID
|
||||
long[] pattern = force switch
|
||||
{
|
||||
HapticForce.Light => new long[] { 0, 50 },
|
||||
HapticForce.Medium => new long[] { 0, 100 },
|
||||
HapticForce.Heavy => new long[] { 0, 200 },
|
||||
_ => new long[] { 0, 50 }
|
||||
};
|
||||
Vibration.Vibrate(pattern, -1);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void TriggerHapticFeedback(HapticForce force)
|
||||
{
|
||||
if (!IsVibrationEnabled())
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
private static bool IsVibrationEnabled()
|
||||
{
|
||||
return PlayerPrefs.GetFloat(VibrationPrefKey, 1) > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ad53e4c45a1d42d4bcee63a96caafa5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,36 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace WordsToolkit.Scripts.System.Haptic
|
||||
{
|
||||
public static class Vibration
|
||||
{
|
||||
public static void Vibrate(long[] pattern, int repeat)
|
||||
{
|
||||
if (Application.platform == RuntimePlatform.Android)
|
||||
{
|
||||
using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
|
||||
{
|
||||
using (var currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
|
||||
{
|
||||
using (var vibrator = currentActivity.Call<AndroidJavaObject>("getSystemService", "vibrator"))
|
||||
{
|
||||
vibrator.Call("vibrate", pattern, repeat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 29ec5197bae34b0d9bd40553ecd33494
|
||||
timeCreated: 1729849644
|
||||
@ -0,0 +1,20 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace WordsToolkit.Scripts.System
|
||||
{
|
||||
public class SerializeTypePropertyAttribute : PropertyAttribute
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e24f7ee9a9a49efaee3ca50d3871157
|
||||
timeCreated: 1725704706
|
||||
@ -0,0 +1,47 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace WordsToolkit.Scripts.System
|
||||
{
|
||||
public class SingletonBehaviour<T> : MonoBehaviour where T : SingletonBehaviour<T>
|
||||
{
|
||||
private static T _instance;
|
||||
|
||||
public static T instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = FindObjectOfType<T>();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
private set => _instance = value;
|
||||
}
|
||||
|
||||
public virtual void Awake()
|
||||
{
|
||||
if (instance != null && instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = (T)this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 72690b591b7e4edc8d4887649133671b
|
||||
timeCreated: 1725684407
|
||||
@ -0,0 +1,34 @@
|
||||
// // ©2015 - 2025 Candy Smith
|
||||
// // All rights reserved
|
||||
// // Redistribution of this software is strictly not allowed.
|
||||
// // Copy of this software can be obtained from unity asset store only.
|
||||
// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// // THE SOFTWARE.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace WordsToolkit.Scripts.System
|
||||
{
|
||||
public abstract class SingletonScriptableSettings<T> : ScriptableObject where T : ScriptableObject
|
||||
{
|
||||
private static T _instance;
|
||||
|
||||
public static T instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = Resources.Load<T>("Settings/" + typeof(T).Name);
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9dea19f994814522b6c4a6a6cf51c021
|
||||
timeCreated: 1725684407
|
||||
Reference in New Issue
Block a user