Duke4.net Forums: MP—What's broken? - Duke4.net Forums

Jump to content

Hide message Show message
Welcome to the Duke4.net Forums!

Register an account now to get access to all board features. After you've registered and logged in, you'll be able to create topics, post replies, send and receive private messages, disable the viewing of ads and more!

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

MP—What's broken?

User is offline   ThothXV 

  • 1

#1

Okay, so eduke32 MP has been broken for... jeez. Years. Which is why OldMP is around.

However, I can't find any documentation as to why the MP is in an unworkable state right now. What's actually broken? Does the code buggy, or an actually totally broken WIP mess full of //TODOs? What would it take for us to get it working?
1

User is offline   Mark 

  • Honored Donor
  • 2,822

#2

Its being totally rewritten for a modern client/server approach. I don't know the reasons behind why its taking so long. It looks like OldMP has had quite a few upgrades and people here have been using it and having a good time.

This post has been edited by Mark: 24 January 2019 - 02:40 PM

0

User is online   oasiz 

  • 871

#3

Build never had proper MP, it was an outdated p2p approach that introduced other things such as copious amounts of input lag that increased with your latency. Desyncs galore, etc..
Making proper MP for something like this and an engine that is not MP friendly (very extensive scripting & dynamic geometry) is just not that simple.

general lack of coders / time / people crazy enough / etc.. is probably the biggest thing.
2

User is online   Hendricks266 

  • Sperge Overlord
  • 6,318

  #4

View PostThothXV, on 24 January 2019 - 02:30 PM, said:

What would it take for us to get it working?

Wait 6-8 months for IM MP dev to complete.
6

User is offline   ThothXV 

  • 1

#5

View Postoasiz, on 24 January 2019 - 03:39 PM, said:

Build never had proper MP, it was an outdated p2p approach that introduced other things such as copious amounts of input lag that increased with your latency. Desyncs galore, etc..
Making proper MP for something like this and an engine that is not MP friendly (very extensive scripting & dynamic geometry) is just not that simple.

general lack of coders / time / people crazy enough / etc.. is probably the biggest thing.



Since I AM crazy, where's MP on the source tree? I know originally Build's MP was on the Build side of the Build/Duke divide, but it looks like the new stuff has jumped the gap and is currently in net.cpp/net.h. Just wanna make sure I got that right. It also has licensing implications, as the Build tree is of course under BUILDLIC, and Duke is GPL2 (and thus I don't have to make EXTRA sure I haven't been seen near the Quake sources lately)...

Also... coding convention? Are we 1TBS, K&R, or Allman? Tabs or spaces? I don't wanna muck any of that up.

Sorry for asking so many questions, but while I am a lazy git who promises nothing, if I'm gonna try and do this I wanna do it right.

This post has been edited by ThothXV: 24 January 2019 - 05:47 PM

0

User is offline   necroslut 

  • 231

#6

View Postoasiz, on 24 January 2019 - 03:39 PM, said:

Build never had proper MP, it was an outdated p2p approach that introduced other things such as copious amounts of input lag that increased with your latency. Desyncs galore, etc..
Making proper MP for something like this and an engine that is not MP friendly (very extensive scripting & dynamic geometry) is just not that simple.

general lack of coders / time / people crazy enough / etc.. is probably the biggest thing.

In my experience it always worked pretty flawlessly over LAN, and JF/ED32 online worked pretty well too if the distance between players wasn't too big.

Blue barrels are heavier than regular barrels
0

User is offline   Striker 

  • Auramancer
  • 1,006

#7

View PostThothXV, on 24 January 2019 - 05:46 PM, said:

Since I AM crazy, where's MP on the source tree? I know originally Build's MP was on the Build side of the Build/Duke divide, but it looks like the new stuff has jumped the gap and is currently in net.cpp/net.h. Just wanna make sure I got that right. It also has licensing implications, as the Build tree is of course under BUILDLIC, and Duke is GPL2 (and thus I don't have to make EXTRA sure I haven't been seen near the Quake sources lately)...

Also... coding convention? Are we 1TBS, K&R, or Allman? Tabs or spaces? I don't wanna muck any of that up.

Sorry for asking so many questions, but while I am a lazy git who promises nothing, if I'm gonna try and do this I wanna do it right.

Most of the C/S netcode is in net.cpp/net.h. Spaces, no tabs. Allman braces.

There's a number of things that need to be done. Handling of sector animation and synchronization (Changes in both the netcode and the game code itself need to be made), handling of allocating player sprites and spawning needs to be rewritten, etc. [IFOC]75 (jwaffe on the forum here) could give you a better run-down of what needs to be done.
2

User is offline   Photonic 

  • 1,255

#8

Might as well ask here, where is the bot ai in current EDuke32?

Also will Ion Maiden have bots?
0

User is offline   jwaffe 

  • 27

#9

Hi there, I'm 75 AKA Jwaffe,

Take a look at this post I made a while back it's still pretty much up to date as far as the main issues the c/s netcode is facing right now: https://forums.duke4...988#entry309988, since then my work has been merged into mainline, it's no longer on a private repo.

Quote

What's actually broken? Does the code buggy, or an actually totally broken WIP mess full of //TODOs?

- The netcode is functional as in you can launch it and play it, but it's not very stable unfortunately
- The sync code is done in that it can sync pretty much any change in the map except gamevars (I held off on those for now but I have a plan)

Most of the work left relates to integrating that sync code in with the rest of the engine, right now there are significant parts of the engine that I have trouble converting from p2p to c/s. While the netcode is in net.cpp, other files like premap.cpp could use some work (G_EnterLevel, for example)

Here are some of the main issues still present:

- Players joining and leaving mid-game isn't reliable
- Some sector effectors don't work well yet with the c/s netcode
- Animation smoothness can be improved in general, there's some sector movements that aren't interpolated that really should be
- Map transitions don't work most of the time
- Usermaps don't work correctly, I think this problem's related to the map transition problems (i.e., the player sprite code on startup doesn't quite work right in c/s)
- The player position sync code is vulnerable to speedhacking

Quote

What would it take for us to get it working?


- Adjust the startup code / map loading code so that player sprites are allocated in a way that allows midgame joining
- Investigate some of the SEs and find out special cases where the game should ignore some stuff like t_data values that should be interpolated instead of directly synced

Also, if there's any volunteers:

Quote

At this point what would really help is:
- If somebody could help me work with the map loading / startup code because I have had a lot of trouble figuring out how to implement some of the map change / initialization code for the netcode.
- If somebody who is really knowledgeable with Duke3D (somebody who's worked with the Duke3D source for a long time, or perhaps a really good modder) could go through and find more struct fields that should / shouldn't be synced for certain SEs, picnums, etc.


I've been trying to fix the startup code / map change code for a while but nothing I've done seems to have worked; I'm hoping that after IM ships somebody who's worked with that part of the code more can help me figure out what I'm doing wrong.

This post has been edited by jwaffe: 25 January 2019 - 03:04 PM

6

User is online   Little Tijn 

  • 26

#10

View Postjwaffe, on 25 January 2019 - 02:56 PM, said:

Hi there, I'm 75 AKA Jwaffe,

Take a look at this post I made a while back it's still pretty much up to date as far as the main issues the c/s netcode is facing right now: https://forums.duke4...988#entry309988, since then my work has been merged into mainline, it's no longer on a private repo.


- The netcode is functional as in you can launch it and play it, but it's not very stable unfortunately
- The sync code is done in that it can sync pretty much any change in the map except gamevars (I held off on those for now but I have a plan)

Most of the work left relates to integrating that sync code in with the rest of the engine, right now there are significant parts of the engine that I have trouble converting from p2p to c/s. While the netcode is in net.cpp, other files like premap.cpp could use some work (G_EnterLevel, for example)

Here are some of the main issues still present:

- Players joining and leaving mid-game isn't reliable
- Some sector effectors don't work well yet with the c/s netcode
- Animation smoothness can be improved in general, there's some sector movements that aren't interpolated that really should be
- Map transitions don't work most of the time
- Usermaps don't work correctly, I think this problem's related to the map transition problems (i.e., the player sprite code on startup doesn't quite work right in c/s)
- The player position sync code is vulnerable to speedhacking



- Adjust the startup code / map loading code so that player sprites are allocated in a way that allows midgame joining
- Investigate some of the SEs and find out special cases where the game should ignore some stuff like t_data values that should be interpolated instead of directly synced

Also, if there's any volunteers:


I've been trying to fix the startup code / map change code for a while but nothing I've done seems to have worked; I'm hoping that after IM ships somebody who's worked with that part of the code more can help me figure out what I'm doing wrong.



I was checking out the code for networking to try to fix some of these problems.

The first thing I noticed is that the connectpoint2 list is not cleared correctly. Therefore, disconnected clients are still in the list of frags, etc.
I added the following function to network.c:

void removePlayerFromConnectPoint2(int32_t player)
{
    int32_t i, j = 0;
    for (i = 0; i < g_mostConcurrentPlayers; i++)
    {
        if (connectpoint2[i] == player)
        {
            for (j = i; j < g_mostConcurrentPlayers; j++)
            {
                connectpoint2[j] = connectpoint2[j + 1];
            }
            break;
        }
    }
}


And called it at:
Net_HandleClientPackets() in the case ENET_EVENT_TYPE_DISCONNECT after P_RemovePlayer(playeridx);

Like so:

 case ENET_EVENT_TYPE_DISCONNECT:
            numplayers--;
            ud.multimode--;
            g_mostConcurrentPlayers--; //LITTLETIJN

            P_RemovePlayer(playeridx);
            removePlayerFromConnectPoint2(playeridx); //LITTLETIJN

            g_player[playeridx].revision = cInitialMapStateRevisionNumber;

            packbuf[0] = PACKET_PLAYER_DISCONNECTED;
            packbuf[1] = playeridx;
            packbuf[2] = numplayers;
            packbuf[3] = ud.multimode;
            packbuf[4] = g_mostConcurrentPlayers;
            packbuf[5] = myconnectindex;

            enet_host_broadcast(g_netServer, CHAN_GAMESTATE,
            enet_packet_create(&packbuf[0], 6, ENET_PACKET_FLAG_RELIABLE));

            initprintf("%s disconnected.\n", g_player[playeridx].user_name);
            event.peer->data = NULL;

            Dbg_PacketSent(PACKET_PLAYER_DISCONNECTED);

            break;


It looks like it fixed the frag bar on the server. Now the client. I changed in Net_ParseServerPacket() the case PACKET_PLAYER_DISCONNECTED like:

 case PACKET_PLAYER_DISCONNECTED:
        if ((g_player[myconnectindex].ps->gm & MODE_GAME))
        {
            P_RemovePlayer(pbuf[1]);
        }

        numplayers = pbuf[2];
        ud.multimode = pbuf[3];
        g_mostConcurrentPlayers = pbuf[4];

		removePlayerFromConnectPoint2(pbuf[1]); //LITTLETIJN

        break;


That fixed the frag bar on the client as well as far as I can see.

A question I have, what is stored in g_mostConcurrentPlayers? It looks like it always have the same value as numplayers until someone leaves the server.

What I try to fix next is checking when a player joins it gets the same player spot as the server. Because I noticed than when a client joins, it always spawns on the same spot as the server player. They are somehow connected while it shouldn't be.

Next, when a player disconnects, its player sprite is not removed, only hidden. In P_RemovePlayer() the call to P_QuickKill() only hides it. Is this correct? Or should it really be removed from the list of active sprites? If so, a new call should be made to remove it in the P_RemovePlayer function.

Hopefully this information will help us :).
3

User is online   Little Tijn 

  • 26

#11

When players connect and disconnect, the frag bar keeps the spots of the disconnected players open. Instead of relying on the playerIndex to set the position in the frag bar I think it is a better idea to use the connectpoint2 array instead. The following code is the change for the frag bar, so when a player leaves, its spot get removed as well.

In sbar.cpp:

void G_DrawFrags(void)
{
    if (ud.statusbarflags & STATUSBAR_NOFRAGBAR)
        return;

    int32_t i, j = 0;
    const int32_t orient = 2+8+16+64;

    for (TRAVERSE_CONNECT(i))
        j++;

    for (i=0; i<=(j>>2); i++)
        rotatesprite_fs(0, (8*i)<<16, 65600, 0, FRAGBAR, 0, 0, orient);

	j = 0;
    for (TRAVERSE_CONNECT(i))
    {
        const DukePlayer_t *ps = g_player[i].ps;
        minitext(21+(73*(j&3)), 2+((j&28)<<1), g_player[i].user_name, ps->palookup, 2+8+16);
        Bsprintf(tempbuf, "%d", ps->frag-ps->fraggedself);
        minitext(17+50+(73*(j&3)), 2+((j&28)<<1), tempbuf, ps->palookup, 2+8+16);
        j++;
    }
}


This post has been edited by Little Tijn: 23 March 2019 - 04:23 AM

1

User is online   Little Tijn 

  • 26

#12

Guess I forgot a spot where the fragbar height is calculated. Not tested, but I guess this change should work.

int fragbarheight(void)
{
    if (ud.screen_size > 0 && !(ud.statusbarflags & STATUSBAR_NOFRAGBAR)
#ifdef SPLITSCREEN_MOD_HACKS
        && !g_fakeMultiMode
#endif
        && (g_netServer || ud.multimode > 1) && GTFLAGS(GAMETYPE_FRAGBAR))
    {
        int j = 0;

        for (int TRAVERSE_CONNECT(i))
            j++;

        return ((j + 3) >> 2) * tilesiz[FRAGBAR].y;
    }

    return 0;
}


Just the same change from using playerIndex to number of player via length of connectpoint2 array.
0

User is online   Little Tijn 

  • 26

#13

I see the problem with the player indexes now.

The game is using the following define in macros.h:
TRAVERSE_CONNECT(i)


I trying to make a method to get the lowest available player index and to call it in Net_SyncPlayer() so the new player gets a nice index. Problem is, the TRAVERSE_CONNECT always assumes that the list of player ids in connectpoint2 is in order and that the indexes of connectpoint2 are the same as the player ids. Because of the new way of assigning player ids and the changes to the frag bar, this is not correct anymore.

Now, the solution I see is that the TRAVERSE_CONNECT needs to be modified to walk all player ids in connectpoint2 until -1 is found. I haven't found a good way to do this. If someone has a hint, that would be really nice! :)

EDIT: Removed broken code for now.

This post has been edited by Little Tijn: Yesterday, 01:28 AM

0

User is offline   Striker 

  • Auramancer
  • 1,006

#14

FYI: g_mostConcurrentPlayers should not be reduced. It's to store the most number of players that have ever been in the server simultaneously, not the number that are currently IN the server.


This post has been edited by Striker: Today, 08:06 AM

0

User is online   Little Tijn 

  • 26

#15

That's explaining the name of the variable. Although I though it was used for that, I couldn't find the reason to store this information.

About that problem with spawning, I notice that it is likely occuring when loading the snapshot from the server. When I have time, I will check it again.

Btw, I have a git repository available where my changes are at https://github.com/l...tijn/eduke32-mp

Also, how should the flow for connecting go? That I think is:
- When using the command line to connect, store information given in cmdline.cpp
- Start game as usual till S_ClearSoundLocks()
- Start connecting to server (should not block, so we can show a nice "Waiting for connect" screen
- Get the map to load from and load it with G_NewGame(). This will show the loading map screen
- Call G_CollectSpawnPoints so we get the spawn points for the map
- Wait for snapshot and apply it to the current map (Also with "Waiting for snapshot" message)
- Start game with G_EnterLevel()

Connecting from within the game render will allow us to implement connecting via the menu. It is already there, but not in a working state.

The snapshot will modify the spawn point positions, like all the other sprites. This is wanted, because some levels have changing spawn points (Like E2M2).

Is this correct?

Hope that I can help and not bother you with my questions :)

This post has been edited by Little Tijn: Today, 12:19 PM

0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic


All copyrights and trademarks are property of their respective owners. Instead of reading this text, you could be playing Ion Maiden! ;) © 2018 Voidpoint, LLC

Enter your sign in name and password


Sign in options