1.15.2 Calculating Online PlayTime

Discussion in 'Spigot Plugin Development' started by OmegaWeaponDev, Feb 22, 2020.

  1. Hi,

    I am currently creating a plugin that gets the players current playtime. So far I've been able to get it so it saves the players login time an work out the playtime in milliseconds using System.currentTimeInMilli() but for some reason I can't get the milliseconds to convert into seconds, mins, hours and days correctly.

    I'm close to getting it but the seconds are slightly off. It is like it's using milliseconds instead of seconds.

    The code I'm using to calculate the seconds: https://prnt.sc/r619lh

    Here is a couple screenshots that shows the playtime command used within seconds of eachother. https://prnt.sc/r61fqs

    Note: The playtime is the 13 seconds & 21 seconds.

    The 21 seconds should be more like 15 or 16 seconds.

    Hopefully none of that is confusing for you, If you need more detail please let me know as I'm really wanting to get this sorted out.
     
    #1 OmegaWeaponDev, Feb 22, 2020
    Last edited: Feb 22, 2020
  2. Well you're using "TimeUnit.SECONDS.toSeconds" to convert your milliseconds to seconds ... which doesn't work out; the conversion rate for seconds to seconds is obviously 1:1. You used the correct one ("TimeUnit.MILLISECONDS.toX") for all the other ones, just not for seconds?
     
  3. I sent the wrong link for the code. I was already using the milliseconds.toSeconds an was having the same result.

    EDIT: The code you saw before was from when i was playing around trying to get it to work by testing something else. The new screenshot is the one that I'm using that is only slightly off.

    Here is a screenshot of where it works out the long for the playtime and saves it ready to be converted to seconds incase there is something wrong this this part. http://prntscr.com/r619es
     
  4. Hi! That is my code for converting long to String message


    Code (Java):
    private static String toNormalTime(Long millis){
            return String.format("%02d hours %02d minutes %02d seconds", TimeUnit.MILLISECONDS.toHours(millis),
                    TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
                    TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
        }
     
  5. That code seems to have its own issues. Given the following: The players "Play_Time" is set, as is his "Last_Join". What happens if this is run multiple times?

    The first time you're adding <playTime> + <time since login>. The next time you're using that computed value (since it's now saved in "Play_Time") and - again! - add <time since login>, basically duplicating the current time since login. A more concrete example:
    Current Play time: 100
    Last Join: 400000
    Current Millis: 400100
    Now the method/command is called, the new play time is now Current Play Time + ( Current Millis - Last Join ) = 100 + ( 400100 - 400000 ) = 100 + 100 = 200.
    Now its called again (say 100 millis later). The current play time is now 200+ (400200 - 400000) = 200 + 200 = 400.
    The first 200 is because you saved the last result already!

    So how can you avoid that? The easiest solution is probably to just update "Last_Join" to the current time when updating the "Play_Time", but that would not allow one to get the time of the current login session anymore. Alternatively, you could add another setting/field that specifies how much time of the current session has already been added to "Play_Time".

    Another approach would be to only update the play time once the user logs out and thus always calculate the current play time on the fly (i.e. pass it directly to StatsUtils.playerStats). That way, you can ignore this whole problem all together.
     
  6. What's all the effort for?
    Minecraft itself has its own play-time statistics.
    Just use this to get the player's online time.
    Code (Java):
    player.getStatistic(Statistic.PLAY_ONE_TICK)
     
  7. To add to this, 1 tick is 1/20 seconds. So play-time-tick / 20 will give the result in minutes
     
  8. *in seconds
    To add to this, there's no Statistic.PLAY_ONE_TICK in 1.15.2 and Statistic.PLAY_ONE_MINUTE instead, but.. it's still counting ticks.
     
    • Like Like x 1
  9. I'm wanting to have a live count that updates when they use the command, as well as the one that updates when they log out. An i'm close to getting it working so I'm wanting to fix it up so it does work. I am still kinda new to plugin development so i'm wanting to challenge myself and get it working without using the Player#Statistics. What would be the best way to resolve the issue with the last_join etc..
     
  10. You can still have that with the second option I mentioned. Whenever you run the command, you'd calculate the current time anew (so the current, saved time plus the time of the current session). This is neither a complicated nor intensive task so it's completely fine. Once the user logs out, you can update the persisted time to be the previous time plus the time of the (now) finished session.
     
  11. If you're planning on using this plugin, honestly this is just adding an already implemented function into the game..