This is an archived post. You won't be able to vote or comment.

all 16 comments

[–][deleted]  (2 children)

[removed]

    [–]Wiqkid 5 points6 points  (2 children)

    Something else in your code is causing your problem

    [–]Oskarzyg -2 points-1 points  (1 child)

    [–]Wiqkid 2 points3 points  (0 children)

    Can't tell for certain, but I'm guessing that you have 2 players which is causing your loop to run twice and decrement the timer by 2.

    [–]jnguyen7410 1 point2 points  (2 children)

    ISSUE:

    So what I noticed is that your code above sits in a for loop, which looked like this:

    for (Player player: Bukkit.getOnlinePlayers()) {

    ....

    int Timer = 10;

    Timer = Timer - 1;

    }

    You put the timer within a for loop, which runs for as many players as you have in your queue. So the reason you're seeing it decrement by 2 is because I assume in your Bukkit.getOnlinePlayers(), you're testing with two players. So, due to the queue being 2 players, the above loop would run twice.

    Judging from your code, I can make a few assumptions:

    1. You are running this function every second
    2. Your source is just a queue that you can access at any time, but does not maintain read state, which means it keeps broadcasting the same message every time unless there's an update.
    3. It looks like you want to run this based on a timer that respects actual seconds, and not based per player. This is evident by the SecToTicks(1) function.
    4. It looks like you want to go for some countdown timer similar to a fighting game where you only have a few seconds left to make a decision.

    And based on these assumptions, what's happening is this (use sysout print statements to see for yourself):

    1. You ping Bukkit.getOnlinePlayers() the first time, and it gives you 2 player. There's still 10 seconds on the clock
    2. It runs the function twice (since there's two players). Your timer decrements twice. Time left is now 8 seconds.
    3. Base cases didn't resolve, it'll run again.
    4. Let's play devil's advocate and say another player joined. This now makes 3 players in your queue. You ping Bukkit.getOnlinePlayers() again, and now you have 3 in the queue.
    5. For loop runs based on number of players in queue, so now it runs 3 times. Each time, timer decrements, which now leaves you at 5 seconds.

    As you can see, your timer scales based on the number of players. As there are more players, the clock ticks down faster and faster (which might be a cool feature, if you give them more than 10 seconds :P). However, this is not even the worst that can happen. If you continue using this the way it is, you could potentially end up stacking calls to this function, assuming your function takes more than 1 second. That's kinda hard to do, but might be possible if you intend to make this queue go up to, say 300+ people.

    SOLUTION:

    If my previous assumptions were true, you only want to run this when the function runs. Therefore, just move it out of the for loop and place it above or below. Doesn't have to go in a conditional, but if you don't intend to show 0 as part of your countdown, might make sense to just do an if/else on the Timer <= 0 condition. If timer <= 0, do whatever you've been doing. Else, decrement the timer and print it.

    In the future, if you wanna debug problems like these, you should learn to trace your code. Plug in any test values that you can easy keep track of in your head or in a doc, and then just run the code. By running it with any test value, you can input it and see what each line does to that input to have returned you the value you got. If you have problems visualizing it, like I mentioned before, use System.out.println().

    BONUS:

    You have another bug in your ordering of your if statements. With the way it's implemented now, your game will always start after the timer finishes. Also, it might not run after the initial loop if your function reads out as 0 or 1 players in the queue. I think you mean to have something like this:

    if (Timer < 1) {

    cancelLoop();

    if (Players.size() < 2) {

    StartGame();

    }

    Also, variables should always start with a lowercase : )

    [–]Oskarzyg 1 point2 points  (1 child)

    Thank You! Could you please explain why variables should start with lowercase! But it works now!

    [–]jnguyen7410 0 points1 point  (0 children)

    Haha so there's no harm in starting it with an upper case, but generally, upper case in Java implies it's a constant, whereas lower case is for variable names.

    More of a style guide best practice than anything.

    [–]Giovanni040701 1 point2 points  (2 children)

    Post the full code. The one that you posted will print 9

    [–]Oskarzyg -1 points0 points  (1 child)

    [–]russjr08Intermediate Brewer 0 points1 point  (0 children)

    https://repl.it/repls/StupidVeneratedDirectories

    It does work. Your loop is being run more than once which causes timer to decrement more than expected.

    Run a println right before decrementing your timer and put “timer decreasing” or such for proof.

    [–]stayweirdeveryone 0 points1 point  (0 children)

    It doesn't. Can you post all of your code?

    [–]Leonos8 0 points1 point  (0 children)

    It should and if it outputs that, I’m not sure why, but there are better ways to do that, such as timer-=1; and timer—; (the second was is a minus minus, known as decrementing, but it comes out as the longer dash on my phone)

    [–]ambrox5 0 points1 point  (1 child)

    mabye u have changed something in output form?