I agree it's sad that coop is neglected in c/s ports. The reasons are largely technical though.
1. A lot more happens in coop.
Monsters spawn all kinds of things, and they each have pretty different behavior. You end up adding a lot of netcode to handle all of it, and about 80% of the way through you think, "this is ass, fuck Maulotaurs", and you stop.
2. Scripting (ACS, etc.) is hard to write good netcode for.
Hopefully the ST2 (Zandronum, I refuse to accept the horrible new name) people can shed more light on this one, I'm pretty ignorant about this. But I have thought about it a little, so here goes.
Think about how you trigger scripts in a level. Most of the time you activate some kind of line special, but there are other ways.
There are two extremes to implementing support for scripting in netcode. Either you can be entirely serverside, which provides perfect sync but horrible lag, or you can predict things clientside, which provides no latency but might get out of sync.
Prediction is a common solution to the latency problem. C/S ports use it to move immediately, activate line specials immediately, move sectors smoothly, etc. Without it, clients would have to wait for server confirmation before anything happened, and put simply that blows.
Generally it's pretty easy to fix prediction errors. If you predict your local player to be somewhere they're not, you just zap them to wherever the server says they were. If you predicted a door to open but it actually didn't, you just zap it closed again (and if you thought you went through that door, you're zapped back behind it as well).
Fixing prediction errors due to scripting desyncs is extremely hard. Some stuff is trivial, like who cares if you triggered an on-screen message improperly. Other stuff is fixed with the old methods - zapping, basically. However, there's no easy solution for resolving desyncs in interpreter state. What if a script modifies a global variable? What if a script modifies internal engine state?
Ultimately you end up saying, "OK, some things can be predicted like on-screen messages, but clients have to wait for the server for other things". This means a couple things:
- You're gonna have to figure out some way of splitting that stuff up
- You're gonna write a bunch of code
"You're gonna write a bunch of code" falls into the "this is ass, fuck Maulotaurs" category of development.
I haven't thought this all the way through, but maybe it's worth moving the effort into the scripts themselves. For example, if you wanted to create a new game mode, you'd want to define a few new line specials, maybe a new scoreboard, some new internal state - like scoring, and some new logic (rules).
A lot of that can be predicted, or just run entirely clientside. Line specials that trigger sector movement are usually predicted, and a new scoreboard is just graphics and math.
Other stuff, like scoring or rule enforcement, has to be serverside. Since the modder is the only one that really knows that, maybe it's best to leave it up to them.
How exactly, I don't know. If you were doing Python you could use decorators maybe, although I spent a solid hour on it and didn't really resolve all the issues (how do you easily confirm or deny a prediction was accurate?).
So maybe it's better to do this stuff at a very low level, and keep it hidden from the modder.
More on topic: best part about vanilla coop was being in the room with whoever you were playing with. Sure it's more convenient to use launchers, plus you get to play with people around the world, but it was tons of fun to sit around eating junk food, drinking coke, and blowing up hellspawn together. Now it's basically trying to have a LAN party at your house, and either you look like you're desperately trying to not die alone (please be friends with me and come play video games) or you get a bunch of anti-social, "I like my setup at home, let's just get on Live dude". Lame.