Search Unity

How do I implement this Get Time and Date From Server Script into this DailyReward Script?

Discussion in 'Scripting' started by Zody123, Jul 8, 2020.

  1. Zody123

    Zody123

    Joined:
    Jun 23, 2020
    Posts:
    4
    I am trying to figure out how to implement my TimeManager script into my DailyReward script. My DailyReward script currently rewards players every 24 hours with a daily reward or every 12 hours if they have a special item. The issue with the DailyReward script is if you set the time or date ahead offline, the daily reward will be available early even if the server time is the same. My TimeManager script gets the time and date from a server, which prevents you from setting time and date ahead to get the reward early.
    This is the TimeManager script:

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using UnityEngine;
    4.  
    5. public class TimeManager : MonoBehaviour
    6. {
    7.     /*
    8.     NEED TO FIND A WORKING URL TO GET THE DATE AND TIME
    9.  
    10.     necessary variables to hold all the things we need.
    11.     php url
    12.     timedata, the data we get back
    13.     current time
    14.     current date
    15.     */
    16.  
    17.     public static TimeManager sharedInstance = null;
    18.     private string url = "http://leatonm.net/wp-content/uploads/2017/candlepin/getdate.php"; //This is a placeholder URL. Change URL in final script version.
    19.     private string timeData;
    20.     private string currentTime;
    21.     private string currentDate;
    22.  
    23.     //Make sure there is only one instance of this always.
    24.     private void Awake()
    25.     {
    26.         if (sharedInstance == null)
    27.         {
    28.             sharedInstance = this;
    29.         }
    30.         else if (sharedInstance != this)
    31.         {
    32.             Destroy(gameObject);
    33.         }
    34.         DontDestroyOnLoad(gameObject);
    35.     }
    36.  
    37.     //Time fether coroutine
    38.     public IEnumerator GetTime()
    39.     {
    40.         Debug.Log("==> step 1. Getting info from internet now!");
    41.         //Debug.Log("connecting to php");
    42.         WWW www = new WWW(url);
    43.         yield return www;
    44.         //if (www.error != null) {
    45.         //Debug.Log ("Error");
    46.         //} else {
    47.         //Debug.Log("got the php information");
    48.         //}
    49.         Debug.Log("==> step 2. Got the info from internet!");
    50.         timeData = www.text;
    51.         string[] words = timeData.Split('/');
    52.         //timerTestLabel.text = www.text;
    53.         Debug.Log("The date is : " + words[0]);
    54.         Debug.Log("The time is : " + words[1]);
    55.  
    56.         //setting current time
    57.         currentDate = words[0];
    58.         currentTime = words[1];
    59.     }
    60.  
    61.     //get the current time at startup
    62.     private void Start()
    63.     {
    64.         Debug.Log("==> TimeManager script is Ready.");
    65.         //Debug.Log ("TimeManager script is Ready.");
    66.         StartCoroutine("getTime");
    67.     }
    68.  
    69.     //get the current date - also converting from string to int.
    70.     //where 12-4-2017 is 1242017
    71.  
    72.     public string GetCurrentDateNow()
    73.     {
    74.         return currentDate;
    75.     }
    76.  
    77.     //public int getCurrentDateNow()
    78.     //{
    79.     //string[] words = _currentDate.Split('-');
    80.     //int x = int.Parse(words[0] + words[1] + words[2]);
    81.     //return x;
    82.     //}
    83.  
    84.     //get the current Time
    85.     public string GetCurrentTimeNow()
    86.     {
    87.         return currentTime;
    88.     }
    89. }
    This is the DailyReward script:
    Code (CSharp):
    1.  
    2. using System;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class DailyReward : MonoBehaviour {
    7.     public static DailyReward DailyRwd;
    8.     private Text chestTimer;
    9.     private float msToWait = 86400000.0f;
    10.     private Button chestButton;
    11.     private ulong lastChestOpen;
    12.  
    13.     void Start(){
    14.         if (DailyRwd == null)
    15.         {
    16.             DailyRwd = this;
    17.         }
    18.  
    19.         chestTimer = GetComponentInChildren<Text>();
    20.         chestButton = GetComponent<Button>();
    21.         lastChestOpen = ulong.Parse(PlayerPrefs.GetString("LastChestOpen"));
    22.  
    23.         if(!isChestReady())
    24.             chestButton.interactable = false;
    25.     }
    26.  
    27.     void Update(){
    28.         if (GameController.GameCon.tierTwoPrizeCharmThree == 1) {
    29.             msToWait = 43200000.0f;
    30.         }
    31.         if(!chestButton.IsInteractable()){
    32.             if(isChestReady()){
    33.                 chestButton.interactable = true;
    34.                 return;
    35.             }
    36.  
    37.             //Set the timer
    38.             ulong diff = ((ulong)DateTime.Now.Ticks - lastChestOpen);
    39.             ulong m = diff / TimeSpan.TicksPerMillisecond;
    40.             float secondsLeft = (float)(msToWait - m) / 1000.0f;
    41.  
    42.             string r = "";
    43.             //Hours
    44.             r += ((int)secondsLeft / 3600).ToString() + "h ";
    45.             secondsLeft -= ((int)secondsLeft / 3600) * 3600;
    46.             //Minutes
    47.             r += ((int)secondsLeft / 60).ToString("00") + "m ";
    48.             //Seconds
    49.             r += (secondsLeft % 60).ToString("00") + "s"; ;
    50.             chestTimer.text = r;
    51.         }
    52.         if (chestButton.interactable == true) {
    53.             GameController.GameCon.claimFreeCards.SetActive (false);
    54.         } else {
    55.             GameController.GameCon.claimFreeCards.SetActive (true);
    56.         }
    57.     }
    58.  
    59.     public void ChestClick(){
    60.         lastChestOpen = (ulong)DateTime.Now.Ticks;
    61.         PlayerPrefs.SetString("LastChestOpen", lastChestOpen.ToString());
    62.         chestButton.interactable = false;
    63.         GameController.GameCon.alreadySwiped = true;
    64.     }
    65.  
    66.     private bool isChestReady(){
    67.         ulong diff = ((ulong)DateTime.Now.Ticks - lastChestOpen);
    68.         ulong m = diff / TimeSpan.TicksPerMillisecond;
    69.         float secondsLeft = (float)(msToWait - m) / 1000.0f;
    70.  
    71.         if(secondsLeft < 0){
    72.             chestTimer.text = "Daily Reward";
    73.             return true;
    74.         }
    75.             return false;
    76.        
    77.     }
    78. }
    79.  
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    If you just ask the server for the time and see if enough time has passed, that won't cut it: a player will simply hack the on-device data so that it says they got the last reward yesterday, or last week.

    To make this actually server authoritative, you also have to send the time from the player's device up to the server and store it in a database specifically for that player, which means you have to uniquely identify each player.

    Identifying each player means you also need to store personally identifiable information (PII) and are subject to GDPR and CCPA regulations, which you can google for yourself. Failure to do so is a fine in the neighborhood of $10,000/day per customer.

    It's a pretty big client-server piece of code, and your server has to be maintained and available 24/7.

    I recommend just using the system clock and checking against a local variable. When you reach 10,000 daily average users, you can reward yourself by doing all the above work. But before you do you might want to see if anyone is even actually cheating. It's pretty rare, and those people won't pay anyway, generally.
     
    Joe-Censored likes this.
  3. rubcc95

    rubcc95

    Joined:
    Dec 27, 2019
    Posts:
    222
    Well, I think it's not exactly as you said Kurt.
    The average player can change the clock hour, it takes 30 segs, but he would not search for your PlayerPrefs or your saving system to change the values. This take more time and you need a minimal knowledge about what you're doing... and with a simply obfuscation it could be harder yet... And anyway, if so much people try to do it, you should start to think about hire people because your game is really addictive and people might spend bunch of money on it...
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    I am completely open to this possibility.

    I just choose to spend my time making a better game experience rather than trying to change people's behavior.

    Good luck!
     
    Joe-Censored and rubcc95 like this.
  5. rubcc95

    rubcc95

    Joined:
    Dec 27, 2019
    Posts:
    222
    About how to apply it... Since GetTime() is a Coroutine and the time of the server could not be loaded when it's required for daily reward, TimeManager should be which actives the Chest of DailyReward. When GetTime() ends without any error, it could active an event or set a bool at DailyReward. If this bool is not true, chest will be unavaiable.

    Remember at ChestClick to change the value given to lastChestOpen to the value of the server, not the phone value... Or someone could open a chest with the phone date changed and imediatly open another indefinitely.

    Also, i think it would be easier if you use Unixtime instead of date and time as strings.
    https://showcase.api.linx.twenty57.net/UnixTime/tounix?date=now
    This page gives you a timestamp with the UnixTime which you can store at an integer. You only need to know one day is 86400 seconds so if currentTime - lastTime > 86400, a day has been completed.