Jump to content
Search In
  • More options...
Find results that contain...
Find results in...


  • Content count

  • Joined

  • Last visited


About Ladna

  • Rank

Recent Profile Visitors

1278 profile views
  1. That's essentially deltas, I think. I don't know that having the clients "ahead" gives any benefit, because they can't be ahead of each other. That is, you only ever have two choices: wait for a peer command, or guess and be prepared to rollback and replay. And technically, I think all the c/s ports advance gametic asynchronously from the server anyway. But, yeah it is imo the only reasonable netcode architecture. The only thing to really engineer at that point is the actual delta process. For example, whenever someone fires the SSG, something like 22 new mobj_t's are spawned, which ends up being like, lots of kilobytes. That caused instant lag in D2K, so I had to build some "frequently spawned actors" hack. Properly built out it wouldn't be a hack, but the point here is while deltas solve a lot of problems, it's not a free lunch. But that said, I haven't run into anything fundamentally impossible to manage, which I can't say about network messages.
  2. Ladna

    How does this source port handle multiplayer?

    C/S netcode in Doom is hard for several reasons. Doom is a fast game, so the netcode has to be high-performing. You can't skimp on this, or you'll cause cascading problems. C/S netcode by itself is a pretty deep area. The main worry is you'll bake desyncs deep into your protocol without a plan. But there are lots of things to work on too: lag, packet loss, prediction, reconciliation, randomizing the order you think on players, projectile nudging.... Each of those things is pretty deep too. I spent months just on sound sync, for example. There aren't really good libraries for it. There's ENet, but it has a pretty hard limit of 4095 connections (maybe an issue considering spectators) and you have to build tons of stuff on top of it. EECS and D2K use(d) ENet, but these days I think that's a mistake. Reliable UDP isn't actually that useful. Doom assumes it's always using the P2P, TIC/command based netcode everywhere, and that means you have to change a lot of things, everything from finales, to the automap, to player commands themselves. As a result of this, it's very easy to break demo sync. Unless you have a great testing framework like Odamex and D2K, it'll be so hard to maintain you'll probably give up on it. Doom really thinks there should only ever be 4 players. Boom increased this limit to... 64? Changing this further requires a lot of thought, think about scoreboards, saves, etc. And of course, monkeying with this affects demo sync. Once you bring C/S netcode into the fold, you need to do a lot to make it usable. Things like a console, a sane configuration/menu system, a way to find servers and join games, a C/S netdemo system, and a way to manage and monitor servers--either an RCON system or a standalone server console. You probably want to implement different game modes (e.g. TeamDM or CTF) or statistics. Finally, modern Doom is a moving target and it's not all up to you. People will design popular new LUMPs in formats you think are garbage or require a lot of work from you to support, extend ACS or implement their own scripting whatevers, build new mods directly into source ports, etc. Like any source port author or modder, you'll have to make your own personal choice about how much of that to implement yourself, and how much to get involved in designing those things. I'm basically retired, but I was tinkering around w/ D2K over the holidays and it's kind of impressive. The netcode evidently works, it preserves demo sync, it has a console, scripting, and a new config/cvar system. I think where I left off was refactoring the netcode to be clearer so it could be used by other ports. If you (or anyone else) are looking for a project... :)
  3. Ladna

    Float to Fixed Behavior

    I don't know if a lot of research has been done on this. Odamex will run on ARM, like a Raspberry Pi, but you probably want to test on wired LAN so as to increase the likelihood that any desync you experience is because of architecture differences and not packet loss. Chocolate Doom (I think also Crispy) is another candidate, but I don't think you'll have any float-based problems there. I do know that if you goof with the compiler's float flags in Odamex you'll cause desyncs (fast-math; but I can't remember if it should be on or off... probably off), so that indicates vulnerability there, but it's not certain.
  4. Ladna

    Float to Fixed Behavior

    To kind of provide closure: I'm planning on doing this kind of thing only for the renderer, so I went with a clamp inside an #ifdef. It may turn out that I can't confine floats to the renderer, in which case it looks like I'll have to do something like what ZDoom does, but we'll see. Thanks again everyone.
  5. Ladna

    Float to Fixed Behavior

    Yeah like basically anything modern. Like this is in PrBoom+: static float GetTexelDistance(int dx, int dy) { //return (float)((int)(GetDistance(dx, dy) + 0.5f)); float fx = (float)(dx)/FRACUNIT, fy = (float)(dy)/FRACUNIT; return (float)((int)(0.5f + (float)sqrt(fx*fx + fy*fy))); } I imagine Cardboard does similar float -> fixed stuff, or a GL renderer. EDIT: Thanks Graf; I'll have a look :)
  6. Ladna

    Float to Fixed Behavior

    Converting from floating to fixed point in Doom is essentially: fixed_t float_to_fixed(float f) { return (fixed_t)(f * ((float)FRACUNIT)); } But this can result in undefined behavior: it's possible for the multiplication operation to yield +INF, and casting that to an integral type is undefined. My question is what Doom expects in this case? Does it want a clamp at 0xFFFFFFFF or 0x00000000? Does it expect wraparound? In advance, I'm not interested in "this rarely if ever happens". I would guess that's the case. I'm just trying to avoid undefined behavior if I can at all help it.
  7. Ladna

    "UMAPINFO" discussion

    I knew there was something I liked about you ;)
  8. This is simply untrue, as shown by the hundreds and hundreds of games that have a single, powerful, general purpose scripting language (google "games using Lua" and "games made with Unity"). The standard in industry is a single scripting language for everything. Many games are even written entirely in a single scripting language. The major barrier is piling languages (and text formats, for that matter) on top of each other because it requires so much work on the development side. That's entirely fair, and while I'm not trying to be inflammatory, my position is that I'd rather there be no standard than a bad one because then you don't need to continue to support it, and you don't have a constant, "just use [the standard]" argument to everything you might try and do. A good example is Zandronum's stats DB support. They essentially had to build database bindings for ACS. It's absolutely the case that even if a scripting language is only intended to be for very limited, simple map scripting, there will be significant pressure to use it for everything. There's real-world examples right now. There's a number of reasons, most of which have been brought up in all these threads ("ACS is a standard", "everyone already knows ACS", "ACS support already exists in [port x], don't add an entirely separate scripting engine for this 1 feature"). You can't apply this argument to general purpose scripting language and not ACS. It's just `actor.set_position(...)` everywhere. Besides, the whole point of adding a scripting language is to smooth out those differences so you don't need to have multiple C/C++ implementations of an engine feature. This is also false. If anything, "use ACS" is far more restrictive than "implement these APIs in [language x]". === Variously, people say, "Ugh Ladna, you're just trying to derail these standards threads", or here it's "you will most likely kill any momentum", and I guess I am? I mean I guess if the thread ends up being "hey let's make ACS the standard" and I disagree with it, I'll keep arguing until someone convinces me. But I've said pretty much everything I want to say, so I'll try and avoid that here and bow out. Please don't make ACS the standard Doom scripting language.
  9. Ladna

    "UMAPINFO" discussion

    stricmp is windows, strcasecmp is POSIX. In the build system you have to check for them and define one in terms of the other; you can't just replace it.
  10. That's a valid point, but I desperately want to avoid having more than one scripting language in an engine. This is sort of the same design perspective that leads to having dozens of different text lump formats, with the corresponding code bloat necessary to support them. Building a source port is already maybe an impossible amount of work, and I believe that adding to that workload stifles source port innovation. There's nothing wrong with an API spec. There's plenty of examples, probably the most famous are the C standard library, the Java standard library, and POSIX. I'm not saying I want something on the level of detail of a "Doom POSIX", but it's absolutely doable at a high level. `actor.set_position(4.0, 2.0, 8.0)` isn't hard to define. I'm actively working on that, so yes. Ahhhh, well I kind of have two responses. First, I think the best example is enemy/friend/bot behavior. Building a sophisticated AI in ACS isn't the easiest thing because reusing logic isn't very easy. As the Doom playerbase dwindles, I think it's probably an important feature to have pretty smart bots to fill in spaces. Like if you want to have a huge 100-player FFA on a pretty big map, that equals bots. But if you don't want it to be an idiot carnival, you need good AI, and doing that in ACS is harder than needs to be. This is a great lead-in to my 2nd, and more hand-wavy point. I think "doom effect" is at this point limited by ACS (and other stuff, but w/e). Vehicles, for example, aren't really "doom-y", but that's because we don't have the infrastructure to really support them. If we had a powerful scripting language 5 years ago we might feel differently about that now. Like, to a lot of people CTF is Doom because CTF was added a decade ago, but that's because C++ programmers added it to ZDoom. If they'd added vehicle racing instead there might be a lot of people who think DoomKart is Doom. If it was possible to do this kind of thing in scripting and not C++ (probably the hardest mainstream language), I think our idea of "doom effect" would be a lot wider than it is today. I get the frustration with me, and I'm not at all offended. But I think it's a very real possibility that the community comes to some sort of tacit understanding of "Boom Plus" as "GZDoom Minus", and while that's obviously a step up in terms of functionality, it's a step backwards in future development. I stand by my other position in favor of external library support, and my position here in favor of a powerful, mainstream scripting language that suits all purposes instead of multiple, limited, custom scripting languages that don't, because I think external library support and something like Lua or JavaScript would be a real boon for Doom's featureset and playerbase. I really view things like custom text formats and custom scripting languages as technical debt that port authors have to pay later, and that's why there are far fewer ports these days than there used to be. That's a real shame, and I think that general lack of innovation has a direct effect on our playerbase.
  11. Your answers all essentially reduce to "no ACS doesn't do this, so use something else". Hobbes asked "what doesn't ACS do?" I think if you pick a scripting language to do these things and it doesn't do them, you didn't do it right. But besides all of the functionality ACS simply lacks, it's legitimately a very limited language. It doesn't even have namespaces. Scripting should be the way modders extend the engine, because there's really no other way they can. It's supposed to be the thing you resort to when DECORATE or action functions don't cut it. If even that last resort is "if you can't do it in DECORATE you can't do it" then I really don't see the point. Plus I think it's generally counterproductive to pick a super limited language, and then extend it with an entirely different technology. It would have been better to just add that functionality in the first place. And finally, and I include this specifically because I think it's very important, just because you can do something doesn't mean you should. I can absolutely create a thing type in DECORATE, spawn an instance in ACS, and use its attributes to hold game state for my mod. But if I use this as an argument for why you don't need composite data types, I've totally lost it. There's a reason programmers like things like namespaces, custom types, or composite data structures, because even though in the end it's all ones and zeros, these tools allow us to write more featureful and sophisticated programs while avoiding errors and crashes. Your rebuttals boil down to "it's all just ones and zeros", which is true, but there's a reason we don't program in ones and zeros any more.
  12. Stats, new game modes, new weapons, new items, HUD mods and displays, console stuff, menu mods. Honestly stuff you use scripting for in nearly every other gaming engine from the last 10 years.
  13. Going off what I've been able to find on ZDoom's wiki. You have a single data structure, the array. String manipulation is... non-existent? Functions aren't first class. There's no way to declare a new type. There's also no way to declare a composite type, but in fairness ACS doesn't have those so consistency I guess. There are no external libraries, which means no support for things like JSON, databases, filesystem access, HTTP, etc. There are no tools for ACS, no debuggers, no analysis, no IDEs. You have very little control over allocation, and the lifetimes of objects isn't clear. I'm not trying to be a jerk but ACS is an extremely limited language. Whether you think that's a virtue or a fault is up to you, but you should also consider that there are other languages that can be similarly sandboxed but don't necessarily have these fundamental limitations.
  14. The main thing here is to do as much as you can in the engine and provide only an interface in the scripting API. You're right the more shit you store in the VM the more it will slog, so don't do that. Boxing is the enemy. Or: class Actor: def __init__(self, god, help, me, etc): self.god = god self.help = help self.me = me def main(): ac = Actor('a', 'b', 'c') Don't do that. Do this instead: from doom import Actor def main(): ac = Actor('a', 'b', 'c') Or you can use a language/runtime with a different GC model. Python uses refcounting, which is more deterministic and controllable, for example. Yeah but you don't necessarily need to ship Python, you just need it installed for the build system... which I agree is aggravating but I guess it takes hours to compile Chrome on a single machine so I can see why they would try insane things. There are a couple other engines besides v8 and SpiderMonkey; the "in-vogue" ones are Duktape, MuJS, and v7 (har har). Duktape and MuJS use the stack-based API that I remember you don't like from Lua, but v7 looks pretty dynamic in its API. Honestly the stack-based thing has been no problem at all; I basically have a single file that wraps these things and I never think about it. You rarely go further than 3-4 deep in the stack anyway so it's not like a cognitive burden besides. The main thing that pulled me off JS (I re-evaluated recently) is the lack of libraries. It's just hard to find them because there's not really a standard embedded JS engine. SpiderMonkey is close, but even then there aren't, say, database libraries. My $0.02 is "look at industry and see what they do". Some games have embedded Python, some games have invented their own language or their own toolchain (Sucker Punch Studios, QuakeC), but I think the standards now are basically C# (Unity) or Lua. I'm kind of OK with either; I think C# is a little boring and offputting to modders but meh. I don't personally think this is an interesting discussion, either in terms of tech or philosophy. Like, if this thread ends up being about punctuation vs. words, semicolons vs. line breaks, types vs. no types, then it's a huge waste of time. Let's focus on some basic stuff: Is a given solution technically feasible (fast enough, powerful enough, sandboxable) Is it a pain in the ass Have people used it before (sure, ACS and Fragglescript count) Is it extensible, i.e. are there libraries for it Can ports use it (PrBoom+ is still C, so no giant C++ JS engines or C++ binding generators) I'm not saying these are requirements; I'm saying they're the things we should weigh.
  15. Yeah that's true but here's kind of how the conversation went: <Graf> Pixel counts mad crazy yo, dat CPU sweatin <Ladna> Chill, just get some fly threads <Graf> Hold up cuz, BSP trippin <Ladna> BSP always been trippin, you can still parallelize and handle the pixel counts I feel like you could be tricky about the BSP too. I don't have a good idea right now though. BSP copies? BSP edit queue?