Thread: [634] Main thread events

Page 1 of 2 12 LastLast
Results 1 to 10 of 16
  1. #1 [634] Main thread events 
    Contributor

    clem585's Avatar
    Join Date
    Sep 2013
    Posts
    3,556
    Thanks given
    654
    Thanks received
    640
    Rep Power
    358
    I'd like to confirm the order in which events should be executed in the main game thread. Here's what I have right now:

    Code:
    package com.rs.tasks;
    
    import com.common.Settings;
    import com.common.engine.GameEngine;
    import com.common.utils.misc.GameTime;
    import com.common.utils.logger.Logger;
    import com.rs.game.World;
    import com.rs.game.entity.list.EntityList;
    import com.rs.game.npc.NPC;
    import com.rs.game.player.Player;
    import com.rs.net.NetworkHandler;
    import com.rs.net.game.decoders.IngoingGamePacket;
    import com.rs.net.game.encoders.game.LocalNpcUpdatePacket;
    import com.rs.net.game.encoders.game.LocalPlayerUpdatePacket;
    import lombok.Getter;
    import lombok.Setter;
    
    import java.util.List;
    
    /**
     * Created by clem585 on 2018-06-03.
     */
    public class WorldThread extends Thread {
    
        // ...
    
        @Getter
        private long lastCycleTime;
        @Setter
        private boolean running;
    
        // ...
    
        @Override
        public final void run() {
            while (running) {
                long start = GameTime.currentTimeMillis();
                try {
                    GameEngine.tick(); // tick tasks
    
                    // so you don't skip steps - creates a copy of the current players/npcs
                    EntityList<Player> players = World.getPlayers().clone();
                    EntityList<NPC> npcs = World.getNpcs().clone();
    
                    for (Player player : players) {
                        try {
                            player.processEntity();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
    
                    for (NPC npc : npcs) {
                        try {
                            npc.processEntity();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
    
                    for (Player player : players) {
                        try {
                            player.getEncoder().write(new LocalPlayerUpdatePacket());
                            player.getEncoder().write(new LocalNpcUpdatePacket());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
    
                    for (NPC npc : npcs) {
                        try {
                            npc.resetMasks();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
    
                    for (Player player : players) {
                        try {
                            player.resetMasks();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
    
                    // flushes the buffer for the clients connected and the game clients connected
                    NetworkHandler.sendPackets();
                } catch (Throwable e) {
                    Logger.handle(e);
                }
                lastCycleTime = GameTime.timeElapsed(start);
                long sleepTime = Math.max(50, Settings.GAME_TICK - lastCycleTime);
                try {
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {
                    Logger.handle(e);
                }
            }
        }
    
        // ...
    
    }
    Essentially it's:

    1- Game tasks. Stuff like castlewars timer ticking.
    2- Process player. This processes logic packets, then continue on with what the player was doing (ex: fishing).
    3- Same stuff with NPCs
    4- Send players/npcs local update. This sends the masks for each player/npc
    5- Reset masks for next tick of local update
    6- Flush session to send the OUT packets that were written

    I just wanted to know if that was the correct structure. Should there be a way to handle tasks after the player is processed as well (between 2&3)? And does anybody have a list of logic packets? What about non-logic packets like chat message, how are they processed? On receive, but limited to 1 per tick?
    Project thread
    [Only registered and activated users can see links. ]
    Reply With Quote  
     

  2. #2  
    Contributor
    Kris's Avatar
    Join Date
    Jun 2016
    Age
    23
    Posts
    3,536
    Thanks given
    703
    Thanks received
    2,322
    Discord
    View profile
    Rep Power
    5000
    Switch player and NPC processing, NPCs get processed first.
    All delayed tasks should be handled at the top.
    There is no such thing as a "list of logical packets", all packets are handled in the first block of player processing. Nothing should be handled directly on the network threads. The rest of the structure looks good, although you really could flush all the players' packets out in the player/npc local update block, no need to re-iterate players multiple times.

    Edit:
    I'd also like to add that this is bollocks:
    Code:
    long sleepTime = Math.max(50, Settings.GAME_TICK - lastCycleTime);
    Because.. 1) You're restricting it to sleeping a minimum of 50ms even if the tick takes longer than 600ms, in which case it should be trying to catch up, you should never slow it down further.
    and 2) The overall mechanic will result in your average tick taking 600.5ms, not the 600ms you should be aiming for. I suggest using a single thread scheduled executor to achieve this, the scheduleAtFixedRate method takes care of the time fluctuating, so your ticks will be more in lines of.. 600ms, 600.5ms, 599.5 ms etc. It will correct the previous tick's leftovers - or shortgoings with the next tick.
    Reply With Quote  
     

  3. Thankful users:


  4. #3  
    Contributor

    clem585's Avatar
    Join Date
    Sep 2013
    Posts
    3,556
    Thanks given
    654
    Thanks received
    640
    Rep Power
    358
    Quote Originally Posted by Kris View Post
    Switch player and NPC processing, NPCs get processed first.
    All delayed tasks should be handled at the top.
    There is no such thing as a "list of logical packets", all packets are handled in the first block of player processing. Nothing should be handled directly on the network threads. The rest of the structure looks good, although you really could flush all the players' packets out in the player/npc local update block, no need to re-iterate players multiple times.

    Edit:
    I'd also like to add that this is bollocks:
    Code:
    long sleepTime = Math.max(50, Settings.GAME_TICK - lastCycleTime);
    Because.. 1) You're restricting it to sleeping a minimum of 50ms even if the tick takes longer than 600ms, in which case it should be trying to catch up, you should never slow it down further.
    and 2) The overall mechanic will result in your average tick taking 600.5ms, not the 600ms you should be aiming for. I suggest using a single thread scheduled executor to achieve this, the scheduleAtFixedRate method takes care of the time fluctuating, so your ticks will be more in lines of.. 600ms, 600.5ms, 599.5 ms etc. It will correct the previous tick's leftovers - or shortgoings with the next tick.
    Thanks!

    Now I'd just need to know how processEntity() should work. What are high/medium/low priority commands and how do they queue? Like poison behind an interface for example.
    Project thread
    [Only registered and activated users can see links. ]
    Reply With Quote  
     

  5. #4  
    Mug Club


    Join Date
    Jul 2011
    Age
    26
    Posts
    1,875
    Thanks given
    510
    Thanks received
    890
    Discord
    View profile
    Rep Power
    332
    Quote Originally Posted by clem585 View Post
    Thanks!

    Now I'd just need to know how processEntity() should work. What are high/medium/low priority commands and how do they queue? Like poison behind an interface for example.
    Jagex actually has a very precise and accurate Nanotime based FPS manager in the client used to ensure that each frame is 20ms. You can use to ensure your ticks are always being executed at the precise time they should be and keep the server in sync.

    [Only registered and activated users can see links. ]

    I would also like to confirm the order events should be processed to especially to fix things like objects and region based events. (IE: Net trapping and other various hunter objects spawning automatically animated objects and those animations not being synced with the client's pulses properly).

    These objects are being replaced with the animated ones on the world tasks. Sometimes the anims are synced sometimes not.

    Last edited by Makar; 07-02-2020 at 01:30 AM.


    My Open Source Projects
    [Only registered and activated users can see links. ]
    [Only registered and activated users can see links. ]
    Reply With Quote  
     

  6. Thankful user:


  7. #5  
    Contributor

    clem585's Avatar
    Join Date
    Sep 2013
    Posts
    3,556
    Thanks given
    654
    Thanks received
    640
    Rep Power
    358
    Quote Originally Posted by Makar View Post
    Jagex actually has a very precise and accurate Nanotime based FPS manager in the client used to ensure that each frame is 20ms. You can use to ensure your ticks are always being executed at the precise time they should be and keep the server in sync.

    [Only registered and activated users can see links. ]
    I just used what Kris suggested for this, I think Java's Executors does the same thing behind the scene so less code to write. Thanks for the suggestion though

    Quote Originally Posted by Makar View Post
    I would also like to confirm the order events should be processed to especially to fix things like objects and region based events. (IE: Net trapping and other various hunter objects spawning automatically animated objects and those animations not being synced with the client's pulses properly).

    These objects are being replaced with the animated ones on the world tasks. Sometimes the anims are synced sometimes not.

    This isn't something we can fix though right? Has to do with how client handle these animation events and how the server sends these updates only once every tick.
    Project thread
    [Only registered and activated users can see links. ]
    Reply With Quote  
     

  8. #6  
    Mug Club


    Join Date
    Jul 2011
    Age
    26
    Posts
    1,875
    Thanks given
    510
    Thanks received
    890
    Discord
    View profile
    Rep Power
    332
    Quote Originally Posted by clem585 View Post
    I just used what Kris suggested for this, I think Java's Executors does the same thing behind the scene so less code to write. Thanks for the suggestion though



    This isn't something we can fix though right? Has to do with how client handle these animation events and how the server sends these updates only once every tick.
    I have not once seen that issue happen in the real game though. There is definitely SOME way to synchronize the client with these ticks somehow so that the animations are on time.

    Also Java's executors don't do that behind the scene unfortunately so that doesn't work as a solution.

    Java scheduled executor service:
    Code:
    1593651161231
    1593651161832
    1593651162432
    1593651163034
    1593651163635
    1593651164236
    1593651164838
    1593651165439
    1593651166041
    1593651166642
    1593651167243
    Constant increasing time that never corrects itself.

    Jagex's nanotime sleep:

    Code:
    1593651211199
    1593651211799
    1593651212399
    1593651212998
    1593651213598
    1593651214198
    1593651214798
    1593651215398
    1593651215998
    1593651216599
    1593651217198
    1593651217799
    1593651218398
    1593651218998
    Always corrects itself and has support to correct for missed ticks if somehow that happens.


    My Open Source Projects
    [Only registered and activated users can see links. ]
    [Only registered and activated users can see links. ]
    Reply With Quote  
     

  9. Thankful user:


  10. #7  
    Contributor

    clem585's Avatar
    Join Date
    Sep 2013
    Posts
    3,556
    Thanks given
    654
    Thanks received
    640
    Rep Power
    358
    Quote Originally Posted by Makar View Post
    I have not once seen that issue happen in the real game though. There is definitely SOME way to synchronize the client with these ticks somehow so that the animations are on time.

    Also Java's executors don't do that behind the scene unfortunately so that doesn't work as a solution.

    Java scheduled executor service:
    Code:
    1593651161231
    1593651161832
    1593651162432
    1593651163034
    1593651163635
    1593651164236
    1593651164838
    1593651165439
    1593651166041
    1593651166642
    1593651167243
    Constant increasing time that never corrects itself.

    Jagex's nanotime sleep:

    Code:
    1593651211199
    1593651211799
    1593651212399
    1593651212998
    1593651213598
    1593651214198
    1593651214798
    1593651215398
    1593651215998
    1593651216599
    1593651217198
    1593651217799
    1593651218398
    1593651218998
    Always corrects itself and has support to correct for missed ticks if somehow that happens.
    I will try to see what I can do for object animation but I have no idea what it could be. Apart from that, Java's Executors does correct himself, depends which method you use:

    Code:
    [09:16:12 PM] 1593652572159
    [09:16:12 PM] 1593652572760
    [09:16:13 PM] 1593652573360
    [09:16:13 PM] 1593652573961
    [09:16:14 PM] 1593652574559
    [09:16:15 PM] 1593652575159
    [09:16:15 PM] 1593652575759
    [09:16:16 PM] 1593652576361
    [09:16:16 PM] 1593652576961
    [09:16:17 PM] 1593652577560
    [09:16:18 PM] 1593652578161
    [09:16:18 PM] 1593652578759
    [09:16:19 PM] 1593652579359
    [09:16:19 PM] 1593652579959
    [09:16:20 PM] 1593652580559
    [09:16:21 PM] 1593652581161
    [09:16:21 PM] 1593652581759
    [09:16:22 PM] 1593652582359
    [09:16:22 PM] 1593652582959
    [09:16:23 PM] 1593652583560
    [09:16:24 PM] 1593652584160
    [09:16:24 PM] 1593652584759
    [09:16:25 PM] 1593652585359
    [09:16:25 PM] 1593652585960
    [09:16:26 PM] 1593652586559
    [09:16:27 PM] 1593652587161
    [09:16:27 PM] 1593652587760
    [09:16:28 PM] 1593652588359
    [09:16:28 PM] 1593652588961
    [09:16:29 PM] 1593652589560
    [09:16:30 PM] 1593652590161
    Project thread
    [Only registered and activated users can see links. ]
    Reply With Quote  
     

  11. #8  
    Mug Club


    Join Date
    Jul 2011
    Age
    26
    Posts
    1,875
    Thanks given
    510
    Thanks received
    890
    Discord
    View profile
    Rep Power
    332
    Quote Originally Posted by clem585 View Post
    I will try to see what I can do for object animation but I have no idea what it could be. Apart from that, Java's Executors does correct himself, depends which method you use:

    Code:
    [09:16:12 PM] 1593652572159
    [09:16:12 PM] 1593652572760
    [09:16:13 PM] 1593652573360
    [09:16:13 PM] 1593652573961
    [09:16:14 PM] 1593652574559
    [09:16:15 PM] 1593652575159
    [09:16:15 PM] 1593652575759
    [09:16:16 PM] 1593652576361
    [09:16:16 PM] 1593652576961
    [09:16:17 PM] 1593652577560
    [09:16:18 PM] 1593652578161
    [09:16:18 PM] 1593652578759
    [09:16:19 PM] 1593652579359
    [09:16:19 PM] 1593652579959
    [09:16:20 PM] 1593652580559
    [09:16:21 PM] 1593652581161
    [09:16:21 PM] 1593652581759
    [09:16:22 PM] 1593652582359
    [09:16:22 PM] 1593652582959
    [09:16:23 PM] 1593652583560
    [09:16:24 PM] 1593652584160
    [09:16:24 PM] 1593652584759
    [09:16:25 PM] 1593652585359
    [09:16:25 PM] 1593652585960
    [09:16:26 PM] 1593652586559
    [09:16:27 PM] 1593652587161
    [09:16:27 PM] 1593652587760
    [09:16:28 PM] 1593652588359
    [09:16:28 PM] 1593652588961
    [09:16:29 PM] 1593652589560
    [09:16:30 PM] 1593652590161
    What method corrects itself? I have used a ScheduledExecutorService and all of the schedule methods within it and none of them correct themselves.


    My Open Source Projects
    [Only registered and activated users can see links. ]
    [Only registered and activated users can see links. ]
    Reply With Quote  
     

  12. #9  
    Contributor

    clem585's Avatar
    Join Date
    Sep 2013
    Posts
    3,556
    Thanks given
    654
    Thanks received
    640
    Rep Power
    358
    Quote Originally Posted by Makar View Post
    What method corrects itself? I have used a ScheduledExecutorService and all of the schedule methods within it and none of them correct themselves.
    From Kris:

    Code:
    ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(ThreadFactory f);
    ses.scheduleAtFixedRate(thread, initialDelay, period, timeunit);
    Project thread
    [Only registered and activated users can see links. ]
    Reply With Quote  
     

  13. #10  
    Mug Club


    Join Date
    Jul 2011
    Age
    26
    Posts
    1,875
    Thanks given
    510
    Thanks received
    890
    Discord
    View profile
    Rep Power
    332
    Quote Originally Posted by clem585 View Post
    From Kris:

    Code:
    ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(ThreadFactory f);
    ses.scheduleAtFixedRate(thread, initialDelay, period, timeunit);
    Hmm, on my linux system, it works, on my windows system it doesn't.


    My Open Source Projects
    [Only registered and activated users can see links. ]
    [Only registered and activated users can see links. ]
    Reply With Quote  
     

Page 1 of 2 12 LastLast

Thread Information
Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)


User Tag List

Similar Threads

  1. Medieval Age || 317/634 || Project Thread
    By Haze in forum Projects
    Replies: 17
    Last Post: 10-04-2012, 05:28 PM
  2. [C#] Multi-threaded event system
    By Synthesized Insanity in forum Snippets
    Replies: 8
    Last Post: 03-02-2010, 10:27 PM
  3. Multi threaded event system
    By Maxi in forum Snippets
    Replies: 19
    Last Post: 02-14-2010, 04:35 AM
  4. Replies: 2
    Last Post: 12-17-2009, 08:22 AM
  5. {Fix} Exception in "main" thread
    By wizzyt21 in forum Tutorials
    Replies: 5
    Last Post: 08-01-2008, 08:21 AM
Posting Permissions
  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •