public void tick() {
        roundId = this.maxTick + Constants.USER_ACTION_DELAY;

        // First tick, roundId = 50
        if (this.maxTick == 0) {
            RoundMessage message = new RoundMessage();
            message.setRoundId(roundId);
            this.getGame().sendAll(message);
        }

        this.maxTick += 1;

        if ((this.maxTick < Constants.USER_ACTION_DELAY * 10) && (this.maxTick % Constants.USER_ACTION_DELAY == 0)) {
            RoundMessage message = new RoundMessage();
            message.setRoundId(roundId);
            this.getGame().sendAll(message);
        }

        if (this.maxTick % (Constants.USER_ACTION_DELAY * 10) == 0) {
            RoundMessage message = new RoundMessage();
            message.setRoundId(this.maxTick + (Constants.USER_ACTION_DELAY * 10));
            this.getGame().sendAll(message);
        }

        this.gameMode.onTick(this.maxTick); // Call the listener

        if (this.maxTick % (Constants.INCOME_TIME / Constants.TICK_MS) == 0) {
            List<Integer> incomeLogEntry = new LinkedList<Integer>();
            for (PlayerInGame p : this.getGame().getPlayers()) {
                if (p.isConnected()) {
                    p.anticheat_updateMoney(this.maxTick);
                    if (p.anticheat_getCurrentMoney() < 0) {
                        processIntegrity(p.getClient().getId());
                        incomeLogEntry.add(p.anticheat_getCurrentIncome());
                    }
                }
            }
            incomeLog.add(incomeLogEntry);
            if (!gameStarted) {
                gameStarted = true;
                this.gameMode.onGameStart();
            }
            this.gameMode.onNewIncome();
        }
    }