This week we discuss the 0.5 intro meeting that occurred last weekend. Some topics include design meetings and the Liberapay plan of action. We also stop in with @imbris, who shows off some new optimizations with caching, as well as a bug that prevented spawned objects from being shown.

Contributor Work

Thanks to this week's contributors, @imbris, @Slipped, @Timo, @Acrimon, @Pfau, @Songtronix, @soruh, @pestilence, @xMAC94x, and @Mckol!

The first design iteration for Veloren's login website

@Songtronix has been working on testing and fixes for Airshipper, which is slated for release soon. @SrMizuki is working on general user interface improvements to try and find a balance between functionality, design, and user experience.

A positive message from @Lulu!

@Soruh has been working on upgrading dependencies to get rid of security issues from RUSTSEC. @AngelOnFira has been working on getting a MacOSX target set up. This has proven to be quite difficult, but it will allow CI to automatically build Mac executables.

Some variations of axolotl by @Axolotl

Optimizations by @imbris

Time for a mini flamegraph story. I hadn't run a flamegraph recently and there had been some improvements to meshing speed among other changes to the engine. I was curious about what the current flamegaph would look like, so I gave it a go. The result showed that meshing was still a huge chunk of the flamegraph, especially now that I could crank the view distance up past 25.

Taking another look at it, I discovered there was a portion of the code doing lookups into the volume that didn't use the cached access that I had previously added. It caches the last accessed chunk to prevent a hashmap lookup for every block since most will be in the same chunk. The code of interest looked up adjacent blocks to determine which faces were exposed and thus needed to be meshed.

For a moment I considered using the caching here as well. However, the color smoothing was already accessing all the adjacent blocks which I took advantage of essentially removing redundant block accesses. Now the main bottleneck is the lighting flood calculations which is slated to be moved out of meshing entirely. For more information, check out !625

Object Spawn Bug by @imbris

Here's what happens when the client sends the /object chair chat command. For context, the server communication with clients was moved into the ECS systems. The relevant server code looks like this:

// 3) Handle inputs from clients frontend_events.append(&mut self.handle_new_connections()?); // Handle game events frontend_events.append(&mut self.handle_events()); let before_tick_4 = Instant::now(); // 4) Tick the client's LocalState. self.state.tick(dt, sys::add_server_systems); // Tick the world self.world.tick(dt); // 5) Fetch any generated `TerrainChunk`s and insert them into the terrain. // in sys/terrain.rs let before_tick_6 = Instant::now(); // 6) Synchronise clients with the new state of the world. // TODO: Remove sphynx // Sync 'logical' state using Sphynx. let sync_package = self.state.ecs_mut().next_sync_package(); self.state .notify_registered_clients(ServerMsg::EcsSync(sync_package));

During state.tick() one of the systems, message , receives messages from clients. When it gets this chat command, it pushes it onto the server-side event bus. So our /object chair commend is pushed onto this bus. But where does it get handled? In self.handle_events() , which occurs before state.tick() . This means we wait until the next tick to handle the chat command. This might introduce some latency but logically we are good so far. Now the next tick arrives and a chair entity is assembled and inserted into the world inside of self.handle_events() .

Rat

Now we get to state.tick() . At this point, the ECS systems are run including the entity_sync system which is responsible for sending physics updates to the clients. This includes the Pos , Vel , and Ori components. It happily does this, since the chair has no Last<Pos/Vel/Ori> components, which are used to track whether an update needs to be sent. The client then receives this information and processes it in a match :

ServerMsg::EntityPos { entity, pos } => { if let Some(entity) = self.state.ecs().entity_from_uid(entity) { self.state.write_component(entity, pos); } } ServerMsg::EntityVel { entity, vel } => { if let Some(entity) = self.state.ecs().entity_from_uid(entity) { self.state.write_component(entity, vel); } } ServerMsg::EntityOri { entity, ori } => { if let Some(entity) = self.state.ecs().entity_from_uid(entity) { self.state.write_component(entity, ori); } }

The client then promptly converts the uid to its associated entity and uses that to insert the received value e.g. the position... or does it? In reality, the client doesn't know this entity exists and so it just throws out this information since entity_from_uid() returns None . Meanwhile, the server keeps going through the current tick, all the way to:

self.state.notify_registered_clients(ServerMsg::EcsSync(sync_package))

Here, sphynx bundles up all the information it manages, like new entities! And that is sent to the client. So our client receives this and a positionless (effectively invisible) chair is created on the client's side. And because that chair never moves the server won't waste network bandwidth sending its position again.

The evasive chair, at long last

0.5 Intro Meeting

Last weekend, we met up to discuss what we were going to achieve in 0.5. Each team lead also gave a rundown on what they had worked on during 0.4, and their goals for 0.5.

The meeting attendees list keeps getting longer!

@Silentium and @AngelOnFira are working on working on coming up with a better process to make design decisions. The process focuses on regular design meetings and request for comments (RFC). A design meeting will consist of discussion on a specific topic, with a moderator to keep the conversation in scope. This meeting will produce an RFC document, which will be added to the Veloren RFC repo.

Anyone will be able to discuss the RFC in the comment section. Once everyone has been able to voice their opinion, a selected few will sign off on the RFC, and it will be added to the MDBook. The MDBook will be an accessible collection of all finalized design ideas. Since the MDBook only includes finalized ideas, it will be easier for external parties as well as contributors to understand Veloren's design. For more information on the process, take a look at the WIP document.

Down by the riverside

Although a formal description for 0.5 has not been written yet, some initial ideas were brainstormed for what the release could include;

- More player combat design in the game, multiple skills, more weapons. Individual behaviors, left click is different on sword and axe - Skills with buttons on the keyboard - Some effects from the skills. - Integrating this with levels and XP, so that people have reasons to progress. - Make NPCs drop stuff - Crafting - Fishing action - Initial implementation to prehistory simulation - Initial implementation of real-time simulation - Have NPC AI hook into the realtime simulation - Rework towns and populate them - Have some basic trade/reputation mechanics

The release date of 0.5 has been moved forward to sometime in January rather than the beginning of December. Since 0.4 was released partly into October, contributors would have been stressed on time to get new content ready for 0.5. On top of that, since many contributors are in school, progress is made a bit more slowly. The new release date is still being figured out, but it will be at least a week into January. This will hopefully allow for a healthy code freeze period right after the new year.

Liberapay was also a big topic during this meeting. The core team is working on setting up a crowdfunding model for Veloren. It is important to note that this model is incredibly experimental. Many tweaks will be made, and the logistic setup of the process is still ongoing. This model would follow three phases:

# Phase 1 - Anyone can donate, but not advertised as much - Money only goes to official infrastructure, rest is saved for Phase 2 # Phase 2 - Anyone can donate - Infrastructure costs have the highest priority - The remainder is distributed into each working group by the leads # Phase 3 - Anyone can donate - Infrastructure costs have the highest priority - Process of remainder usage is refined depending on the outcome of Phase 2

For more information about the meeting, you can take a look at the meeting minutes.