This Week In Veloren 96

14 minute read02 December 2020

Authored by AngelOnFira

This week, Veloren 0.8 was released! We take a look at how the release went, and some of the feedback. We also hear from /u/o11c about some of their experience on large multiplayer projects.

- AngelOnFira, TWiV Editor

Contributor Work

Thanks to this week's contributors, @xMAC94x, @Yusdacra, @ubruntu, @Nicknakin, @XVar, @azymohliad, @AngelOnFira, @imbris, @Sam, @Snowram, @Treeco, @zesterer, @timsueberkrueb, @Pfau, @DaforLynx, @James, and @Slipped!

0.8 was released last weekend! There is a new article on GamingOnLinux about the Veloren 0.8 release. This was our biggest release ever, and it amazed the entire core team that so many people came out. @ubruntu has been working on small bug fixes and is currently working on adding chat commands for inviting, kicking, promoting, and leaving a group. @Snowram worked on adding and animating fish.

@Christof asked around for help on how to die less quickly in combat against bow wielding bandits, and then collected the answers into a beginner' hint section of the book. They also started to work on a minimum viable solution for selling inventory items that you gather over time and buying stuff you need instead. @Christof also got teloren, Veloren's terminal frontend, working on 0.8.0.

@Sam worked on abilities being automatically greyed out when you have insufficient energy. Previously, the UI had hardcoded values it checked, leading to some abilities greying out at incorrect values since they were checking outdated numbers. @Sam also fixed a bug with the leap potion of the bow's skill bar ability, and did a few miscellaneous combat tweaks. These primarily affected energy regen of melee weapons, and the bow's primary attack.

@Yusdacra improved the Nix dev environment so now it has a Cachix setup meaning that Veloren dependencies can be stored globally and everyone can benefit since they won't need to compile the same stuff again. It now also sets up git-lfs automatically, adds a direnv setup, and includes nixGL commands for non-NixOS users. This means they can actually run Voxygen now, since OpenGL programs on non-NixOS compiled via Nix is problematic. The Voxygen package now includes a .desktop file too.

Veloren 0.8 Launch

Veloren launched 0.8 this weekend! This launch includes some massive new systems, as well as a multitude of other changes. Here is a small part of the changelog, but make sure to check out the full changes here.

- New level of detail feature, letting you see all the world's terrain at any view distance.
- Point and directional lights now cast realistic shadows, using shadow mapping.
- Added leaf and chimney particles
- Some more combat sound effects
- Beehives and bees
- Fireflies
- Fullscreen modes now show two options (exclusive and borderless)
- Added banlist and `/ban`, `/unban`, and `/kick` commands for admins
- A new dungeon boss (venture there and discover it yourself)
- Adaptive stride setup for more dynamic run behavior
- Several new animals
- Buff system
- Flight
- Persistent waypoints (start from the last camp fire you visited)
- Ambient SFX emitted from terrain blocks
- Initial implementation of real-time world simulation
- Travellers that explore the world
- Innumerable minor improvements to world generation
- Aurora Borealis (localised entirely within the kitchen)
- Block-based voxel lighting
- Animals now have customized attacks and AI

Launch party!

This was not only the biggest update to Veloren yet, but also the biggest launch party. At the peak, there were 112 players online. This gave us a lot of insight into how scaling works. Here are some quick facts:

  • 5 minutes before the release party, we had to restart the server as we forgot to increase the player cap past 40.
  • We used a 32 core dedicated server from Hetzner. Although we had 128GB of ram on the server, we only used around 5GB.
  • The release party had the peak number of players 30 minutes after it started.
  • Normally, release parties go for around 2 hours before we get down to fewer than 10 players. This time, we went down to 30 players after two hours, and hovered there for around 24 hours.
  • We used around 100GB of bandwidth for the launch.
  • The server cost around 4 Euros, or $4.84 USD for the 7 hours it was up.
  • Players started reporting higher latency and some rubber-banding issues at the peak player count, but it was still playable.

We learned a lot from the release, and got a ton of important feedback. The most important item is how balance works for new players entering the spawn town. It was very difficult to spawn in and make it out of the initial area alive. There were also a lot of comments about how we could work on other character balance in the future.

From the stress test and release, we found many areas that need improvement on the scalability side. Our main game thread struggled a lot, which implies that we aren't assigning tasks to other threads as much as we need to be. Further, there are lots of improvements to be made within physics, AI, and other compute-heavy tasks. We also need to work on how we are sending data over the network to players. There are likely massive gains we can make, which would allow bandwidth to be improved significantly.

What People Are Saying About the Launch


Release party just now was chaos, in a good way :) I think there were around 100 players fighting a giant dragon

- Julius

Installation was super-smooth though, totally unexpected. It's just ~125MB, I expected something measured in GB. But then, makes sense, voxels + procgen...

- riidom

Going to snag this for my boy to check out. He was watching all 15 minutes and really liked what he saw. Great to hear this in Rust!

- techieg33k

Looks amazing. Definitely the most impressive FOSS RPG project that I have seen to date (no offense to Flare).

- nate

The timing of this release is funny for me because I just played the game with my kids yesterday before I knew there was a big update. I was pleasantly surprised to see a lot of things added to add interest to what was a more empty game. We used the Airshipper launcher which updated the game and then we played on a local server that was launched by browsing to the installation folder and running the server-cli program.

- 14


Veloren is shaping up beautifully, can't wait to see what's to come.

- /u/SmurfTaters

Idea Drop by /u/o11c

Context: On a Veloren 0.8 release post to Reddit, /u/o11c gave some insight from their own development experience. Although not all of it will be the path that Veloren takes, the points are valuable nonetheless.

LPT: don't ban botters too harshly, you want to get them to work for you. Also, be aware that people will use a bot client just because they want to avoid some particular pain point with the official client. So, steal their patches. Finally ... no matter what you do, you will never block all bots. So instead focus on making sure bots don't ruin people's fun.

Also a random dump of other things I've learned, mostly from doing everything the wrong way (some items already filtered because I saw you did them right already, but I admit I haven't looked hard yet):

  • Never use TCP. ISPs will rudely inject RSTs into long-running streams, and you can't realistically ask people to install a firewall rule to drop them.

  • Likewise, always encrypt everything. QUIC made life easier but there are numerous alternates. Multiple streams are probably overrated.

  • Always have a "frontend" server that proxies client connections from the start; this allows transparently moving them to a different backend server when they move between in-game regions (which is essential for scalability). You cannot rely on clients to successfully connect to a second server themselves. Not all players need to use the same frontend server either. Load typically isn't an issue, but this may be useful for working around crappy ISP peering in some countries.

  • Think about ways players can organize:

    • A friend is a one-way, individual, relationship. There should be user-labeled levels of friends ("rivals" might be a level).

      • Some of this should sensibly be viewed from a web interface, not just in-game
    • A guild is a large long-term group of many players, possibly with ranks. Sometimes it would be convenient if it's possible to join multiple guilds, but not too many.

    • A party is a small short-term group of players intending to do combat together; they may or may not be part of the same guild.

      • In practice, people often treated them as long-term. I suspect that it would be smart to systematically discourage that (e.g. by automatically breaking parties on logout ... but perhaps adding them to a "recently partied" friend group so that people can re-party them easily), and encourage creation of guilds.

      • Most dungeons can reasonably be set to take (or even create/enforce) a single party, but particularly large dungeons might not, since it's hard to keep track of too many people.

    • People might cooperate in combat even without joining a party

    • People or parties might compete in combat ("kill-stealing")

    • Make sure people who play support get XP/loot appropriately

  • Figure out (in-world) instancing so that guilds/individuals can have private space, multiple groups can run a dungeon at once if enabled, ...

  • Figure out how accounts can have multiple characters, how that interacts with friendship and server privileges, and what happens when they are deleted. Please do it in a sane way, I still have nightmares of that code ... (hint: "character id" should almost always be what is used, "account id" might not even exist at all except as a database-internal detail)

    • It may even be feasible to share accounts between official servers and third-party servers, but this may cause concerns about identity leaking if not done carefully
  • Consider eliminating username/passwords entirely in favor of public and private keys; invent a system of securely sharing an account between your computer and your phone that is immune to user error. (computer to phone is easy enough with a QR code, but you need two-way communication - if you think you don't, you don't understand the problem yet. Perhaps use the server as mediator? Should each device have its own private key that the server aggregates into a single account?)

  • If you allow in-app signup, someone will spam you and create millions of accounts and waste both storage and namespaces. Use a web browser so it can do it with captchas etc.

  • Always make sure each logical packet's size is known directly (this will generally not be the same as underlying UDP packets). This allows both skipping of totally-unknown packets, and size increase of existing packets.

    • It may be useful to have a special packet that says "wait for the next N packets (or bytes?) together before handling any of them"
  • Have a "display a message" packet that works no matter what the state of the client (on the login screen, in-game, ...). Possibly they should include a text domain (I favor client-side translation - just send the MO files as part of your updates (remember to include the fallback language-without-country stuff if you download only needed languages); that way, the client can log the not localized version; multiple languages in a single process is hard anyway).

    • This should be distinct from "display message in chat" (which may be translated if it's from the server, but set no text domain if it's from a player), "display message in NPC dialog" (also translated). Support for formatting and pluralization must be included.

    • You will have at least 3 text domains involved (client, server code, server script), might as well make it unlimited (different scripts (dungeons?) or even different parts of the server code might have different text domains) - think about people running a fork.

  • Make "connection to the server" a separate class than "info about the player", even though they both need to point to the other (Rust will probably fight you here too - neither owns the other (connection is owned by the event loop; player is owned by the map), but the former limits the latter's lifetime). The latter should not even exist until auth'ed (no more "spoof or eventual segv" if you don't tape up all the holey ducts).

  • Player shops are best done with special server support, not pure scripting or client hacks based on the trade dialog. Trust me, it has been tried.

  • As a rule, always limit things by configuration-file policy, not code (user name length, packet size/buffer/throughput; in particular, not having a hard inventory limit removes a lot of special cases in scripts)

  • Make a "transaction" script command to gain/lose items at once and handle failure cleanly (consider stacking and equipment)

  • Have a general-purpose "object inventory" class that gets reused sanely, with a special UI for moving objects between them arbitrarily. Don't specially implement player inventory, player storage, chest inventory, monster inventory, ...

    • A few cases are special, but should still share a lot: shops (have prices and maybe randomness too?), equipped items (know what slot they're equipped in - note, I'm increasingly leaning toward equipment-separate-from-inventory as opposed to equipment-as-part-of-inventory; really only the "transaction" script command should care), mob drops (might be random, maybe combining sub inventories?) - maybe use "struct of arrays" rather than "array of struct"? I wish languages gave support to that.

    • Make everything stackable if all properties match (padding bits are evil; upgrade slots are tricky), even if you want it to display unstacked (Rust probably helps you here)

    • Large arrays are slow! we've all played games like that. At the very least, if you display by category you should consider storing it by category.

  • Whenever you have jagged "array of arrays", be sure all the arrays share an allocation to keep the cache happy (also applies to set/map contents). E.g. load item definitions in the order given, then make a map pointing to them (Rust might fight you here, but with split arrays you probably don't have usable references anyway). Packet dispatch similar since IDs should be chunky.

  • Lots and lots of "hard typedef"s for all the IDs/indices floating around where pointers are inappropriate.

  • Consider what happens to a "high-score list" if a character is deleted (and possibly recreated) (merge this into the other list's entry about charid).

  • XML is a wonderful thing if you keep it away from humans.

Cave exploring at night. See you next week!