Veloren: An Owner's Manual

This manual is the primary source of documentation for Veloren, both for users and for developers. It aims to document the features of Veloren, the manner in which it is developed, and describe the inner workings of both the game and the engine. It also aims to discuss future plans the development team has for Veloren.

Image of Veloren | Taken by @bidgehop

Image of Veloren | Taken by @bidgehop

Image of Veloren | Taken by @bidgehop

What is Veloren?

Veloren is a multiplayer voxel RPG written in Rust. It is inspired by games such as Cube World, Legend of Zelda: Breath of the Wild, Dwarf Fortress and Minecraft.

Beautiful town | Taken by @ogzzmert

Veloren is fully open-source, licensed under GPL 3. It uses original graphics, music and other assets created by its community. Being contributor-driven, its development community and user community is one and the same: developers, players, artists and musicians come together to develop the game.

What status is the project currently in?

After rewriting the engine from scratch (old game can be found here) we're now at a stage where multiple features are introduced quite rapidly.

Who develops Veloren?

Veloren is developed by a community of volunteers that have one unifying aim: creating a bright, colourful, fun world that can be explored and interacted with in unique and interesting ways.


The Veloren website contains weekly blog updates, developer information and download links. You can find it at


The Veloren community (both developers and players) are most active on the Veloren Discord server. You can join the server using the link below:

Social Media

We're on YouTube and Reddit and don't forget to follow us on Mastodon.


Visit to find all available options.

Veloren for Players

Thank you for being interested in playing Veloren!

If you want to kickstart your playthrough you can read through the Getting Started guide on the Veloren Wiki.

As the game updates at least once a week we recommend using Airshipper, the official Veloren launcher.

Enjoy your journey!

Veloren for Players

This section of the book will explain basic game concepts for players and general tooling.

Note: Please keep in mind that Veloren is not even in alpha yet and gameplay can't be considered fully fledged out. Some gaming aspects mentioned are still heavily in development.

Reporting Bugs

  1. First thing to do will be to check our GitLab issues if this bug is already known.
  2. If not create an issue with the Bug template and try to describe the bug as good as possible, include screenshots if needed.
  3. Upload the log file for additional information which can help us identify the issue. See below how to get logs. (Note: make sure no sensitive information is included in the log files)
  4. Submit the issue

Tip: Incase you do not want to create an GitLab account you can join our Discord and report the bug in #bugs-and-support.

Collect Logs

If you encounter problems with Veloren, we might ask you for logs or a trace. This tutorial shows you how to collect the logs, depending on your operating system, and the way you have installed Veloren.

By default Veloren server and Voxygen will both produce logs. They are printed in the terminal/cmd and to a file, called voxygen.log.<todays_date>. It even prints where the file is located to terminal/cmd:

Nov 25 01:40:14.388  INFO veloren_voxygen::logging: Setup terminal and file logging. logdir="/mnt/games/cargo-build/debug/userdata/voxygen/logs"

By default the granularity is INFO, but please provide logs on TRACE level (as shown below). Search for a message called Tracing is successfully set to TRACE to verify TRACE level is enabled.

Linux and macOS


  1. Start Airshipper with -vv argument.
  2. When the game starts it will print to the terminal the location of the log file. Check Airshipper page.


  1. Start voxygen with TRACE level in terminal:

    RUST_LOG="trace" ./target/debug/veloren-voxygen
    # or RUST_LOG="trace" cargo run
  2. Copy trace from terminal or the log file mentioned above.



  1. Opening a CMD.

    On Windows press Windows key + R. Then type cmd and hit enter.

  2. Type airshipper run -vv and hit enter.
  3. Run the game (till you encounter the problem).
  4. The logs should be located in %Appdata%/airshipper/profiles/default/userdata/voxygen/logs Or check Airshipper page.


Git Bash

-> See Linux/Compiled above

  1. Open a CMD.
  2. Go to your veloren folder with the cd command, e.g. cd C:\Users\<Your Username>\Desktop\veloren.
  3. Write set RUST_LOG=trace&& veloren-voxygen.exe and hit enter (exactly like here, without whitespace before &&)
  4. The logs will now be printed to the CMD and the folder userdata\voxygen\logs or %appdata%\veloren\.

Collecting info for graphics bugs

Sometimes it can be useful to collect extra information when debugging graphics issues. This info is not always needed so this mainly serves as a reference to point users to when the information would be helpful.

wgpu API trace

  1. Create a folder that to hold the trace. (e.g. wgpu-trace)

        mkdir wgpu-trace
  2. Run the game with the environment variable WGPU_TRACE_DIR set to the new folder. (the path can be absolute or relative)

    • Linux

          WGPU_TRACE_DIR="./wgpu-trace" airshipper start
    • Windows

          set "WGPU_TRACE_DIR=./wgpu-trace"
          airshipper start
  3. Reproduce the bug/crash and then exit the game (the trace will be larger if this takes a while).

  4. Zip up the trace folder for easy sharing.

For more details about wgpu's API tracing see

Dx12/Dx11 debug layer output

First, check that you are using the dx12 or dx11 graphics backend.

Using DebugView++

  1. Force the debug layer on for Voxygen (Note: if you compiled the game yourself without --release then this step can be skipped):
    1. Run dxcpl.
    2. Click "edit list".
    3. Add veloren-voxygen.exe and click ok.
    4. Make sure "Force On" is selected in the debug layer section.
    5. Click "Apply".

    Warning: Enabling debug layers adds extra overhead, make sure to follow the last step to disable them again.

  2. Setup DebugView++:
    1. Download the latest DebugView++.exe version from this page:
    2. Download the filter settings here: View.xml
    3. Run DebugView++.exe.
    4. Open filter settings screen with F5.
    5. Click "Load" button, select the downloaded filter settings file, click "Open", and then click "Ok" to close the filter settings screen.
  3. Start voxygen (with the dx backend has issues) and run until the crash/error occurs.
  4. In DebugView++, press Ctrl + S to save the current view containing all the debug messages from voxygen.
  5. Share the saved file.
  6. Run dxcpl again and remove voxygen from the list.

Using Visual Studio

  1. Install visual studio
  2. Force the debug layer on for Voxygen (Note: if you compiled the game yourself without --release then this step can be skipped):
    1. Open visual studio.
    2. Go to Debug > Graphics > DirectX control panel.
    3. Click the Edit List... button..
    4. Add veloren-voxygen.exe to the list (be sure to remove this when finished).
    5. Change the Debug Layer setting to Force On.
    6. Click apply and exit the control panel.
  3. Open the Voxygen executable as a project (original instructions):
    1. In visual studio: File > Open > Project.
    2. Navigate to veloren-voxygen.exe, select it, and click open.
  4. Run the project (green arrow and or option under the Debug menu).
  5. Reproduce the issue.
  6. Visual studio will have a section labeled "Output" with the output of the graphics debug layer and other random stuff (this can be shared via copy-paste).


The changelog can be found in the repository, and in the Airshipper launcher.


Veloren's development process is naturally open-ended and guided by its community: new features get added as and when there is consensus within the community. Veloren's development is a constant process of re-evaluation and incremental improvement, with contributors working on the features that most interest them. For this reason, the project doesn't have a precise roadmap! The goal of this roadmap is to provide a rough idea of where Veloren is headed, while also trying to explain why things are the way they are, and why some features are still unclear. Another thing to note is that we want all those features to work alongside each other to create synergies and deeper gameplay. Therefore, you will see similar subjects addressed in different parts of the roadmap. Finally, we are not able to provide a specific date for those features, as we are not a game studio: the game is based on the work of volunteers, whose time and motivation vary, so it’s impossible for us to give concrete estimates without creating potential disappointment for the players awaiting those features.

Existing Features’ Expansion/Rework:

  • Durability

How it works

Every piece of equipment, consisting of armor and weapons, starts off with 12/12 charges of durability with each death reducing said charge by 1. Durability has no effect on the stats of the equipment for a vast majority of charge, with the player only seeing a reduction in stats once the armor reaches 4/12 durability and steeply continues to decline the closer it gets to 0/12. Once a piece of equipment reaches 0/12 durability the item will still be usable, however, due to the steep decline in stats it becomes unviable for combat. A player can repair their damaged items at repair benches found in towns, costing Velorite and the primary material at lower levels.

Why do we want this?

Durability is an important death penalty as it hinders players from continuously zerg-rushing entities that exceed their abilities in order to obtain high-ranking items.

Future plans

Durability is a relatively new mechanic within the world of Veloren and thereby lacks polish. With the current implementation of the mechanic being unclear and frustrating for a lot of players, we are looking at a few tweaks that would make it more accessible and understandable for the players. The planned changes consist of:

  • Reducing the maximum durability to 8.
  • Making all repairs free.
  • Adding an option to reinforce durability, temporarily raising the maximum durability by eg. 6 on every reinforcement
    • Each reinforcement would cost extra materials (velorite + primary materials).
    • Reinforced durability cannot be repaired.
  • UI Changes:
    • Make the durability section of the death screen more explanatory (and flash!).
    • Add a durability bar below damaged items.

Additionally, we would like to incorporate more Points of Interest in the open world of Veloren such as Inns or other resting locations which allow you to repair your items outside of towns.

For more information, feel free to contact us on the Veloren Discord.

  • Pets and Mounts

Pets and Mounts have both been introduced in the game for a while now. However, they are far from being a complete system. We plan to rework them sometime in the future, but most of the mechanics wanted for pets and mounts have to be discussed to know where we are headed. It is quite a complex topic, as there have been many variants of pets in games we take inspiration from. There is no set plan for how they will work, and it will probably take time for them to get a proper rework. Those are some of the questions and debates we have surrounding the system:

  1. Should pets and mounts die permanently? If yes, how do we make them more resistant and less superficial?
  2. How should we implement the orders that we give? Should it be a skill tree? Should it be only related to combat? Etc.
  3. How do we distinguish battle pets from regular pets?

For more information, feel free to contact us on the Veloren Discord.

  • Vehicles (Airships, Ships, Trains, Carriages, etc.)

When asked about fast travel, we answer that there will be no teleportation. Instead, we have decided that we want to add faster means of travel, aka vehicles. The 100% confirmed means of travel are Airships and Ships. Carriages and trains are still on the discussion table, or at least we aren’t 100% sure how they will operate aesthetically or technically. The decision to not have instant travel is to protect the economy and incentivize players to explore. Flights/Rides will take less time but will not be instant. Because of that, we also want to make sure those travels aren’t chores, so we want to have enough potential activities to do on them notably by having crafting stations and other players/NPCs to talk/trade with. As for ownership, there is no set decision yet on how it will be implemented for technical and gameplay reasons. Some questions we ask ourselves are for example: “How accessible should such a vehicle be?” “Won’t it be weird if everyone has their own ship/airship?” “What do we do about a vehicle when its owner logs out?” etc. For more information, feel free to contact us on the Veloren Discord.

  • Food

Currently, food serves as a healing mechanic, but we plan to change it to a “long-time buff”.

  • Economy

We plan to have a complete economy that touches upon every single aspect of the game. That’s to say all mechanics will be directly or indirectly impacted by the economy. The ideal goal is to reach a point where players and NPCs can impact the economy without breaking it, while also ensuring no artificial resources are spawned. This means that we want all resources and coins to be actually traded and not appear out of nowhere. This will allow the game to have coherent/developed shortages, supply and demand pricing, price competition, market control, market regulations, regions of influence, trade routes, externalities, etc. While this is extremely promising, it is also extremely complex and hard to pull off, therefore, it will take a lot of time and tweaking to reach a stable and believable stage. For more information, feel free to contact us on the Veloren Discord.

  • World Sim

In Veloren’s description, Dwarf Fortress is listed as one of the inspirations, and world sim is where most of that inspiration will go. Currently, we have rtsim, which is a system that keeps track of things that change over time in the world. This ranges from NPCs to how many resources are left in a chunk, so understandably this will have a big effect on the whole game. One quite important goal with rtsim is that we don’t want there to be too much of a difference, for simulated things, whether a chunk is loaded or not. This also means we don’t want different kinds of resources to be created from nothing when a chunk is reloaded, this also has the effect of making grinding not viable. There are more things we want to keep track of here though. We want to keep track of wildlife populations, of NPCs inventories while unloaded (maybe at a lower resolution). We also want to make NPCs actually work, some examples might include hunters affecting the wildlife population, or herbalists affecting resource counts in chunks when they pick things up. For more information, feel free to contact us on the Veloren Discord.

  • Dungeons:

Dungeons are currently under rework, with the Gnarling Fortress and the Adlet Caves being the first two dungeons to be reworked. The future dungeons rework/addition include Sahagin Dungeon, Haniwa Tombs, Myrmidons Dungeon, Cultist Dungeon, Dwarven Mine, Vampire Dungeon, etc.

The objective is to make the dungeons more unique in how they look, how they play, and how the player interacts with them. We want dungeons to feel more tied to the world of Veloren, where there is interaction between the dungeon inhabitants and the world. For that, we aim at answering the following questions: Why is this dungeon here, what is its importance in the region, what are their motivations, and what will happen if they are defeated? (etc.) Therefore, we want those dungeons to feel “organic”, that’s to say they are an actual part of the world, and they interact with it. For that, the dungeons will not have instances, as this is incompatible with the “organic” part of it. The organic element of it also means that when a dungeon is cleared, we want to have the possibility that another group can settle in that particular dungeon. The tricky part is to find a balance between the availability of said dungeon and avoiding having grindy dungeons.

Additionally, in regards to content and balancing around dungeons we would like dungeons to be a more niche aspect of combat which requires a group of individuals to complete. This, of course, means that there will be both content designed for solo players and grouped players so as to not trivialize the completion of said content. For those playing single-player or those that find it difficult to form groups with other individuals, we offer the opportunity to team up with NPCs either by gaining favor or purchasing them for wares (See NPC Companions part of the roadmap).

For more information, feel free to refer to the following chapters of the roadmap: Horizontal Progression, Quests, NPCs Companions, and Instances. You can also contact us on the Veloren Discord.

  • Skill Trees

For now, Sword and Axe have received a Skill Tree rework (Note that it is not definitive, there will be modifications later to balance all weapons). Hammer, Bow, Staff, Sceptre, and General skill trees will also receive a rework. However, the discussions for those have either not begun, or are still in the very early stages. Therefore it is currently not possible to give more information about those without creating unstable expectations. For more information, feel free to contact us on the Veloren Discord.

  • Respawn

Respawns will receive a rework, to propose a more interesting and meaningful part of gameplay. However, there are no concrete plans yet, only a few areas around the mechanic that are being discussed on Discord. First, we might replace campfires with shrines/magic stones to give another use to campfires (cooking for example). Then, with the dungeon reworks (See Dungeon part of the Roadmap), respawn points might also be removed from dungeon entrances. Finally, we want to make the respawn points interactive, meaning that you would have to purposely select it as your spawn point (by pressing E). For more information, feel free to contact us on the Veloren Discord.

  • Combat animations

One feedback we receive a lot is about the animations in Veloren, more precisely the combat animations. They will most likely be reworked one day, but as things stand, the persons working on animations are not 3D animators per se. Therefore, most animations can be considered as placeholder for now, until someone gets to rework them. One important thing to note is that we do animations through code (Sam/Slipped explains). The downside is that many animators are only used to working with 3D rigging. For more information, feel free to contact us on the Veloren Discord.

Planned Features:

  • Quests

Quests are one of the main features we want that is still missing from the game. The reason for that is that we don’t want traditional quests that reset and have no direct ties to the events of the world. As you may have seen in the world sim section, we want quests to be generated with that system (RT Sim2), where quests are generated based on an actual need in the world. For that, we need to procedurally generate the quest objective based on a set of variables. As an example, let’s say a region has been attacked by wolves and the sheep and farm have been damaged. The local population would want someone to deal with that, but they would also need enough money to pay the hunter. This simple example can be developed for all kinds of quests, from a microenvironment to a macroenvironment, thus leading to complex quest lines and many opportunities to complete those quests. As you may suspect, this takes a lot of time, as other systems need to be developed beforehand. There will be a first iteration for quests, where we set up the structure and develop an MVP. For more information, feel free to contact us on the Veloren Discord.

  • Tutorial

Rest assured, a better tutorial is planned. However, there are many reasons why the current tutorial is lacking. First, it was developed a while ago, when the game loop was different from the current one, meaning that it may be wrong in some aspects. It does give valuable information, but could vastly be improved. That being said, it would be a lot of work for very little to rework the tutorial now. Indeed, as we are in the pre-alpha stages, the game is evolving very fast, and from one week to another, a completely new feature can be introduced. Therefore, it is better for us to wait until we have developed the core of the gameplay to our liking before building a new tutorial. For more information, feel free to contact us on the Veloren Discord.

  • Horizontal Progression

We plan on moving away from vertical progression and focusing more on its horizontal counterpart when designing player-based progression. The charm of a horizontal system is that it allows for every encounter to carry some weight of danger even when returning to, what would be described as, earlier areas of content. That is not to say that the player will never get stronger as it is important to have some degree of verticality to help work the players through earlier stages of the game whilst learning game mechanics and other fundamental systems that will set up for a large portion of the game that is horizontal. To expand on this, Veloren will see three tiers of verticality and two tiers of horizontalness when viewing gear. These tiers are described as T1, T2, T3A, and T3B, with the latter two being horizontal variants of one another in which the B variant acts as a more niche version of the A while still being just as strong and viable to use.

Although there is a degree of verticality, as mentioned before, a large portion of the game focuses on aspects in which verticality is trivial. Instead, we encourage and would like to see a player’s ability to deal with difficult situations by having a large amount of game understanding and experience in dealing with said challenge under their belt. Additionally, we would like to encourage group plays for more treacherous entities found in the overworld, with only the most experienced being able to solo group-oriented content with a great deal of content and resources (See NPC Companions part of the roadmap).

For more information, feel free to contact us on the Veloren Discord.

  • New Weapons

Shields, Daggers, Spears/Polearms, Crossbows, and more magical weapons (grimoires, elemental gauntlets, etc.) are all planned. They will be worked on when the current weapons have all received their rework. Guns are up for discussion (Think pirate guns rather than modern guns). Some other questions include the addition of throwing weapons, and having ammunition for ranged weapons. For more information, feel free to contact us on the Veloren Discord.

  • Recipes

We plan to have recipes in the game to expand crafting gameplay. As of right now, all crafts are unlocked at the start, which lessens the sense of exploration and progression. Having recipes will add a deeper layer to the crafting system by tying it to other mechanics, such as quests for example. The development of this feature is in its early stages, so a lot of details and implementation plans still need to be discussed. For more information, feel free to contact us on the Veloren Discord.

  • Jobs / Professions

Veloren will have jobs and professions with a wide variety. So far, we have only planned the mechanic, but we have no concrete plan of execution for it. Some of the jobs would include Alchemy, Cooking, Blacksmithing, Hunting, Mining, Wood Cutting, Trading, etc. For more information, feel free to contact us on the Veloren Discord.

  • NPC Companions

One of the fundamental premises of Veloren is that players are no different from the inhabitants of the world. This means that humanoid NPCs should be continuously interacting with the world in a similar fashion to players in an attempt to breathe life into the game. As players are capable of teaming up with one another we wish to see adventuring NPCs form parties with one another and players. This can be done by either gaining the favor of an adventurer NPC or hiring them for wares.

Why is this wanted?

Aside from the aforementioned pros it provides for the world it also is an incredibly important premise for the sake of combat-related balance. A large portion of entities will be created under the assumption that it will take a group of humanoids to slay the beast. This allows individuals playing on single-player to experience the same kind of content as those in multiplayer, in addition to individuals playing on multiplayer that find it difficult to form a party with others and/or prefer playing by themselves.

For more information, feel free to contact us on the Veloren Discord.

  • Storage / Banking

Banking is a desired feature within the future of the game. We would like to see major banks have some sort of bank that allows them to store non-perishable items in them for a cost. These items can be removed at other banks in other cities as long as they have the corresponding resources to do so. An example of this would be If the player were to submit X-troll hide in town A’s bank and were to then travel to town B, they may not be able to withdraw troll hide if the town has a lack of trolls in their vicinity, and subsequently lack the material in their bank stock.

Such a system is desired as it provides content, coherence in the world of Veloren, and roleplaying opportunities. In Veloren we would like to provide a variety of choices for how one interacts with the world. This can range from roleplaying as a noble adventurer to partying with a band of crooked thugs intent on robbing the town’s local bank.

For more information, feel free to contact us on the Veloren Discord.

  • Housing

We definitely want a way for players to have a more settled presence in the world of Veloren. Therefore, housing is planned to be a mechanic, but there is currently no concrete plan of execution because it relies on core systems that are not complete yet. Some of the questions we currently have are:

  1. How can we make it persist with map changes?
  2. How to tie it to our rtsim2 system?
  3. How do we set up the real estate market?

For more information, feel free to contact us on the Veloren Discord.

  • Server Federation

Eventually, we’d like to have a ‘federation’ system for Veloren servers, which would allow trusted servers to enable character transfer (and perhaps other aspects of economy sharing & communication) between one another. Note that, in general, there is no good way to authenticate the world or player data generated by third-party servers, so all servers in a federation must trust one another to act in a legitimate manner. Note that this is a long-term feature with no specific implementation plan or timeline, so is unlikely to happen soon. For more information, feel free to contact us on the Veloren Discord.

  • Reputation system (RTSim)

Our goal is to have a reputation system using RTSim in which the actions of the players are remembered by NPCs and can affect the world around them. This system is currently in its early stages, where NPCs will remember and attack you if you have killed an NPC in the past hour and have been sighted. We plan to extend the system to create more scenarios that reinforce the coherence of the world. For example, reputation could allow a player access to a faction restricted areas, or give them the possibility to interact in a particular quest because of their past actions. This would greatly reinforce the roleplay elements in the game as every action would have potential consequences. For more information, feel free to contact us on the Veloren Discord.

  • World Map

We definitely plan to have a bigger map, with bigger biomes, and more biome types. However, there are two main reasons why we are currently not doing it. First, some of the worldgen tools and systems are not developed or optimized, which would currently damage the quality of the landscape and the performance. Such improvements take a lot of time and research. Secondly, gameplay-wise, Veloren is not ready to be much bigger in scale map-wise: we need to have more connections between regions, more activities in the overworld, better means of travel, and overall more reasons to travel.

We plan to expand the map to 262x262 km^2 and to have oceans and continents rather than only one big landmass. Some of the additional biomes include oceans, badlands, plains, swamps, more types of forests such as bamboo, more magical/fantasy biomes, etc.

For more information, feel free to contact us on the Veloren Discord.

  • Factions / Kingdoms / Wars

Thanks to rtsim2, we want to have organic factions/kingdoms that will be able to take part in power struggles between each other and within themselves. Therefore, the diplomatic map will evolve with time because of the actions of the actors of Veloren. Note that this is a very long-term planned mechanic and that core mechanics will need to be developed and expanded before such a feature makes its appearance in the game. For more information, feel free to contact us on the Veloren Discord.

  • Mods & Plugins

We definitely want mods and plugins in the game. Some of the decisions we make may not be to the liking of everyone, that’s why we think it’s important that everyone can freely and easily modify the game on their side. The open-source aspect of the projects will enhance the modding potential of the game. The #learning channel in our Discord is also open for anyone who has questions regarding coding or any aspect of the game or programs we can help with.

Some ideas for plugins are that they enable (in ascending complexity):

  1. adding new models (armor), graphics, ron based stats to the game
  2. adding new animations, weapon skills, NPCs, structures (ships)
  3. logic behavior for sprite interaction (far future) I would like plugins to get downloaded from the server on the connection (but locally cached to cut down initial bandwidth).

Our devs working on plugins would also like to use wasm component model technology (WASI preview2) to enable plugins in Rust, C/++, Python, JavaScript, and perhaps more languages. This will enable servers to differentiate even more with different game content.

For more information, feel free to contact us on the Veloren Discord.

Discussed Features:

  • Inventory rework

The current inventory system is heavily affected by the introduction of new items, as it is slots based. It favors having stacks of items while limiting the diversity of materials. There are talks of switching to a weight-based system, which would remove the item introduction constraint, and allow for a deeper/more meaningful inventory management. However, no set conclusion has been reached yet so a lot of the details are still to be discussed. For more information, feel free to contact us on the Veloren Discord.

  • Building

The majority of core developers, if not all, do want some kind of building system. Therefore, it is safe to assume that a building system could see the light of day. However, there are a lot of questions surrounding such a mechanic, as it is first and foremost an RPG. First, free building will not be a thing (See Free Building part of the roadmap). However, this is the only thing that is certain for the official version of the game regarding the building. Some of the questions we have regarding building include terrain persistence between maps, accessibility of the mechanic, ties to the world, level of freedom, and more. Note that this is a long-term feature. For more information, feel free to contact us on the Veloren Discord.

  • Fog of War / Better Map gameplay

Currently, the map shows every dungeon and region on the map. We don’t intend to keep it that way as it damages exploration and discovery quite heavily. Fog of War is more than likely planned, but the details regarding its implementation have not been discussed yet. Some of the questions we have concern the gameplay loop around map discovery, that’s to say we need to discuss the various ways the player will be able to discover the map and mark the different sites. For more information, feel free to contact us on the Veloren Discord.

Non-Planned Features:

  • Instances

Instances are not compatible with a lot of core systems we have planned. Because we want to have organic dungeons (see the dungeon part of the roadmap), we can’t have instances on top of that, as it would affect the world coherence and the synergies of the core systems. Moreover, we believe that different actors should be able to impact the evolution and development of a dungeon. To conclude, instances can work in a traditional raid dungeon system, but this is not what we have planned for dungeons. For more information, feel free to contact us on the Veloren Discord.

  • Teleportation

Fast travel is a mechanic we do not want to see in Veloren as it trivializes a lot of planned systems such as the world’s economics. Teleportation implies the ability to instantaneously bring certain rare materials from one end of the world to another. For an economic system that relies on the notion of scarcity of supply depending on the environment, and thereby the subsequent increase in cost, this mechanic would oppose it in its entirety. Although fast travel is not desired, we would like to see fast_er_ travel such as airships, trains, sea-fairing ships, and a variety of mounts to still allow for both world coherence and to encourage the exploration of the wonderful world of Veloren which will be peppered in a large array of points of interests. For more information, feel free to contact us on the Veloren Discord.

  • Free building

Free building in a way similar to Minecraft isn’t something that is compatible with the style of game Veloren aims to be. First, we have a finite map, so the map would quickly be filled with a huge population. Then, we want to keep the coherence of the world, both aesthetically and gameplay-wise, that’s to say we want to conserve the art direction and quality, while also preventing profanity through free building. Then, we need to tie those buildings to civilization and our rtsim2 feature, which is most likely incompatible with such a mechanic as free building. It’s worth mentioning that the game is first and foremost a RPG, not a survival/sandbox building game like Minecraft is. For the world to be coherent and the RPG elements to stay at the core, we can’t really allow free building in the main game mode. (By main game mode we mean that people are free to create other game modes where free building could work. Think of creative/god mods in other games as potential game modes. For more information, feel free to contact us on the Veloren Discord.

  • Singleplayer characters in Multiplayer

Because everyone is an admin in single-player, we can not allow single-player characters to transfer to the official MP server, as it could quickly destroy the economy and the balance of the game. There are plans to have a server hierarchy, where you can go to a server “below” the one you are currently on in terms of “server trust”, but cannot go up. This would allow players to keep their characters in single-player no matter the fate of a server. However, such a feature takes a lot of time and isn’t planned for the short term. You can also check the Server Federation explanation for more details. For more information, feel free to contact us on the Veloren Discord.

  • Vanity Slots / Transmog:

We do not want a vanity system as we would like the player/NPC to be able to tell how strong an entity is based on visible equipment. We also don't want it simply for roleplaying purposes. If a player wants to look a certain way for roleplay, they should also bear the consequences of that decision. On another note, if players really want to change their look, they can do so on their side by replacing the .vox files of the item in question. That way, it will only be visible to them and it won’t impact the experience of other players. For more information, feel free to contact us on the Veloren Discord.

Development Philosophy

🔭 Wide scope

Veloren's world is large and extensive and we encourage many different ways to play the game, as well as diverse elements that enrich the experience. There is no single, specific goal or focus and we believe it would hurt the wider community if one was introduced.

🗽 Player freedom

Where possible, avoid 'invisible walls' (both literal and metaphorical) that arbitrarily break consistency and limit what players can do. If limitations need to exist for technical, balance, gameplay, or moderation reasons then attempt to find in-world justification for those limitations.

🧩 Modularity and extensibility

Where possible and where doing so does not place dramatic limitations on future development, Veloren should attempt to be modular such that disparate components of the project can be reused and integrated into diverse settings. Where possible, features should be small, self-correcting, rugged, and able to operate in diverse environments (a great example of this is the Controller/Agent/CharacterState code, which generalises to all players, NPCs, and even non-sentient entities).

🫱🏼‍🫲🏾 Community-driven

Development should occur in dialogue with the community. While Veloren is inevitably steered by those most active members, it is important to take into account feedback from the periphery: less active developers, moderators, artists, players, as well as third parties such as downstream consumers of the software produced by the project. Veloren should actively resist attempts to turn the project into a for-profit venture, with fundraising and finance used wisely with the primary aim of enhancing the core project, player experience, and upstream/downstream projects.

🗺 Teleological

Veloren emphasises gameplay and systems that emerge out of the application of simple, physically-based rules where possible. Systems should be simple, interconnected, self-balancing, and simple in isolation: complex and interesting behaviour should emerge through the interaction between systems rather than arising due to complexity within any single system.

Game Questions

Technical Issues/Questions


Is there a death punishment?

Yes, players lose durability on their gear when dying.

Is there voxel building?

There is some destruction - you can mine ore chunks and certain kinds of rock with a pickaxe.

Building isn't intended to be a major part of the game though and is currently only available for server admins and in singleplayer mode through commands. You can read more about it here.

Is the map infinite?

The map is finite, and will stay that way. There are many reasons to have a finite map, for one it allows us to do advanced simulation (erosion, economy, etc.). Which creates a more meaningful and consistent world. That doesn't mean that we can't have a big world though.

Is there fast travel?

Faster travel is planned: airships and ships will someday be usable for inter-town travel, and there could be other means of transport as well (underground trains, etc.). The contributors tend to not lean towards fast travel in a sense of instant teleportation, as this tends to deter exploration, and may affect the economy and the coherence of the world, as trade goods could be transported freely.

Can we have cosmetic armor above actual armor?

The contributors tend to not want cosmetic armors that would appear above an actual armor as it would affect immersion with NPCs but also regarding PvP. We want the players and the NPCs to be able to judge the strength of an opponent based on their look (gear), cosmetic armors would go against that. On the other hand, we do plan to have gear only for the look, like an urban outfit you could wear in cities. It would replace your armor and not appear above it.

Will there be flying mounts?

The contributors are divided on this matter but the common agreement is that flying mounts could make certain parts of the game skippeable (air travel with airships notably), but we do think that with the right approach and balance flying mounts could be a thing in the long term.

Is there a roadmap?

Yes! You can find it on this page.

Not really no. The reason for that is that this is a hobby project worked on by many contributors and there is no way to know what feature will come out first or what feature will be worked on next. The closest thing we can offer is looking at our #working groups channels on Discord where you can see what’s being worked on. Also, the weekly blog posts can help you know what’s planned in the future.

Will the game release on Steam?

We do plan to have a Steam release in the future but it won’t happen until we think there is enough content for it to be ready for Steam. We believe that a Steam release could turn away some players permanently if they are not satisfied with the first version they play. Moreover, as of right now, the game is not meant to be played by many, as it’s in pre-alpha. Many players would have demands and expectations that exceed the ones of a pre-alpha content which could harm the good development of Veloren in some ways.

Will we have shields?

And other types of weapons? Yes, shields and other weapons are planned, but we will only start working on them after the modular weapons and skill overhaul updates are out, as we want the current weapons to be where we want them to be before working on new ones.

How to donate?

You can support Veloren here: All donations go into server upkeep and management.

Will we be able to build in the game?

Yes and no. Currently, building is possible on some servers meant for it or in singleplayer with the build mode. But, in the long-term, we don’t plan to have building as free as it is on Minecraft for example, as it could affect the RPG element of Veloren. Free building would affect real time simulation. Another reason is that, unfortunately, not every build made by the players would fit with the art style of the game, which could affect the experience of other players. However, it’s not impossible that you may be able to customize the inside of your house in a town or city with premade assets.

Will Veloren contributors add NFT and crypto to the game?

Simply put, no. We do not want to add any form of crypto nor be tied to it. If you see cryptos or NFTs linked to Veloren, please be advised that it’s not an official part of the game and that we are not responsible for what you do with it.

Will the game ever have paying content?

No. Everything made by the official team will be free. We want every user to have the same gaming experience.

Can I use boats or airships?

Right now,no, boats and airships are glitched, but in the future, we plan to have travel means with airships and ships.

Airshipper crashes on launch

Airshipper doesn't work for some people, you could try updating your graphic drivers. But you can still open the game by using Airshipper in the console via the command airshipper run.

Will dungeons change?

Yes. Dungeons are currently being reworked. It is a process that takes time as we want every dungeon to be unique in gameplay and experience.

When will the “X” feature come out?

We do not know. Every Veloren contributors works on the game during their own time, meaning that there is no way to know how fast something will be merged in the game.

Game crashes on launch

  • With Airshipper you can switch graphics mode by pressing the cogs next to the play button. If none of the graphic modes you can select work, you could try to update your video drivers. Otherwise your GPU might be too old to run Veloren 😔
  • If you start the game through console you can switch graphics mode by setting the WGPU_BACKEND environment variable to either dx12, dx11 or vulkan.
  • In Windows cmd: set WGPU_BACKEND="vulkan"
  • In PowerShell: $env:WGPU_BACKEND="vulkan"
  • On macOS and Linux: export WGPU_BACKEND="vulkan"

Then running the game through airshipper run

Cannot connect to the server

For some people switching DNS server fixes this problem. Here is a guide.

In the worst case you'd have to use a VPN to connect to the server.

Game is lagging

  • If you have latency issues, it can help to enable "Lossy terrain compression" and lower View Distance in Graphics settings. Note: The game server is hosted in Germany so expect high latency if you're geographically far away.
  • If you have fps issues, the best settings to change are:
  • Cloud Rendering Mode to Cheap
  • Shadow Rendering Mode to None
  • Fluid Rendering Mode to Cheap
  • Select a lower Internal Resolution
  • Put Bloom and Point Glow at 0%.

If you're still having issues with fps you could try enabling the BareMinimum experimental shader. Here is a guide how to enable experimental shaders.

What software do you use for models?

We use MagicaVoxel, you can download it here: However, you can also use other apps if you feel like it (Goxel, etc) but some features we use might not be available.

How to download the game on macOS and Linux?

Mac: Steps to run Airshipper on Mac

  1. Download Airshipper for mac
  2. Open the zip to get the file
  3. Open terminal and write chmod +x ~/Downloads/airshipper-macos/airshipper
  4. Double click the file
  5. Enable running in system preferences>Security & Privacy>Allow Linux: You can download the Linux Airshipper here:

How to host a server?

Suggest to take a look at this and following the steps. If there's anything you don't understand don't be afraid to reach out to the devs on Discord and ask for help through our multitude of channels, such as #support: Hosting Guide

Will there be mods?

Yes. This game is open source, meaning that anyone can fork the project to make a mod with their own vision. We plan to have many mods in this game!

Can I add an email to my account to change my password?

For now (2022-06-07) it is impossible to add email to account. We plan to add User Account Panel which will make that possible.

How frequently is the game updated?

We should have an update every Thursday, but the amount of content in each update depends on what has been worked on in the week, which will vary quite often. We also have official releases that cover more content than the weekly updates to keep every player informed.

How do I become a moderator?

Becoming a mod is relatively natural.

If someone is a long term, talkative, and active player in discussion then they're likely to be recognized by the current community and the moderators too. If the devs need more moderators to handle the influx of players then they'll privately reach out to them and ask if they'd like to become one.

How to change account password?

You currently cannot change your password due to how our encryption system works. There has been discussion regarding optional Email verification. Those that do not tie their accounts to it will not be able to change their passwords as may be guessed

Can I remove my account?

In theory you can currently remove your account. Certain devs can remove it (AngelOnFira) but it is difficult task that we attempt to dissuade people from requesting account deletion. There is absolutely no drawback towards keeping an account, all the passwords are encrypted. We hash it once client-side with the auth domain as a salt using argon2id and then once again server-side with a randomized 256-bit salt. The client-side pre-hash is to prevent third party authentication servers from discovering potentially reused user passwords If you decide to keep your account then it simply means that you can log onto it whenever you'd like.

Will there be a User Access panel on the website for accounts?

In the future, most likely we will have a User Access panel for accounts.

Can I transfer my character between servers?

You currently cannot transfer characters as there's no proper way of trusting the player to not give themselves items (whether in the game or through source code) which would effect the official server. We may eventually add a way to bring your multiplayers character to single player or allow the option for server hosts to let character transfers.

"Veloren is open-source and community-driven" How do you plan to overcome the problem of going in too many directions at the same time? Do you plan to create more than one version of the game or hope that too many features will not break the code/game identity, etc.?

The Veloren contributors uses an organized system through its Discord and GitLab to restrict what content gets added into the main game. This allows the dev team to progress and polish the game to the degree they want. Additionally, because of its FOSS nature we expect, and even encourage, Veloren to be forked. Modders will be able to make the necessary changes to the code of the game then present to the community to try and snag the some players while also continuously adding new code from the main to the fork as long as it stays within GPL3 guidelines. We've already seen this happen with a popular Chinese server created by Evan Meek, who has heavily modded and changed the game, adding new entities, abilities, and tons more!


Airshipper is a cross-platform Veloren launcher taking care of keeping Veloren up to date. Due to our frequent updates it is the recommended way of installing Veloren.


Visit the download page to download Airshipper.


Airshipper stores its files in the following directories depending on your operating system:

Linux (Flatpak)~/.var/app/net.veloren.airshipper/data/airshipper
macOS~/Library/Application Support/airshipper

Airshipper will support profiles in future and and already stores the game files in a profile called default.
Logs, screenshots, assets are all located in the userdata directory inside a profile.


If Airshipper does not open or display correctly, you can use the CLI by

  1. Opening a terminal

    On Windows press [Windows] + [R]. Then type cmd and hit enter.

  2. Type airshipper run and hit enter

  3. Enjoy the game.

Voxygen - 3D client frontend

Voxygen is Veloren's official 3D frontend. It's the frontend that almost all users interact with Veloren though, although alternatives do exist. However, almost all documentation about Veloren assumes that Voxygen is the client frontend in use.

Voxygen is designed to be user-friendly and intuitive.


Voxygen's configuration file can be found in the userdata directory.

Gamepad Controls

Voxygen supports inputs via a gamepad or game controller. Unfortunately, inputs are not yet configurable through a GUI, but settings.ron can be edited manually via the controller section.

Experimental shaders

Voxygen has several experimental shaders that can be enabled via the graphics.render_mode.experimental_shaders option.

Please note that these shaders come with no guarantees: they may be completely broken, mutually-incompatible, or may melt your GPU. Please do not report rendering bugs if you have them enabled (unless you are quite sure that the bug has nothing to do with the shaders).

Experimental shaders are explicitly not a feature of the game. They may be removed, break, or change at any time and without warning. They exist purely as a way for developers to try out new rendering ideas and as a fun extra for experienced players.

Experimental shaders can be enabled by adding them to the relevant section. For example, to enable the Brickloren and NoNoise shaders:

    graphics: (
        render_moder: (
            experimental_shaders: [Brickloren, NoNoise],

The order of the shaders is irrelevant.

You can find a list of all available experimental shaders here.


All commands that can be executed in-game are listed below, note that many commands require Admin or Moderator permissions. Arguments surrounded by <> are required, [] indicates an optional argument.

Note: The table below is auto-generated from the commands within the Veloren source code using the command cargo cmd-doc-gen.

/adminifyTemporarily gives a player a restricted admin role or removes the current one (if not given)Admin<player> [role]
/airshipSpawns an airshipAdmin[destination_degrees_ccw_of_east]
/aliasChange your aliasModerator<name>
/buffCast a buff on playerAdmin<buff> [strength] [duration]
/banBan a player with a given username, for a given duration (if provided). Pass true for overwrite to alter an existing ban..Moderator<player> [overwrite] [ban duration] [message]
/battlemodeSet your battle mode to: pvp (player vs player) pve (player vs environment). If called without arguments will show current battle mode.[battle mode]
/battlemode_forceChange your battle mode flag without any checksAdmin<battle mode>
/buildToggles build mode on and off
/build_area_addAdds a new build areaAdmin<name> <xlo> <xhi> <ylo> <yhi> <zlo> <zhi>
/build_area_listList all build areasAdmin
/build_area_removeRemoves specified build areaAdmin<name>
/campfireSpawns a campfireAdmin
/debug_columnPrints some debug information about a columnModerator<x> <y>
/disconnect_all_playersDisconnects all players from the serverAdmin<confirm>
/dropallDrops all your items on the groundModerator
/dummySpawns a training dummyAdmin
/explosionExplodes the ground around youAdmin<radius>
/factionSend messages to your faction[message]
/give_itemGive yourself some items. For an example or to auto complete use Tab.Admin<item> [num]
/gotoTeleport to a positionAdmin<x> <y> <z>
/groupSend messages to your group[message]
/group_inviteInvite a player to join a group<player>
/group_kickRemove a player from a group<player>
/group_leaveLeave the current group
/group_promotePromote a player to group leader<player>
/healthSet your current healthAdmin<hp>
/helpDisplay information about commands[[/]command]
/homeReturn to the home townModerator
/join_factionJoin/leave the specified faction[faction]
/jumpOffset your current positionAdmin<x> <y> <z>
/kickKick a player with a given usernameModerator<player> [message]
/killKill yourself
/kill_npcsKill the NPCsAdmin
/kitPlace a set of items into your inventory.Admin<kit_name>
/lanternChange your lantern's strength and colorAdmin<strength> [r] [g] [b]
/lightSpawn entity with lightAdmin[r] [g] [b] [x] [y] [z] [strength]
/make_blockMake a block at your location with a colorAdmin<block> [r] [g] [b]
/make_npcSpawn entity from config near you. For an example or to auto complete use Tab.Admin<entity_config> [num]
/make_spriteMake a sprite at your locationAdmin<sprite>
/motdView the server description[message]
/objectSpawn an objectAdmin<object>
/permit_buildGrants player a bounded box they can build inAdmin<area_name>
/playersLists players currently online
/regionSend messages to everyone in your region of the world[message]
/reload_chunksReloads all chunks loaded on the serverAdmin
/remove_lightsRemoves all lights spawned by playersAdmin[radius]
/revoke_buildRevokes build area permission for playerAdmin<area_name>
/revoke_build_allRevokes all build area permissions for playerAdmin
/safezoneCreates a safezoneModerator[range]
/saySend messages to everyone within shouting distance[message]
/server_physicsSet/unset server-authoritative physics for an accountModerator<player> [enabled]
/set_motdSet the server descriptionAdmin[message]
/shipSpawns a shipAdmin[destination_degrees_ccw_of_east]
/siteTeleport to a siteModerator<site>
/skill_pointGive yourself skill points for a particular skill treeAdmin<skill tree> [amount]
/skill_presetGives your character desired skills.Admin<preset_name>
/spawnSpawn a test entityAdmin<alignment> <entity> [amount] [ai]
/sudoRun command as if you were another playerModerator<player> <[/]command> [args...]
/tellSend a message to another player<player> [message]
/timeSet the time of dayAdmin[time]
/tpTeleport to another playerModerator[player]
/unbanRemove the ban for the given usernameModerator<player>
/versionPrints server version
/waypointSet your waypoint to your current positionAdmin
/whitelistAdds/removes username to whitelistModerator<add/remove> <player>
/wiringCreate wiring elementAdmin
/worldSend messages to everyone on the server[message]
/make_volumeCreate a volume (experimental)Admin
/locationTeleport to a location<name>
/create_locationCreate a location at the current positionModerator<name>
/delete_locationDelete a locationModerator<name>


All the parameters that can be used in the commands that can be executed in-game are listed below.

aispawned entity has an agent/ai, true/false
alignmentwild, enemy, npc, petcode reference
area_namename of an area
args...additional parameters, e.g. in /sudo player tell Hello, how are you? args... would be Hello, how are you?
ban durationduration of the ban, e.g. 3d2h30m
battle mode"pvp" (player vs player) or "pve" (player vs environment)
blockname of blockblocks
buffName of Buff; be careful, docs use CamelCase and command expects snake_case, e.g. docs: "IncreaseMaxHealth" command: "increase_max_health"docs reference
[/]commande.g. give_item or /give_item
confirm"confirm", to confirm
durationduration in seconds
enabledboolean, true/false
entity_configpath to the entity starting from veloren.assets.common.entity with . as separator of directory names; with the prefix common.entity.! e.g.: common.entity.dungeon.fallback.bossfolder with the entities
factionString of Characters, e.g. "Hello"
hpHealth Points as number
itempath to the item starting from veloren.assets.common.items with . as separator of directory names; with the prefix common.items.! e.g.: common.items.armor.assassin.beltfolder with the items
kit_namename of a kit, e.g. debugdefinition of the kits
messageString of Characters, e.g. "Hello"
nameString of Characters, e.g. "Hello"
objectname of the objectdefinition of objects
overwriteset to true to overwrite previous ban
playerName of Player's Character
preset_namepath to the skillset starting from veloren.assets.common.skillset with . as separator of directory names; with the prefix common.skillset.! e.g.: common.skillset.preset.max.sceptrefolder with the skillset
radiusa number to define the radius, has to be higher than 0 and lower than 512
r, g, bred, green, blue; numbers used to define a color
role"admin" or "moderator"
skill treename of a skill tree, e.g. generalskill tree names from code
spritename of the spritedefinition of sprites
timeoptions: midnight, night, dawn, morning, day, noon, dusk or %H:%M format e.g. 12:21code reference
usernameusername of a player
xhipoint x on hi
xlopoint x on lo
xpoint x
yhipoint y on hi
ylopoint y on lo
ypoint y
zhipoint z on hi
zlopoint z on lo
zpoint z

Userdata Folder Structure

The userdata folder unifies all player and server configuration in a single place, which should be transferrable between different Veloren installations from v0.8 onwards.

The folder will be next to your Veloren executable, or in your repository's root if self-compiling. See where Airshipper stores files if using the launcher.


Contains settings for Voxygen, Veloren's official 3D client frontend.

This file is almost entirely configurable through Voxygen's in-game settings UI. For more information, see here.

The main thing not accessible from main game menus is gamepad keybindings, which can only be changed by directly editing the file.


Contains hotbar information per-character and per-server. Should never need to be manually modified.


This file is intended for manual editing, and should never be overwritten by the game. If the file is in an invalid state, the server will emit a warning in including the position of the error, create a settings.template.ron file full of the default values, and start up with all default values.

SettingDescriptionDefault value
gameserver_addressAddress and port the game server will listen to. Note that clients will use the port 14004 by default. Changing the port will require to specify it in the client too.""
metrics_addressAddress and port the game server will expose Prometheus metrics.""
auth_server_addressWhen using Some(<value>): The value is the IP address or domain the game server and client will use. If you want to disable authentication, you replace Some(...) with None.Some("")
max_playersMaximum number of players connected to the game server.100
world_seedseed number used to setup the random generation of the world.59686
server_namedisplayed server name"Veloren Alpha"
start_timeServer daylight start time in seconds.32400
map_fileSets which map to load. See here for allowed values.None
max_view_distanceThe maximum view distance that clients may request. Useful for low-RAM servers.Some(30)
banned_words_filesList of files containing words to be censored. None are distributed by default.[] (Empty array)
max_player_group_sizeThe maximum party size players can have, for purposes of XP sharing and ignoring friendly fire.6
client_timeout(secs: 40, nanos: 0,)
battle_modeCan be Global(mode) or PerPlayer(default: mode), where mode can be PvP or PvE and will be given to each player on join. The difference between Global and PerPlayer is that PerPlayer enables /battlemode command.Global(PvP)


Contains the introductory chat message clients get when entering the server, as a quoted string. Can be multiple lines.


"This is the best Veloren server"


Contains a list of whitelisted account IDs, and is considered disabled if empty. Heavily recommended to use the /whitelist add/remove in-game command, rather than manual editing.

Example: Result of using /whitelist add Treeco and /whitelist add treeco2.



Contains a list of banned accounts, and reasons. Heavily recommended to use the /ban and /unban in-game commands, rather than manual editing.

Example: Result of using /ban Treeco General nuisance and /ban treeco2 alt account.

    "6f15b915-074f-f78d-df88-34fb33e4e13f": (
        username_when_banned: "treeco2",
        reason: "alt account",
    "3445349e-d03c-64bf-6ecf-a15806275a1f": (
        username_when_banned: "Treeco",
        reason: "General nuisance",


Contains a list of admin account IDs. Heavily recommended to use admin add/remove from the server's TUI, rather than manual editing. There is no in-game command to permanently add admins, for security reasons.

Example: Result of using admin add Treeco.


If you have the TUI disabled or are otherwise unable to use it, you can instead use the server CLI to add/remove admins.


veloren-server-cli admin add Treeco


The settings in this file govern the warning period the server gives for automatic shutdowns for updates.

Hosting a Veloren Server


At its core Veloren is split into 2 components, a client (veloren-voxygen) and a server (veloren-server-cli).
In singleplayer mode, the game starts a server listening on a random port in the background and connects to it automatically.
In multiplayer mode however, Veloren also uses an authentication server (veloren-auth). This allows players to register just once on our website, and log into any server with the same account, similar to for example Minecraft.

How to use this guide

  1. Follow one of the Setup Guides:
  2. Head over to the Configuring The Server page to learn how to set it up according to your needs and preferences.
  3. (Optional) Generate a custom world.

Available Setup Guides

Choose the instructions for the runtime platform on which you want to run Veloren:

Hosting a Server on Your Computer

If you want to play with your friends and do not have a dedicated server, follow these instructions to set one up on your computer.

Playing over LAN

Note: This will only work when everyone is connected to the same Local Area Network (generally that means the same WiFi network or router).

  1. Start the server
  2. Find your local IP address and share it with your friends. They will need to enter it in-game to join the server.
  3. Have fun!

Playing over the internet

Note: You will need access to your router and knowledge about port forwarding.

Tip: If you are unable to set up port forwarding, there exist programs such as ZeroTier, Netbird or Hamachi, which allow a limited amount of users to connect to a local server through the internet.

  1. Forward port 14004 TCP and UDP on your router.
  2. Start the server
  3. Find your public IP address and share it with your friends. They will need to enter it in-game to join the server.
  4. Have fun! :)

Note: If you need your computer's local IP address for port forwarding, refer to the Finding your local IP address section below.

Starting the server

Using the server provided by Airshipper

This is a good option if everyone playing uses Airshipper.

  1. Find your game installation folder.
  2. Go into profiles/default.
  3. Launch veloren-server-cli[.exe].

Using a custom server executable

This is a good option if you want to play an older release or a custom version.

  1. Open the folder with extracted game files.
  2. Make sure you have the assets folder in the same place as the server executable.
  3. Launch veloren-server-cli[.exe].

Finding your local IP address

Tip: Generally local IPv4 addresses have the form of or, more rarely, For IPv6 addresses, local ones generally start with fe80:

On Linux and macOS

  1. Open the Terminal.
  2. Type ip addr || ifconfig and press enter.
  3. You will see all of your computer's IP addresses, grouped by network card/interface.
    Interface names starting with e are generally ethernet while ones starting with w are generally wireless. Lines starting with inet and inet6 show IPv4 and IPv6 addresses respectively. If there are multiple addresses in one line, only the first is important.
    For example, lo is the loopback interface with a IPv4 address and a ::1 IPv6 address.
    Likely, the first address which doesn't belong to the loopback interface is what you are looking for.

On Windows

  1. Open CMD (type cmd.exe into the start menu and press enter).
  2. Type ipconfig and press enter.
  3. You will see all of your computer's IP addresses, grouped by network card/interface.
    Lines starting with IPv4 address or IPv6 address show the respective address types. Likely, the first address which isn't or ::1 will be what you are looking for.

Windows Firewall (Optional)

If you use windows firewall, open cmd as admin and write those commands, and press enter. It will automatically add rules to the windows firewall. Remember to configure your router firewall accordingly too.

netsh advfirewall firewall add rule name="Veloren 14004" dir=in action=allow protocol=TCP localport=14004
netsh advfirewall firewall add rule name="Veloren Metrics" dir=in action=allow protocol=TCP localport=14005  

Hosting a server using Docker

If you want to run a dedicated Veloren server 24/7 follow this.

Note: We assume general command line and docker-compose knowledge. You will need docker and docker-compose installed on the server. You will likely also need root access to access docker.

Tip: Check out the Docker Compose file reference for more information about the docker-compose.yml file.


Note: The default docker_compose.yml will automatically keep the game server updated to the latest weekly release.

  1. Create a folder for the server data and cd into it.
  2. Download the sample docker-compose.yml from the repository into the folder.
  3. If needed, open port 14004 (14005 for metrics) in your firewall.
  4. To create and start the containers, run sudo docker-compose up -d.
    If you modify the docker-compose.yml file, you'll need to run that command again for it to take effect.
  5. Add moderators/admins by following the instructions below

Note: If you used the provided docker-compose file, you can use veloren-game-server-master in place of <CONTAINER_ID> in the following instructions.

Monitoring and maintenance

  • To restart the server, run docker-compose restart.
  • To view logs, run docker logs <CONTAINER_ID>.
  • To access the server's configuration files, open the userdata folder automatically created next to docker-compose.yml.

Running commands inside the docker container

The game server has a CLI interface that can be used to run commands for tasks such as adding admins and moderators. The steps for accessing this interface while the server is running inside Docker are outlined below:

  1. Run docker attach <CONTAINER_ID> (run docker ps to find the ID of the game server container, then if the ID is for example e002d350ab26, run docker attach e002d350ab26).
  2. You can now run server CLI commands. To see the available options type help and press enter.
  3. Once you are done, to escape press Ctrl+p followed by Ctrl+q.

Tip: To add an admin or mod, use admin add <USER> <ROLE>. <ROLE> can be either Admin or Moderator.

Tip: To gracefully shutdown the server for maintenance with 2 minute countdown, use:

shutdown graceful --reason "Shutting down for maintenance :)" 120

Note: Logging output from the server can break up the visualization of command input but this can be ignored and broken up commands will still work.

You are done!

Building the Veloren Server for Raspberry Pi

The model of Raspberry Pi you have and the operating system your Pi is running can significantly impact your installation steps and Veloren's performance on your Pi. For the best performance we recommend using the Raspberry Pi model 4 and a 64-bit OS like Ubuntu Server, which is available through the Raspberry Pi Imaging utility. There is a 64-bit beta of Raspberry Pi OS as well.

Note: The amount of RAM on the Pi 4 does not matter. Even the official Veloren server uses well under 2 GiB of memory most of the time.

Cross-compiling or not

Cross-compilation means setting up a toolchain for the Raspberry Pi's instruction set on a separate computer in order to compile the Veloren server binary which you then copy onto the Pi.

Direct compiling is preferred if:

  • You don't want to install and set up as many things on your computer
  • You want to be up and running in fewer steps

Cross compiling is preferred if:

  • You have a computer setup for development
  • You want the compilation step to be faster

Note: Even with cross-compilation it is necessary to clone the assets folder from the code repository onto the Pi as these files are not compiled into the server binary.

Direct Compiling

Log in to your Pi using SSH.
ssh <username>@<ip> and enter password Install the Rust programming language on the Pi if it's not already installed.

curl --proto '=https' --tlsv1.2 -sSf | sh

Install Git LFS in order to download the audio and visual assets along with the source code.

sudo apt install git-lfs

Git clone the Veloren codebase. You may need to generate SSH keys on your Pi for your GitLab account.

git clone

Compile the server binary from the code in the Veloren directory.

cd veloren
cargo build --bin veloren-server-cli --release

Run the server binary, optionally with -h or --help to see the list of arguments you can supply.


Note: Compilation on a Raspberry Pi 4 running Ubuntu Server 64-bit can take around 30 minutes for an optimized build.

Note: Remember to replace <username> by your own username and <ip> by the IP address of your Raspberry Pi!

Note: The process itself is resource heavy. Maybe still consider cross compiling. RAM usage can go over 8G, so you may consider creating a swap (although swap slows down the entire compilation process)

Note: If you experience an error when compiling wasmer-vm, you will need to disable plugin support by removing plugins = ["server/plugins"] from server-cli/Cargo.toml.

Cross Compiling

Installing Dependencies

Install the following dependencies on the cross compiling machine and the Raspberry Pi:

Cross Compiling PC:

  • git
  • git-lfs
  • cargo (which is installed along with Rust)
  • docker

Raspberry Pi:

  • git
  • git-lfs

Preparing the Raspberry Pi

First we need to clone the Veloren git repository.

git clone

Next we can reset the repository to the state of the last stable release. To do that we have to find out the git hash of that version. This can be found on The git hash is the sequence in the bottom left corner of the release. This step can be skipped if you want to play with the very latest updates.

cd veloren
git checkout <git hash>

Next we have to create some folders to later put the binary in.

mkdir target
mkdir target/release

Next, we need to add an environment variable to our .profile.

nano ~/.profile

In the last line of this file, add the line export VELOREN_USERDATA="$(pwd)/userdata

Lastly, we reload our environment to use the new variable

. ~/.profile

Cross Compiling the code

Again we have to clone the Veloren repository to our cross compiling machine, reset it to the state of the latest stable release and setup git-lfs.

git clone
cd veloren
git checkout <git hash>
git lfs install
cargo install cross

The install command will be different depending on which OS you have running on the Raspberry Pi.
If you are using a 64-bit OS like Ubuntu Server with an ARMv8 instruction set, run the command:

cross build --target aarch64-unknown-linux-gnu --bin veloren-server-cli --release

If you are using Raspberry Pi OS which is currently 32-bit and using ARMv7 instruction set for backwards compatibility reasons, run the command:

cross build --target armv7-unknown-linux-gnueabihf --bin veloren-server-cli --release

Note: You may need to register an account on docker hub and run the docker login command in the terminal to access the Docker image required for cross-compilation.

When the compilation process has finished, we can move the binary to the Raspberry Pi. If you have SSH enabled on your Raspberry Pi, you can use the scp command.

scp target/<instruction_set>/release/veloren-server-cli <username>@<ip>:~/veloren/target/release/veloren-server-cli

Note: <instruction_set> refers to either aarch64-unknown-linux-gnu or armv7-unknown-linux-gnueabihf, whichever one you used to compile. Remember to replace <username> by your own username and <ip> by the IP address of your Raspberry Pi!

Creating a systemd service

On the Raspberry Pi we can now create a systemd service for the server. To do that, create a service file with the content below.

sudo nano /etc/systemd/system/veloren-server.service

Note: If you cross-compiled the binary, add an environment variable to the Service section: Environment="VELOREN_USERDATA=/home/veloren/target/release/userdata"

Description=Veloren Server


Now our service is ready and can be started.

sudo systemctl start veloren-server.service

To watch how the server starts and to see debug info, you can use the following command.

sudo journalctl -f -u veloren-server.service

In case you want to start the server every time the Raspberry Pi boots, you can enable the service.

sudo systemctl enable veloren-server.service

Monitoring the server

When the server is running, you can watch your Pi's performance with tools like htop or set up a Prometheus server to scrape metrics from your Veloren server at the addresshttp://<ip>:14005/metrics.

Configuring The Server

Whichever route you chose for hosting the server, you might want to configure it. This section contains an explanation of all the config files related to a Veloren server, their purposes and contents.

The userdata folder structure

After running veloren-server-cli for the first time, a userdata folder will be created, containing all of it's configuration and data. It's contents will look like this:

├── server
│   ├── saves
│   │   └── db.sqlite
│   └── server_config
│       ├── admins.ron
│       ├── banlist.ron
│       ├── description.ron
│       ├── settings.ron
│       └── whitelist.ron
└── server-cli
    └── settings.ron


This folder is the most interesting to us. It contains various important configuration files.


This file contains a list of UUIDs of players with administrator privileges.

You need access to server console to modify this file.




This file contains the list of banned players, and associated information about each ban.

Server admins can use in-game commands to modify this file.


    "7ea1a4cd-3002-4fe6-957e-4483f3fda3e7": (
        username_when_banned: "YuriMomo",
        reason: "No testing bugs on this server >:(",


This file contains the server description (also known as 'Message Of The Day' (MTOD)), and server rules.

Both support localisation. If the user's locale matches one of the entries, they will see the corresponding localised entry for both.

If the rules field is set to Some("...") rather than None, users will see the rules when they first join the server, with a mandatory 'accept' button (any changes to the rules will also cause them to be shown to users again).

The default_locale field determines which set of descriptions users are shown if their locale does not match any of those present in the file (by default, this field is "en" i.e: English).

Server admins can use in-game commands to modify this file.


    default_locale: "en",
    descriptions: {
        "en": (
            motd: "This is the best Veloren server",
            rules: None,


This is the file containing most of the configuration options.

Most fields are self-explanatory, but more information can be found here.

You need direct access to the server files to modify this file.


    gameserver_address: "",
    metrics_address: "",
    auth_server_address: Some(""),
    max_players: 100,
    world_seed: 25269,
    server_name: "Veloren Alpha",
    start_time: 32400,
    map_file: None,
    max_view_distance: Some(65),
    banned_words_files: [],
    max_player_group_size: 6,
    client_timeout: (
        secs: 40,
        nanos: 0,
    spawn_town: None,
    safe_spawn: true,
    max_player_for_kill_broadcast: Some(20),

Note: While you can use a custom auth server, if you do it, players will see a security warning when connecting to your game server.

Note: While you can disable authentication completely, it would allow anyone to log in using any username, including as a server admin.

Explanations of non-obvious options:

  • Some values use the Option type, which means they can either be set to either Some(value) or None.
  • max_player_for_kill_broadcast might sound scary, but it only prevents chat spam by only sending death messages of others to their group and nearby players if the set player count is exceeded. Setting it to None means the server will never broadcast kill messages globally.


If this file is not empty, only players whose UUIDs it contains will be able to join the server.

Server admins can use in-game commands to modify this file.




This folder contains the server database.


This folder only contains the settings.ron file with the following contents:

    update_shutdown_grace_period_secs: 120,
    update_shutdown_message: "The server is restarting for an update",

It allows you to customize the waiting time before restarting to update the server, and the message it uses when warning players about that. This is only used by the Docker hosting method.


Veloren is primary an action-adventure RPG rather than a sandbox building game. Despite this, it does provide some features that allow for limited in-game building.

Build Mode

Build mode can be enabled with the /build command. When enabled, players can add (Right Click), remove (Left Click) and pick (Middle Click) blocks in build regions for which they have permission. Build mode is not considered a canonical part of the Veloren experience. It is a fun feature to use if you wish to experiment with the game's features.


By default, there is a region that covers the entire world named world. You can enable permissions for it with /permit_build world (this requires admin permissions).

The vox_spawn branch

There exists a highly experimental branch called vox_spawn. It adds a client-side command that hooks into build mode and uses it to "3D print" (row by row) .vox models into the game world. Generally, this process is fairly quick and all but the largest models typically take less than a minute to fully spawn in. If you're an admin wanting to spawn structures into your world, it might be worth designing the structures with a voxel modelling tool first and using vox_spawn to spawn them into the world to avoid the structure being lost forever if the chunk unloads.


By default, Veloren does not persist changes made to the world. Unloading a chunk will lead to any changes made to it being lost. However, as of 2021-08-14, Veloren has an experimental persistence system built into the game. It is not enabled by default.


To enable persistent building, the persistent_world feature must be enabled when compiling the game (this is enabled by default). In addition, the server must have the experimental_terrain_persistence flag set to true in the server settings.ron file (this also works for singleplayer). This flag does not exist in the settings file by default and must be added manually by the server owner.

Once enabled, you will see a log entry in the server console (or the main game console if in singleplayer) on startup, as well as a message when toggling build mode.

Important Information

The experimental terrain persistence is not an officially supported feature. While some attempts are made to not arbitrarily break things between subsequent updates, this is not a guarantee and it is quite possible that updates may corrupt, delete, or otherwise break persisted terrain data at any time. Additionally, no stability guarantees are made (although you can still report bugs relating to the feature): enabling the feature may result in crashes, instability, lag, etc.

The experimental terrain persistence feature is not simply unfinished: it is a stop-gap until a proper, more restricted player-oriented building system is developed. It is not intended to evolve into such a system, nor is it intended to be compatible with it: it exists only to facilitate server admins adding minor customisation to their servers, to be enjoyed by players, until such a time at which a reliable, forward-compatible, player-oriented building system is developed.

As one might expect, updates to the game can often subtly (or not so subtly as the case may be) break persisted terrain data. For example, significant changes to world generation may result in structures built with the system appearing at the wrong altitude, clipping inside of other generated structures, or perhaps even overridden/removed entirely. As before, no guarantees are made about this. If world generation changes significantly or you switch out the map file, the best thing to do is probably to remove the terrain directory and start afresh.

How does it work?

On server startup, the terrain persistence system creates the {DATADIR}/terrain/ directory if it does not exist already where {DATADIR} is the server's data directory (userdata/singleplayer/ or userdata/server/, in most cases). This directory can be changed using the VELOREN_TERRAIN environment variable.

The feature hooks into various actions performed as the game runs: newly loaded chunks will have persisted changes applied on top of them, and unloaded chunks will have their changes persisted to disk. Any modifications made via either build mode or the /make_sprite and /make_block commands will be recorded. The same does not apply to other kinds of block modification: blocks mined with the pickaxe or discolored/destroyed with explosions will not be recorded. This means that players are not able to permanently damage structures spawned in by server admins.

See the original merge request for more detailed technical information.

What is it for?

As mentioned, the terrain persistence system is not intended to be player-facing. Build mode is neither intuitive nor well-integrated into the rest of the game. We do not account for it in any of the game's existing mechanics, and it is even possible to cause the server and clients to crash, lag, or freeze if building at an altitude that is too high or low.

We intend terrain persistence to be a way for server admins to customise the experience of the server for players with pre-built structures that may be interacted with. Below are a few ideas to get you started:

  • Gliding courses demarcated with pillars and hoops for glider racing

  • A custom spawn zone complete with crafting stations and meeting areas for players

  • Mining challenges (using mineable blocks like WeakRock and ores) that players can partake in. Because mining is not persisted, any mined blocks will naturally regenerate when the chunk reloads!

  • Custom mazes and climbing/jumping challenges for players with rewards in the form of chests/ores/etc.

  • Pixel artwork and sculptures dotted around the world for players to find

  • Visual customisations to existing world structures like towns and dungeons that make them more interesting to explore

  • PvP or PvE arenas for players to battle monsters and each other in an environment where others can watch

If you do something neat with this feature, feel free to tell us! It might even get featured in the weekly blog!

Environment Variables

Veloren uses special environment variables to affect game behaviour. Environment variables should be set before starting the game, search for tutorials on how to do it in the web.

NOTE: this list is incomplete, and needs to be expanded.


Optional variable to point to veloren assets directory. Not needed if you use Airshipper, but may be useful in more more exotic scenarios.


Variable to add directory with assets overrides. Recommended if you want to modify some files, for example different weapon textures.

Linux example:

env VELOREN_ASSETS_OVERRIDE="/home/user/veloren/override_assets/" airshipper run

If you have $VELOREN_ASSETS_OVERRIDE/voxygen/voxel/weapon/caladbolg.vox with your modified version of caladbolg.vox, it will be used instead of main caladbolg.vox file in veloren assets.


May be helpful if your game crashes for no reason. Alternatively, you can choose it in Airshipper GUI.

Possible values:

  • "vulkan"
  • "metal" (macOS only)
  • "dx12" (Windows only)
  • "dx11" (Windows only)
  • "primary"
  • "opengl" (not supported at the time of writing)
  • "secondary"
  • "all"

Generating or loading a custom world

  1. Open your singleplayer or server's settings file. See here.

  2. Set your custom world_seed, and map_file to Some(Save(())).

  3. Launch your game as normal, whether you're doing it through singleplayer or the server cli.

  4. The generation process can take a significant length of time, with little indication that it's running properly. 10 minutes on a good CPU is expected, for standard-sized worlds. Eventually, it will load into the new world.

  5. The world will be saved in a maps folder, as a binary file. Set map_file to Some(Load("maps/<filename>.bin")),, else it will try to regenerate it each time.

map_file Options

NoneLoads the default world map, located in the assets/world/map folder.
Some(Generate(([options])))Generates a new world, using world_seed, and starts the server using it. Does not save the resulting world file.
Some(Save(([options])))Same as with Generate, but will save the world as a binary file in a maps directory.
Some(Load("maps/example.bin"))Loads a map from file

Generation Options

The options above can be filled out to change the size of generated maps, and to change the scale of mountains within them. Options you do not wish to change can be left blank, and will be replaced by defaults, however you must keep the spare braces. Manually writing out the default set of options would give Some(Save((x_lg: 10, y_lg: 10, scale: 2.0))).

World size

x_lg and y_lg give the binary logarithm of the number of chunks along each axis of the world, that is, x_lg: 10 results in a world 2^10=1024 chunks wide.

Each increment doubles length, and each decrement halves it. Rectangular worlds are fully supported, however each doubling of each dimension also roughly doubles world generation time and RAM consumption, which can quickly get out of hand.

A maximum of 14 is supposed to be supported in each dimension, giving a square world 524 km across, roughly equivalent to the United Kingdom in area, but it would look pretty bad due to the current lack of tectonics simulation, which becomes more important at larger scales. 13x13 is the largest so far attempted.

World scale

scale simply changes the scale of mountains, landmasses, etc. A value of 4.0 grants a roughly Earthlike scale, although a larger-than-default world is recommended for this. Going beyond 4.0 is not considered supported, but generally works. As a guide, the tallest mountains will be a little taller than this value, in kilometres.

Loading a pre-generated map with a specific seed

Navigate to your server's or singleplayer settings file like shown here.

In there

  1. Change the world seed, e.g. world_seed: 40382,
  2. Change map_file to something like
    map_file: Some(Load("userdata/server/maps/map_1624935538562.bin")),
  3. Optionally you can also set a spawn town: spawn_town: Some("Elden"),

Make sure to use the correct file path (from the root of your veloren folder) and filenames!
There needs to be a , behind all of these inputs or the server will use the fallback settings template file.

Note: The file path used in this example requires the creation of an additional folder called "maps" inside the userdata/server folder.

Map Viewer

If you are able to compile, you can also try an example map generator and viewer application. Run the following command from your local repository, depending on preferred terminal.


RUST_LOG="info,veloren_world=debug" cargo run --release --example water

Windows, cmd:

set RUST_LOG=info,veloren_world=debug&& cargo run --release --example water

Windows, PowerShell:

$env:RUST_LOG="info,veloren_world=debug"; cargo run --release --example water

By default it will load the default world from the assets folder. Input a custom seed here, and change two lines below if you want to generate or load a different world.

This method will indicate progress through world generation, progressing from Erosion iteration 0 through to 99, and so is recommended for larger worlds.

Once the map loads, the default view shows temperature and humidity overlays. Press T and H to disable them, respectively, and M to enable real map colours. F4 will take a screenshot.

The map viewer is somewhat unresponsive, so you may need to hold keys for a moment for them to take effect.


If loading a custom world fails or the default map is still loaded, double check you haven't mistyped any of the settings. A common mistake is forgetting to place one of the trailing commas inside the settings .ron file(s).


Veloren runs on many operating systems, architectures, GPUs, and system configurations. Sometimes, things don't work!

This page contains a list of common problems and solutions.

Use the links below to navigate to the section most relevant to you. You can also use the search functionality at the top of the page to search for keywords.

If you've found a solution to a problem that wasn't mentioned here, you can contribute to this section!

If you can't find a solution to your problem here, you can ask for help from the community:

If you think you've encountered a more serious bug, you can report the bug on GitLab.

⛔ Crashes

Although we try to ensure that Veloren is as stable as possible, there are a small number of things that can cause the game to crash. Thankfully, many of these are fixable!

Airshipper won't start (or crashes on startup)

Possible solutions:

Compatibility Mode

Airshipper can run in a mode where the user interface does not appear, known as 'compatibility mode'. In this mode, Airshipper will automatically download and run the latest version of Veloren for you.

  • On Windows, compatibility mode can be used with the dedicated 'Airshipper: Compatibility Mode' icon

  • On all platforms, entering airshipper run into your console will start Airshipper in compatibility mode

Veloren (Voxygen) crashes on startup

Possible solutions:

🎨 Graphics

Veloren requires that your computer supports one of the following:

  • DirectX (Windows only, version 11.2 or above)
    • (note: recent versions of Airshipper require DirectX 12, but compatibility mode should still work)
  • Vulkan (Windows and Linux only, version 1.2 or above)
  • Metal (Mac OS only)

If your computer does not support one of these, you may not be able to run the game.


Running Veloren might require that you update your graphics drivers, or install them if you do not already have them.

  • If running Windows, you can follow this guide to update your graphics drivers

  • If running Linux, you can follow this guide to install Vulkan drivers. Please note that many distributions do not have Vulkan drivers pre-installed: the fact that other games run fine is not an indication that you have Vulkan drivers installed!

  • If running Mac OS, you may need to perform a system update to obtain the latest drivers

Graphics Backend

On some platforms, Veloren can be run using one of several different graphics APIs.

You can switch between the available graphics backends in the Airshipper Settings.

  • On Windows, the following graphics backends are supported:
    • DirectX 11
    • DirectX 12
    • Vulkan
  • On Linux, only Vulkan is supported (however, Veloren has been known to run well through WINE using backends supported on Windows, so this may be an option for you)
  • On Mac OS, only Metal is supported

If you're running Airshipper in compatibility mode, you can still change the graphics backend by running airshipper config into your console. You will be presented with a menu that will allow you to configure Airshipper's settings in a similar manner to the GUI.

Changing the graphics backend in compatibility mode

In older versions of Airshipper, you can still change the graphics backend by opening the file airshipper_state.ron in a text editor. Toward the bottom of the file is the following line:

wgpu_backend: Auto,

You can replace Auto with one of DX11, DX12, Vulkan, or Metal (depending on your operating system). Please note that this field is case-sensitive.

Airshipper is missing UI elements or flickers when moving the mouse

Airshipper graphics problems

To fix this, you may need to update your graphics drivers.

Graphical glitches in-game

In-game graphics problems

You may need to update update your graphics drivers.

Alternatively, switching to another graphics backend may solve the problem.

Ensure that your computer has the required graphics support.

🎧 Audio

Audio not working

On Linux, you might need to install ALSA configuration for PulseAudio.

  • For Arch Linux, this means installing the pulseaudio-alsa package. You can do this with pacman -S pulseaudio-alsa

Disabling Audio

In particularly dire cases, it may be necessary to disable audio in Veloren to avoid crashes or similar problems. You can do this by:

  1. Making sure Veloren is closed.
  2. Locating settings.ron (See where Airshipper stores files)
  3. Editing it and replacing output: Automatic with output: Off. It should look like:
  audio: (
    master_volume: 1,
    music_volume: 1
    sfx_volume: 1,
    max_sfx_channels: 10,
    output: Off, // The important line!
  1. saving the file and running the game again.

🎮 Input and controllers

Mouse is invisible or window resizing isn't working properly when using Wayland on Linux

Although Veloren does support Wayland, this support can sometimes be buggy. These problems may be fixed by explicitly specifying an xcursor theme for the program to use. To do that, first run the following command in a terminal to get a usable theme:

find /usr/share/icons/ -type d -name "cursors" | head -1 | awk -F / '{print $5}'

Set the XCURSOR_THEME environment variable to the result. If you got Adwaita, for example, you would do the following:

  • If using Airshipper, add XCURSOR_THEME=Adwaita to the 'Environment Variables' field in the settings

  • If running as a standalone program, have your desktop environment set XCURSOR_THEME to Adwaita when running the game

  • If running via the command line, prepend XCURSOR_THEME=Adwaita to the command you use to run the game, like XCURSOR_THEME=Adwaita ./veloren-voxygen

If that doesn't work, you can try using the xwayland compatibility layer when running.

  • If using Airshipper, add WINIT_UNIX_BACKEND=x11 to the 'Environment Variables' field in the settings

  • If running as a standalone program, have your desktop environment set WINIT_UNIX_BACKEND to x11 when running the game

  • If running via the command line, prepend WINIT_UNIX_BACKEND=x11 to the command you use to run the game, like WINIT_UNIX_BACKEND=x11 ./veloren-voxygen

PS4 or other controller not working

Currently only XInput controllers are supported on Windows. This means that controllers like the PS4, Switch, and some older generic controllers may not work with Veloren.

In order to work around this, a program such as DS4Windows can be used. Both a text and video tutorial on how to use DS4Windows can be found here.


On this page you'll find tips and tricks to help you get the most out of Veloren.


Veloren's world might be mostly made of cubes, but don't be fooled! Veloren's world is expansive and detailed and the base game has many graphical effects. On highest settings, Veloren can require a very powerful computer to run. Do not expect to be able to throw all of the sliders up to their maximum and expect the game to run perfectly.

Identifying your bottleneck

Most of the time, poor performance in Veloren results from one of 3 'bottlenecks'. See below for information about these cases, how to identify them, and how to rectify them.


If you're fragment-limited, performance gets worse if the amount of time required to render each pixel increases. If reducing your internal resolution improves your framerate, this likely applies to you. To rectify this situation, you can:

  • Reduce internal resolution (an anti-aliasing technique can improve the look of the game at lower resolutions)
  • Reduce cloud rendering quality
  • Switch to fluid rendering to 'cheap'
  • Lower shadow map resolution or switch to 'cheap' shadows
  • Reduce or disable bloom


If you're vertex-limited, anything that results in the game rendering more polygons to the screen worsens your performance. If reducing sprite view distance improves your framerate, this likely applies to you. To rectify this situation, you can:

  • Reduce the view distance (reduces the amount of terrain the game must render)
  • Reduce the sprite/entity/entity detail view distance
  • Reduce the LoD distance
  • Reduce LoD detail


If you're CPU-limited, the performance of the game is limited by the speed of your CPU and not the GPU. If your CPU usage is regularly very high, this likely applies to you. Sadly, these are a limited number of things you can do to rectify this situation because most of the CPU's work is essential to the functioning of the game. That said, you can:

  • Reduce your view distance (fewer entities and less terrain data to process)
  • Switch to multiplayer (now it's the server's job to simulate the world and generate terrain)
  • Close any other programs you may have open

What compromise are you looking for?

Veloren has a much larger number of settings (and a wider range of those settings) than most other games. We don't like it when games artificially limit the way we play, so Veloren is designed to allow you to choose the effects you care about. Here are a few archetypes you might fit into, along with some tips you might want to follow:

The pixel perfectionist

You care about precision. It frustrates you when games have aliasing artifacts. You expect every pixel to be an immaculate work of art in its own right. You're the sort of person that plays Morrowind, but only with 8x super-sampling. You might want to:

  • Increase 'Internal Resolution' (more than 1.0x corresponds to super-sampled anti-aliasing, i.e: SSAA)
  • Disable FXAA (it can create subtle artifacts)
  • Increase shadow map resolution

The low-power underdog

You just want Veloren to be playable on your hardware. You're willing to sacrifice the more fancy graphical effects, but ideally without the game looking like the arse end of a donkey. Anything above 20 fps and 240p is a success in your books. You might want to:

  • Switch to 'cheap' shadows
  • Switch cloud rendering to 'low' or 'minimal'
  • Reduce internal resolution (you can enable an anti-aliasing technique like FXAA or HQX to soften the blow)
  • Switch 'fluid rendering' to 'cheap'
  • Reduce the maximum FPS to avoid your GPU overheating
  • Try enabling the 'BareMinimum' experimental shader

The god-ray god

You sprinkle bloom on your breakfast cereal every morning. You're not happy until your game looks like an underwater disco. The only program you run more than Veloren is 'ReShade'. You might want to:

  • Increase 'bloom'
  • Increase 'point glow'
  • Switch 'light rendering mode' to 'high'
  • Increase cloud rendering to 'high' or even 'ultra' (beware: very expensive)
  • Decrease 'internal resolution' to free up your GPU for more post-processing effects
  • Switch 'fluid rendering' to 'shiny'
  • Enable 'camera smoothing' in 'Gameplay' for improved aesthetics
  • Give some of the experimental shaders a try

The 144hz gamer

Your senses have been honed over decades to detect sub-millisecond latencies. Back in the day, you ran consoles in NTSC configurations for the extra 4.97 frames per second over PAL. Merely glancing at a screen with a refresh rate in the double digits causes you to vomit. You've already disabled 'motion interpolation' on your TV, and the TVs of everybody you know. You might want to:

  • Increase the maximum FPS to 'unlimited'
  • Switch 'present mode' to 'vsync uncapped' to reduce tearing
  • Reduce 'internal resolution' so your GPU has less work to do per frame
  • Switch to 'exclusive fullscreen' to minimise any latencies that might be imposed by your window manager
  • Ensure that 'camera smoothing' is disabled in the gameplay settings
  • Use the 'GPU timings' tool to figure out what areas of rendering are taking the most time

Veloren for Contributors

Thank you for your interest in contributing!
Make sure to read the Introduction section and if you want the For Developers section.

Otherwise feel free to jump around as you need.

Veloren for Contributors

This section of the book will give an overview on how to contribute to Veloren no matter if you got a degree or taught yourself. Shall it be code, assets, creatures, bug fixes, or the book itself!

Note: In this guide we assume basic computer knowledge and some curiosity to learn about what we do here by yourself.


If you want to contribute to Veloren in any form you probably need to deal with Veloren's source code. Therefore these basic tools have to be installed to interact with it.

Note: Throughout the book we will mention a lot of commands. Therefore we highly recommend getting comfortable with a terminal.


Keeping track of Veloren's history.

For Windows, The 'Git for Windows' suite is a sensible way to install Git, along with a set of tools that'll make it easier for you to use.

On Linux Git is most likely already installed, if it isn't, use your distribution's package manager to install it.

On recent macOS versions you will be prompted to install Git the first time you run it. Otherwise install it using Homebrew via brew install git or MacPorts via port install git.


Keeping track of the really big giants out there (aka. asset files).

Git LFS is a Git extension used to store large files like images and audio files. You need to install it in order to download the assets.

  1. For Windows you can download an installer here.

    On Linux you can use the package manager to install Git LFS, usually the package is called git-lfs.

    On macOS you can use Homebrew via brew install git-lfs or MacPorts via port install git-lfs.

  2. Git LFS needs to be set up by running git lfs install or git-lfs install (macOS) in a terminal.

Note: If you already cloned the repo before setting up Git LFS, additional steps are necessary.

Note: git-lfs has a known bug with working off remotes. If you plan to work off a fork, refer to this section.


Keeping us safe and sound to build a reliable and efficient game.

Rust is a general-purpose programming language we use. Refer to the FAQ section to learn why.

The recommended way of installing Rust is through Rustup. Follow the instructions carefully and everything should be good.

Local repository setup and maintenance

This section describes the initial setup and maintenance of your local repository.

Note: To understand the following we highly recommend reading about git!

Download source code

Note: Veloren needs git LFS installed before cloning to be able to download the assets. If you already cloned the repository before setting up git LFS use these steps to get the assets downloaded.

Clone the repository

git clone

Change your working directory to the cloned repository

cd veloren

Note: All commands in this chapter from now on should be executed from there.

Basic repo navigation

Changing branches

In order to try out new unmerged or unfinished features, you may want to switch to a different branch.

To switch to a development branch

git checkout <branch_name>

To switch back to master

git checkout master


To download the latest changes and update your current branch

git pull

To download the latest changes without merging them into your local branch

git fetch

The help command

Git also offers a help command with detailed information about other commands

git help <optional subcommand name>

Modifying the source code

If you want to modify the source code, refer to the developer section.

To discard changes you've made to the source code

git reset --hard

Keep in mind that this deletes all the changes without a way to recover them.

To discard your changes with ability to restore them later

git stash

To restore stashed changes

git stash pop

Cleaning old build files

Over time as dependencies get updated, the old compiled versions start to take up a lot of space. To delete them type

cargo clean

NOTE: Keep in mind that cargo will need to recompile all dependencies which can take a long time.

Updating the Rust toolchain

We use a rust-toolchain file in the repository which will automatically update your rust toolchain to whichever version we use. There shouldn't be any additional effort needed on your side.

Compiling Veloren

This section covers building Veloren from rust source with cargo and running it.

Note: all commands need to be run from the repository.

Required Libraries

On Windows you will need to install the following programs:

Fortunately, there is a quick way to install most of these

  1. Download and run the Visual Studio Build Tools and install:

    • C++ tools.
    • Windows 10 SDK.
  2. Open a PowerShell terminal and run the following commands:

    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
    Invoke-RestMethod -Uri | Invoke-Expression
    scoop install cmake ninja python

    The first two lines install the Scoop package manager and the third line installs CMake, Ninja and Python through Scoop in one go.

On Linux you will need to have installed GTK3, Python and CMake.

On Gentoo you may require having to enable certain use flags for specific packages.

  • sys-devel/binutils (with the gold use flag to enable the linker)
  • media-libs/mesa (with the vulkanuse flag)

On Debian systems additional libraries may need to be downloaded, below is a non-exhaustive list:

  • libglib2.0-dev
  • libcairo2-dev
  • libasound2-dev
  • libpango1.0-dev
  • libatk1.0-dev
  • libgdk-pixbuf2.0-dev
  • libgtk-3-dev
  • libxcb-shape0-dev
  • libxcb-xfixes0-dev
  • libudev-dev
  • libxkbcommon-x11-dev
  • libxcb-xkb-dev

And a one liner to download and install them all:
sudo apt install libglib2.0-dev libasound2-dev libcairo2-dev libpango1.0-dev libatk1.0-dev libgtk-3-dev libxcb-shape0-dev libxcb-xfixes0-dev libudev-dev libxkbcommon-x11-dev libxcb-xkb-dev

On Fedora systems additional libraries may need to be downloaded, below is a command to install them:
sudo dnf install alsa-lib-devel libxkbcommon-x11-devel libudev-devel

On macOS you only need to install cmake. This can be done using either homebrew or macports. Using homebrew, enter brew install cmake or similarly, using macports enter sudo port install cmake. Note: Do not use sudo with homebrew.

Note: Feel free to open an issue incase these dependencies are incorrect.

Compile and Run Veloren

Run this in a terminal to compile and run Veloren:

cargo run

To compile without running, use cargo build instead.

Note: The initial compilation will take from 5min up to 30min therefore grab a tea and some snacks and come back later.

Compile and Run Veloren Server

cargo run --bin veloren-server-cli

Logging output

We use tracing to collect logs. They can be filtered by setting the RUST_LOG environment variable to the respective level (error, warn, info, debug, trace).

For all available filtering options visit the docs.

Tip: this works both for the server and client

Optimized Release builds

By default debug builds are created which compile faster but run a bit slower than optimized release builds. Unlike many other projects, we've set them up so they're fast enough to be playable. If you want to get optimized builds, add the --release flag when calling cargo. Keep in mind that compiling release might be very slow!

If you want get familiar with cargo we recommend the Cargo Book.

Cross-Compiling Veloren

As more and more people want to play or develop for Veloren on other platforms, it may come as no surprise that building on these platforms might not be the most elegant solution, emulation is quite often slow, and the platform of choice simply doesn't have the necessary resources to build the game in a reasonable amount of time.

Please note: Documentation of these steps is currently underway, you might need to adjust these for your specific scenario.



In order to build for your platform of choice, for example arm64, you'll need to install the compiler toolchain for that architecture. In our case, that's aarch64-linux-gnu-gcc.

You'll also need the compilation dependencies of the project installed for your architecture. In our example, we used a Raspberry Pi to install all dependencies needed for compiling the project, then the SD Card was plugged into the building system, and it's root filesystem was mounted under /mnt.


The project source tree was cloned to our building machine, in an arbitrary location. Open a terminal and move to the project root, then execute:

rustup target add [target]

where [target] is one of the targets from here. In our case, that was aarch64-unknown-linux-gnu. After this, you'll need to go in the newly created .cargo directory and edit the config file. Add the following entry:


where X was aarch64-unknown-linux-gnu in our case, and Y was aarch64-linux-gnu-gcc respectively. These should correspond with the target mentioned above, and the compiler toolchain respectively (the one you installed as a prerequisite).

For the compilation itself, you'll need to tell Cargo where the correct libraries are. Given that we've mounted the root filesystem of our target at /mnt, we can use the PKG_CONFIG_SYSROOT_DIR environment variable.

The compilation command looks like this:

PKG_CONFIG_SYSROOT_DIR=Z cargo build --release --target X

where X is the target we're building for, and Z is the filesystem root of the platform we're building for. This is where the Raspberry Pi's SD Card was mounted, in our case /mnt.

Feel free to adjust the command for your needs, as per the original compilation instructions. You should find the built binaries in the target subfolder of the project root.


At the time of writing, there is an issue with the keyboard-keynames library for aarch64 and probably others too. Assuming ~/.cargo is the default location of your Cargo downloads, edit the file located at: ~/.cargo/git/checkouts/keyboard-keynames-0b8339ee617b0344/a97ae50/src/platform/unix/ and replace all instances of

fn main() {
unsafe { &*(utf_key as *const [i8] as *const [u8]) }


fn main() {
unsafe { &*(utf_key as *const [c_char] as *const [u8]) }

after which compilation should succeed.

Before you contribute

In case you want to contribute code (or added the assets yourself to the game) continue reading. If you do not want to add your assets yourself skip to Contributing Assets.

Git Workflow

There are two main options how contributions can be made to the game. Regardless of how you decide to make your commits, make sure to follow our commit guidelines mentioned below.

Option #1: the collaboration repository

This is our suggested way of contributing to the project.

This is a public repository where anyone can make branches (after following the steps below), it's synced with the changes from the main repo on an hourly basis and regular branches are not shared between the two (the only exception is the master branch). Having a branch without forking can be more convenient for contributors as you can avoid all the shortcomings of having a fork.

To make your first contribution, follow these steps to gain access to our development repository:

  1. Join our collaboration group:
  2. Ping either Core Developers or Admins on our Discord in the #new-contributors channel (or whichever channel seems suitable). Let us know of your GitLab username and we'll be able to give you developer permissions.
  3. Head over to and clone the repository to your computer.
  4. Create a feature branch (more details about it below). You can now either work on your own or work together with others on the same branch.

The development repository is virtually the same as the main repository but everyone can manage branches in the development repository without the possibility of breaking the main repo in any way.

Naming feature branches

We use feature branches with the following naming scheme for easily identifying the owner of the branch:

git checkout -b <your_nickname>/<branch_name>

Example: zesterer/fix_scrolling_in_chat

Option #2: fork the repository

The downsides of using a fork:

  • You need to configure CI to run on your fork.
  • Maintainers can't easily make changes to your merge requests.

But you are free to choose this workflow instead of collaboration repo (see above). Go to GitLab, to the main repository (not the collaboration one) and use their fork button. Apply the troubleshooting steps in the next section to get LFS to work.

Troubleshooting Git LFS

When working on a fork instead of on a branch in the main repo, you'll need to do the following for the time being due to a bug in git-lfs:

  1. Configure git-lfs to ignore smudging:

    git config filter.lfs.smudge "git-lfs smudge --skip -- %f"
    git config filter.lfs.process "git-lfs filter-process --skip"
  2. Add Veloren as your upstream remote:

    git remote add upstream
  3. Go ahead and run git lfs pull upstream, and continue to do so when new assets are added to the repo.

Commit guidelines

Regardless of which option you picked, we want our commit history to be clean and make it easy to keep track of our past changes. In order to ensure clean commits, we've made a list of suggested practices and tips:

  • Split your changes into reasonably sized, yet logical chunks of work.

    If you feel a feature can be split into smaller pieces of work, you can reflect that with your commits. It can be hard to find a balance between what is the right amount of commits, just try making commits that make sense to you.

  • Use descriptive commit names.

    Take a moment to shortly describe what your commit changes, or even why it changes something. For example, fixes is a poor name for a commit as it doesn't tell you anything about meaningful about the commit itself. If there's an issue on GitLab that relates to the commit, you may use the issue number and title, e.g. Fixes #123 - UDP buffer overflow when too many players are on the server.

  • Use git commit --amend to change the last commit.

    For example, you pushed your change and now CI is reporting that the format check failed, now instead of creating a separate commit fixing the commit before it, run cargo fmt locally, run git add and then run git commit --amend and git push -f to fix the incomplete commit instead of creating a new one. The same applies to smaller fixes like spelling errors introduced by yourself, fix the commit where the mistake was made instead creating a new one. Do note, sometimes cargo fmt formatting rules have changed, in which case formatting may change parts of the codebase you haven't touched. In this case, feel free to make a separate commit that formats the entire codebase.

    Tip: As you may have noticed, if you already pushed to remote, you will have to force push your amended commit (both git push --force-with-lease or git push -f will work for this.)

  • Rebasing is a good way to change your commits later on.

    In case you feel you made a bit of a mess with your commits at some point, you can squash commits and change the commit names.

    1. Count how many commits your branch contains, e.g. in git status.
    2. Run git rebase -i HEAD~N, where N is the number of commits you counted in step 1.
    3. Follow the instructions in the editor. You can change a commit name by modifying the text in a line. For example, to squash commit #2 and #3 into a single commit, write squash in front of commit #3, no need to change commit #2.
    4. Run fmt on every commit in your branch (in bash) git filter-branch -f --tree-filter "cargo fmt" $(git merge-base origin/master HEAD)..HEAD

Catching up on changes to the master branch

Often when working on a feature for longer than a day or two, you might notice your branch is falling behind the master branch. Fortunately, you can catch up on any changes your branch has missed by rebasing on top of master therefore you should never merge master in your feature branch!

How to rebase on top of master

  1. First, make sure you have no uncommitted work, e.g. by creating a new commit.
  2. Run git fetch --all to get all the latest changes.
  3. Run git rebase origin/master to start rebasing. You may or may not encounter merge conflicts during, if you don't, proceed to the next step. If you do, you will have to resolve the conflicts. These usually arise from recent changes on master conflicting with changes of your own and git needs to be told which to prefer. Feel free to ask for help on our Discord with that.
  4. Run git push -f to push your rebased feature branch. It must be a force push as you've changed the existing commit history.

Tip: Run git status to see the current state of your branch.

Getting your contribution into the game

You've made a feature branch, made your commits, what now? Now the branch must be reviewed by other members; to do this you must create a Merge Request on GitLab.

Creating a Merge Request (MR) on GitLab

  1. Once your feature is ready for review, create an MR in GitLab from your branch your-nickname/your-branch-name to veloren/veloren/master.
  2. Make sure to tick the box to delete source branch in the MR. There's rarely a reason to keep the branch around after merging it. Feel free to add additional information to the description. Unless the commit history of your branch comprises of clean commits with descriptive titles, your MR will be squashed — you may preemptively check the squash commits checkbox if you want this to happen.
  3. Send a message on our Discord (if you have access in #programmers or in a working group channel otherwise in #new-contributors) and mention @Code Reviewer with a link to the MR, someone will look over it and will work with you together to get it merged.

Contributing Assets

If you never worked before with git and just want to contribute assets, post them in #veloren-art on our Discord and ask for feedback. Make sure you own the rights to the assets and agree it being publicly available under GPLv3 license. Tip: Check out the Artists section for further information.

After your first contribution

Congratulations on your first contribution and thank you for helping out! After your first contribution you should get the Contributor role on Discord which gives you access to important channels.

Joining a team

If you have loved contributing so far and want to help out further consider joining a working group by letting the respective team lead know.

Tip _You can join multiple groups and are free to work outside of the groups' focus. Mainly it helps to find out who to talk to for a specific part of Veloren.

Group members can be found and contacted via their respective discord group roles_

Audio (led by DaforLynx (@daforlynx))

Discussing, sharing and approving of music and SFX that will be featured in Veloren.

Assets & Visual Design (led by Gemu (@gemupeachems))

3D models, 2D pixel art/icons, UI design, concept art.

Balance (led by crab (@crebmen))

Balancing the mechanics and gameplay

Combat (led by Sam (@goldfalcon9))

Weapons, armor, combat abilities, enemies, and other combat-related things.

Game Design (no formal lead)

Works on designing how the game is played by the player. Designs the way the player interacts with the world, and the system they use to do so.

Meta (led by AngelOnFira (@angelonfira))

Heads up CI, the website, the Discord, and lots inbetween.

Rendering (led by imbris (@imbris))

Graphics, windowing, and UI logic for Voxygen.

Server & Multiplayer (led by xMAC94x (@xmac94x))

Create servers that can host many people, and make multiplayer experience as great as possible.

Testing (led by YuriMomo (@yurimomo))

Testing the game by using specialized tools and making sure new features don't introduce any bugs.

Translation & Localization (led by juliancoffee (@juliancoffee_ua))

We govern Veloren translations to other languages and work on improving internal localization systems so people can translate more, better and faster.

UX & UI (led by Pfau (@pf4u))

We improve Veloren's user experience and user interface by applying well-known UX practices to existing features and collecting information, bug reports from users to work out which Quality of Life improvements are needed the most.

Worldgen (led by Isse ( and Zesterer (@zesterer))

World generation and terrain generation.

Worldsim (led by Isse ( and Zesterer (@zesterer))

World simulation


1) How come you chose Rust for this game? It's not exactly the most mature language for game development.

Rust may seem like an unusual choice for a project like this. It's a new language that has yet to properly prove itself in production environments, and is still undergoing relatively rapid changes. We chose Rust because it has several unique features that we believe will come to benefit the project in the long-term.

Rust is safe Code written in vanilla Rust cannot trigger undefined behaviour. Rust's design helps us avoid a plethora of bugs common in other compiled languages such as dangling pointers, buffer overflow, invalid/null pointers, data races, array bound errors, and many more. This makes it particularly suitable for a large collaborative project such as this because it makes it difficult for new code to introduce difficult to fix bugs into the codebase.

Rust is fast Rust is a compiled language that doesn't require a garbage collector, exceptions, or many of the other runtime systems that make other languages so slow. In most scenarios, well-written Rust is at least as fast (and often faster) than well-written C++.

Rust is modular Rust comes with the Cargo build system and package manager. It allows Rust to be compiled in a modular manner, borrowing other libraries (known as crates) from the rest of the Rust ecosystem with ease.

Rust is portable Rust's compiler uses LLVM to target most major hardware platforms. By using Cargo as its build system, it allows for consistent compilation across many platforms. No more searching for header files or fighting linker errors!

Rust is well-designed Rust's syntax is designed to be user-friendly (wherever it can without compromising on features) and well-suited to system programming. Its unique combination of low-level control and safety makes it perfect for building both game engines and high-level game logic.

2) Why use GitLab over GitHub?

GitLab has better integrated CI/CD and offers everything else that GitHub has. Both of them are only a service on top of git on the computer, so not too much different.

3) What noise function do we actually use?

Perlin, worley, simplex, value, gradient, and a few Zesterer invented.

4) How can I help? Do I have to be part of a team? I don't have experience in Rust but really want to learn and help.

Generally speaking, you can help in every area you want to. You don't have to become part of a team. But as soon as you helped a bit and showed that you are interested you can get in the respective "team".

5) How is the movement/physics/mechanics programming handled?

That's implemented in common, which is a crate for code that's common between both the server and the client. (because the server needs to be the ultimate authority on physics, but the client needs to do physics prediction so that lag/latency doesn't look bad).

6) Does it have all the OOP stuff you need for a project like this? Are there times when you are coding in Rust and there is something you feel could be expressed much better in C++? I originally dismissed Rust when I first encountered it since it looked like it was just C with different syntax and some functional programming stuff, but I heard recently it is supposedly much more than that.

Although Rust has features that on the surface appear to make it an object-oriented language (it has objects, methods, interfaces, etc.) it's not actually an object-oriented language. One of the common trip-ups new developers make is to try to force Rust to behave like an OO language when a particular problem is better solved in a more Rust-y way.

7) What flexibility does Rust provide that Unreal Engine does not? Is it simply because Rust makes the project modular while Unreal Engine is not modular enough for open source development?

A voxel game is a rather specific kind of game. It deals with a lot of data that most engines simply aren't really designed to deal with. Along with that, a lot of the game is procedural, something that existing asset-driven engines aren't too well equipped to deal with either. An existing engine, for us, would provide relatively few advantages despite providing several pretty significant disadvantages.

8) Do you guys ever want to take this project to a fundraising platform like Kickstarter so that someone can work on it full time? Is it possible that this could become a goal one day? Or will this never be a goal?

We probably won't go that route, though I guess it's hard to say anything for sure. We see this as a volunteer project. It's more likely that any fundraising we do would go towards maintaining servers and such.

9) I got a question on how to compile the game?

Everything should be described in the Contributors section.


Incase you've hit an issue this section might help you resolve it.


If LFS is not installed and setup properly the lfs pointers will not be replaced with actual assets. This produces an error when running Voxygen where it complains about the validity of whatever filetype it is trying to load.

Check status

To check if Git LFS works correctly:

git lfs status

When LFS was not setup before cloning the repo

Windows and Linux

To setup LFS and download the asset files on Linux or Windows

git lfs install
git lfs fetch
git lfs checkout


git-lfs install
git-lfs fetch
git-lfs checkout

Git pull/rebase failed due to a smudging error/404

This is a known bug with git-lfs itself and has a nice workaround. Refer to this section here.

When using Mingw64 (Windows)

Git LFS fails download the files properly. The main issue seems to be that the askpass program is not spawned when using a normal CMD prompt, preventing Git LFS from authenticating via SSH to retrieve the temporary access token. Setting the SSH_ASKPASS, GIT_ASKPASS and DISPLAY variables seems to solve this issue:

SET "SSH_ASKPASS=C:\Program Files\Git\mingw64\libexec\git-core\git-gui--askpass"
SET "DISPLAY=required"

Migrating from submodules

If you used the previous submodules system, you can deactivate it with:

git submodule deinit --force --all

Autoformat with git commit hook

You can setup a git commit hook to automatically format your code before committing if your IDE doesn't support it by default. Just create a file .git/hooks/pre-commit with the following content.

# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments.  The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
# To enable this hook, rename this file to "pre-commit".

# run rustfmt to auto check changed files
changefmt=$(git config --bool hooks.changefmt)

rustup component add rustfmt-preview
if [ "$changefmt" != "true" ]
  exec cargo fmt --all -- --check
  echo "change files via fmt"
  cargo fmt --all --
  echo "adding all files via git add ."
  exec git add .

# enable change to make fmt change files instead of just warn
# git config hooks.changefmt true


Make sure you have all runtime dependencies installed.

Tracking Issues

For very large, complex, or long-running features we maintain 'tracking issues': large issues that summarise information about the feature and its development progress. Implementing large features often means implementing many smaller ones, so it's important to keep track of them to avoid confusion and to keep the community up to date.

Note that several tracking issues might be out of date or lacking community consensus: take a look at the roadmap if you're looking for a list of planned features with broad agreement from the community!

Here follows a list of currently existing tracking issues. Feel free to contribute to this section if you think something is missing!


Platform Support


Developers bug-free sky

Introducing the power of Rust development.

Installing an IDE

Before being able to comfortably modify Rust code you will need to install an IDE.

TIP: Checkout the rust tools page to find common IDEs which support Rust and install the respective plugins.

Learning Rust

There are a lot of resources to learn about Rust.

For the basics we recommend taking a look at the book and the cookbook.

After that you can start familiarizing yourself with the codebase.


Veloren uses an Entity Component System (ECS). This is a relatively new paradigm in game engine development that competes against traditional object-oriented design models that make heavy use of hierarchy, inheritance, and polymorphism. It encourages game developers to design data structures in a way that allows for efficient batch processing of data on modern CPU architectures with deep caches by storing batchable data contiguously in memory.

Traditionally, the representation of entities within a game are done like so:

fn main() {
struct Entity {
    position: Vec3<f32>,
    velocity: Vec3<f32>,

When representing multiple entities, it's common to use an array-like data structure.

fn main() {
struct World {
    entities: Vec<Entity>,

However, this comes with problems. Modern CPUs have deep caches, meaning that they are significantly faster at accessing memory that is closer in the address space to memory they have already accessed. The most efficient storage formats pack data to be processed very close together in memory. Our current representation looks like the following:

| Entity 0            | Entity 1            | Entity 2            |
| position | velocity | position | velocity | position | velocity |

Let us imagine a 'typical' operation that we'd like to perform: applying gravity to the entities. This involves adding 9.81 in vertical velocity to each of the entities. Unfortunately, the access pattern of this operation involves touching each velocity field, but skipping each position field. These gaps in our data make the operation slower. In technical jargon, we call this a lack of 'cache coherency'.

All is not lost.

A design pattern you might have heard of is called Struct Of Arrays, or SOA. It suggests that instead of packing the data associated with each entity together in one place, we should instead group data according to its purpose.

fn main() {
struct World {
    positions: Vec<Vec3<f32>>,
    velocities: Vec<Vec3<f32>>,

Now our representation is much more densely packed and our application of gravity to entities is more efficient because we no longer need to skip over the position data while iterating through entity velocities.

| Entity 0 | Entity 1 | Entity 2 |     | Entity 0 | Entity 1 | Entity 2 |
|----------|----------|----------| ... |----------|----------|----------|
| position | position | position |     | velocity | velocity | velocity |

ECS is this idea taken to its logical conclusion: entities as associated but separate collections of components, with each type of component stored in its own distinct storage buffer. This approach comes with more advantages too: because components are stored separately, it is easy and fast to add or remove components from an entity as the game is running, thereby altering the behaviour of the entity and its capabilities. This is a remarkably powerful technique and allows for what amount to the ability to radically alter the behaviour of the game and the entities within it while the game is running and without sacrificing performance.

The specific ECS crate that Veloren uses is SPECS. You can read more about ECS and the specifics of how SPECS works here. If you're looking to work on Veloren, I strongly recommend reading this resource from cover to cover (it's quite short).

Project Architecture

When we started developing Veloren, we set out to with several aims in mind.

  • Modularity: The project should be composed of many interlocking pieces
  • Performance: The project should avoid architectural choices that constrain performance
  • Avoiding lock-in: The project should avoid forcing the use of certain components where possible


Veloren is split into several Rust crates. The purpose of this is twofold.

  1. Reduce compilation time by allowing parallel processing of crates during compilation

  2. Allow users of the Veloren ecosystem to only depend on specific parts of the project


If you've spent any time around games with an active modding scene, you've no doubt come across games that have had entirely new graphical frontends written for them that allow you to play the game using different graphics or that view interesting game data that the default game doesn't usually display, such as the Legends Viewer of Dwarf Fortress. These frontends are often hackily constructed, requiring direct memory access to the game's RAM, lack significant features, or require the main game to be running in parallel.

Veloren ditches this approach and instead makes frontends a first-class abstraction. voxygen, the default graphical client frontend, has no inherent coupling with the internal client library. It's possible to write entirely new frontends that display the game's contents in a vastly different way on top of the generic client library. Examples of such alternative frontends include:

(Is something missing from this list? Feel free to add it)


Read the docs for this crate

Voxygen is the default client frontend for Veloren and is the program that users most commonly interact with. It is a fully maintained and features a fully 3D view of Veloren's world and makes use of all of the game's client features.


Read the docs for this crate

server-cli is the default server frontend for Veloren. It allows running Veloren servers via a simple command-line interface that includes both a 'basic' mode (streaming output to stdout/stderr) and a more complex mode that allows the inputting of server commands via a simple ncurses-style terminal interface.


As mentioned, Veloren implements core gameplay functionality through headless developer-facing libraries. These are:


Read the docs for this crate

The core server implementation of Veloren, with all the bells and whistles. It includes APIs for server frontends to query game state, inject events (such as server-wide broadcasts), and load plugins. In the future, we imagine a plethora of server frontends catering to many requirements: simple graphical frontends for players wanting to host a LAN game with friends, or a powerful CLI server frontend backed by a web control panel that allows precise control over game state and advanced features such as live maps or civilisation stats viewable on the web.


Read the docs for this crate

The core client implementation of Veloren. It is non-prescriptive about how a client frontend displays data and allows clients to connect to servers through one of many 'modes' including chat-only, spectator, and character. The default client frontend, Voxygen, is 3D, but there's no reason as to why other client frontends couldn't implement displaying the world using isometric graphics, Dwarf Fortress style layered 2D graphics, or any other representation one could imagine.


Read the docs for this crate

The core world generation implementation of Veloren. The use of this crate is a little more nebulous since world generation and simulation are under active development, but this crate is intended to allow viewing, generating, and simulating a Veloren world without a client or server being associated with it. In the future we imagine frontends existing that allow viewing aspects of world history like Dwarf Fortress' Legends Viewer, or editing of world data to allow for custom worlds and scenarios.

Utility crates

Many other crates in the ecosystem are utility crates that contain functionality common to many other crates. These are not intended for consumption by anything but the core Veloren libraries and should be treated as an implementation detail. These are:

common (and its sub-crates)

Read the docs for this crate

Implements behaviour and contains definitions that are common to both client and server.


Read the docs for this crate

Contains the raw implementation of Veloren's networking utilities.


Veloren has recently gained a plugin API that allows for the development of additional features on top of the core Veloren experience. While the plugin API is still extremely experimental, we envisage it soon becoming the standard way to expand the game's features. Plugins are written in any language that may compile to Web Assembly (WASM), although Rust is so far the only language with official support and bindings. Plugins are fully sandboxed and get shared with clients when connecting to a server. Plugins may have server-side and client-side behaviour contained within the same package.

There are several crates associated with plugins:


Read the docs for this crate

The core plugin runtime. This crate facilitates communication with the host engine and manages plugin hooks and IO.


Read the docs for this crate

Contains type definitions that constitute the plugin interface used to communicate with Veloren. This includes types and structures used to represent in-game state and communicate about changes in that state.


Read the docs for this crate

Includes utility procedural macros for setting up a plugin, automating some of the more complex APIs provided by plugin-rt.

Coordinate Systems

Various coordinate systems are used for different tasks throughout the codebase so it can be useful to have a reference for how they work and relate to each other.

A not necessarily exhaustive list:

  • "world" coordinates
  • chunk coordinates
  • weather sim cell coordinates
  • "regions" used on the server for syncing to clients
  • coordinate spaces used during rendering in voxygen
  • LoD zones (see common/src/

Note: This document is unfinished and details for more of these could be included.

World coordinates

World coordinates can actually be broken down into two different kinds.

There are non-integer positions currently represented via Vec3<f32>, e.g. which can be used to represent an entity position.

Then there are integer positions currently represented via Vec3<i32>, e.g. which can be used for the position of a voxel in the world. The coordinates of the voxel containing a Vec3<f32> point can be obtained via .floor() as i32 on each element of the Vec3. Consequently, when the integer position of a voxel is directly converted to a Vec3<f32>, this is located at the minimum corner of that voxel. To obtain the center of a voxel in that space 0.5 must be added to each element of the position.


This section covers some helpful debugging tips within the Veloren project. This should help if you wish to explore the code base at runtime, or work on implementing a feature.

Compiling With Debug Symbols

In order for debug symbols to be generated for the project, the debuginfo profile must be used. You can build the project with debug symbols included by running this command:

cargo build --profile debuginfo

Visual Studio Code

Follow this guide to setup your VS Code installation.

After that make the following modifications to launch.json (remember to build with the cargo command listed above!)

  "version": "0.2.0",
  "configurations": [
      "name": "(Windows) Launch",
      "type": "cppvsdbg",
      "request": "launch",
      "program": "${workspaceRoot}\\target\\debuginfo\\veloren-voxygen.exe",
      "args": [],
      "stopAtEntry": false,
      "cwd": "${workspaceRoot}",
      "environment": [],
      "externalConsole": true
      "name": "(OSX) Launch",
      "type": "lldb",
      "request": "launch",
      "program": "${workspaceRoot}/target/debuginfo/veloren-voxygen",
      "args": [],
      "cwd": "${workspaceRoot}"

JetBrains Integrated Development Environments

Please do note that debugging on JetBrains IDEs is only supported on a small subset of their products (like CLion or IntelliJ Idea Ultimate). Visit this link for further information.

Install This plugin in your IDE (either via File -> Settings -> Plugins [Ctrl + Alt + x], or via your browser) and open your rust project in the IDE.

Click the button "Add Configuration..." in the upper right corner. This will open a window giving you the ability to create launch / debug profiles.

Click the little "+" button and select "Cargo in the dropdown". This will create you a launch profile.

Edit the "Name" field however you want. Then here's the interesting part : Editing the "Command" field

By default, the "Command" field should have "run" in it, keep it and add "--bin {bin} --profile debuginfo" where bin is the name of the binary to debug (veloren-server-cli, veloren-voxygen, ...).

The "Command" field should then contain something similar to "run --bin veloren-server-cli --profile=debuginfo".

If you have any question, please reach out to me (infrandomness#4003) on the Veloren Discord server.


Note: Some users have reported needing to run VSCode as an administrator for debugging to work correctly. If you notice an error message similar to below, then try re-running VSCode as administrator.

Unable to open '': Unable to read file (Error: File not found

Performance Analysis

You want to improve Veloren's performance? But you don't know how to best measure Veloren's performance ? This page is a collection of tools that are already integrated in veloren and can be used to help you collecting data.

Compiling With Release & Debug Symbols

Most tools work better with debug symbols AND in release mode: You can build the project with debug symbols included by running this command:

cargo build --profile releasedebuginfo

Integrated tooling


Prometheus allows you to gather internals of veloren during runtime. The data points are aggregated (e.g. all entities, state tick time spend in physics system). It allows to get a quick, rough look into Veloren's performance, but is not very detailed.

Prometheus statics are exported by default whenever you run veloren-server-cli Open your web browser http://localhost:14005/metrics to see the raw values.

You can import this data into Prometheus via this tutorial: Add localhost:14005/metrics to your /etc/prometheus/prometheus.yml. Connect to http://localhost:9090 and enter tick_time, execute and switch over to Graph mode.

You can connect your Prometheus service to a Grafana instance: You'll find example dashboards in the veloren infrastructure repo (not yet available):


Tracy enables you to track the time spent in certain spans based on instrumentation inserted into code. It allows to get a detailed level into certain blocks of code, when they execute and how long they take.

Tracy has an extensive manual available

Enable tracy support with the feature tracy on one of the binary crates:

cargo run --bin veloren-voxygen --no-default-features --features tracy,simd,egui-ui,shaderc-from-source --profile no_overflow"

We have an alias defined for this in .cargo/config, so the following shorthand can be used if you don't need to customize the profile or what features are enabled:

cargo tracy-voxygen

Similarly, we have an alias for running the server with the tracy feature enabled:

cargo tracy-server

Connect to the running process via your Tracy tool:

Note: The version of Tracy required depends on the current version of the tracy_client crate being used by veloren. This can be found in the Cargo.lock file at the repo root and checked against this table

'cargo build -Z timings'

When you want to analyse compile time, you can use cargo's feature -Z timings. It will output a .html file with individual compile times, and dependencies and a total graph showing inactive, active and idling projects.

External tooling

rust: flamegraph

Follow the installation tutorial here: execute it via either cargo flamegraph or simply flamegraph and provide the location to the executable. Once you close veloren a flamegraph.svg file will be created you can open with your browser

Visual Studio 2019 Community Edition (Windows only)

visual studio has a build in profiler, follow this tutorial and attach it to the running veloren program:


you can use valgrind/cachegrind profiler to generate a output file and later analyse it via valgrind. Tutorial:

Artists creative heaven

Introduction into the art of adding artistic content to Veloren.

Saying 'Hello' in one of the art-channels

This is the best way to get in contact with our art-team on Discord. Plus you already get an idea of how we work together as a team and maybe even get to know some of us.

Artists are showing off their creations on those channels to get feedback or an 'OK' from Core-Devs that their model is ready for being animated and placed into the game.

Attribution and Licensing

Assets that are (or are adapted from) licensed copyrighted material often have certain requirements including attribution of the source and making note of the modifications.

For example, the Creative Commons licenses generally require attribution with:

  • Title of the original work
  • Link to the original work
  • Author of the original work
  • The license name with a link to the full license
  • Notes of any modifications to the original work
  • If modifications are enough to be considered a derivative/adaptation, the new title and authors

To keep track of attributions and provide a format that can be displayed in the game we have created assets/common/credits.ron. Merge requests that add works requiring attribution should update this file with new entries. This manifest allows entries with the following fields:

fn main() {
    name: String,
    source_link: String,
    authors: Vec<String>,
    asset_path: String,
    license: String,
    license_link: String,
    modfications: String,
    notes: String,

Attributing work with no modifications or small modifications from the source can be formatted like:

fn main() {
    name: "Original Title",
    source_link: "",
    authors: ["Author One"],
    asset_path: "relative/path/to/fancyfont.ttf",
    license: "CC BY-SA 3.0",
    license_link: "",
    modifications: "Trivial modification",

Derivative work can be formatted in the current scheme like:

fn main() {
    name: "Derivative Title",
    source_link: "",
    authors: ["Author Two (derivative)", "Author One (original)"],
    asset_path: "relative/path/to/fancyfont.ttf",
    license: "CC BY-SA 3.0",
    license_link: "",
    modfications: "Added additional characters to the font.",
    notes: "Derived from Original Title",

There is room for improvement in the format for derivatives works and thoughts on this would be welcome! For instance, in the example above original and derivative authors have to be differentiated using a note in parentheses and the title of the original work is listed in the notes field.

For now, attribution requirements that don't fit the provided fields can utilize the notes field to provide any further information. Additional cases that might need this are:

  • Work derived from multiple original works.
  • Work derived from derived work (indication of previous modifications needs to be retained).

Careful review of the specific license and requests of the original author is advised. For more helpful information on the Creative Commons licenses see:

Contributing Voxel Models

Welcome to the section about getting your voxel models into Veloren!

Software to create Voxel files

Most of our artists use the freely available MagicaVoxel from ephtracy. It's available for Mac, Windows and runs with Wine on Linux.

Of course you are not obliged to use this software but it's highly suggested as some block properties are determined directly with palette parameters shown in MagicaVoxel.

At some point we might create our own voxel editor with built in model rigging and animating.

MagicaVoxel is easy to begin with but hard to master. YouTube is always a great idea to start with.

You should totally have a look at controls in MagicaVoxel as they highly optimise your workflow.

Our GitLab assets repo will give you an idea of how assets are organized and what kind of style we try to achieve with them.

If you want to create armour/weapon models it's suggested taking a look at the reference models For hairstyles you might want to take a look at the hairstyle reference.

For detailed info about how to create and add them to the game have a look at the guides section of the book.

Some basics you should know about

Our world consists of big, "landscape" sized blocks and small scale blocks. Houses, trees and everything directly placed in the procedurally generated world is made from landscape blocks. Objects, figures and sprites (i.e. crops) are made from small scale blocks.

One landscape block is 11x11x11 small scale voxels big.

While creating models you should always keep their scale in mind. A character model is around 22 small scale voxels tall and 10 voxels wide. So that's 1x2 landscape blocks.

Objects/figures made from small scale voxels can be arbitrarily scaled to change their size in relation to the world.

I made a model, it's approved by Core-Devs, what now?

The best way to make your creations available to us is to upload them into our Google Drive model directory.

If you can't find a folder that fits your model you can just create a new one.

Whenever we look for new models and don't have them available in our local asset repositories we will resort to this drive.

How do I get the rank of an artist?

Self motivated model creation, showing general excitement about Veloren and high quality content along with a moderate to high activity on the Discord will earn you the rank of an Artist. Becoming a Contributor is easier and only involves showing any kind of motivation to contribute to Veloren.

What is the art-and-assets working group?

This working group is for the most dedicated and skilled artists having constantly contributed to the project. They are the ones newcomers should listen to and take suggestions from.

Is creating art for a game like playing it and mostly fun?

Yes and no. Creating models will feel like work. Usually following an initial rush of motivation right after discovering Veloren people quickly realize how much there is to do and that they can't invest the required time into this hobby due to their other commitments. We are used to that so please don't feel bad if you have to vanish for some weeks.

Keeping intrinsic motivation and working self organized isn't for everyone.

Seeing people actually playing with your models and ideas feels like a massive achievement though. This is why most of us chose to become artists on this project:

To create a beautiful world for everyone to enjoy.

If you feel like you want to join us on this great journey: We are looking forward to welcome you to our team and seeing your creations!

Contributing Audio

The best way to contribute audio is to first visit the Discord, ask for a contributor role in the #new-contributors channel, and start a conversation in the #audio channel.

All sound files should be in Vorbis format (with the .ogg file extension) and exported at Variable Bit Rate level 5. The quick and easy way to do this is to export as a .wav, open it in Audacity, and export it again as an Ogg Vorbis file at compression level "5".

Sound Effects

Most sound effects go in an appropriate folder in assets\voxygen\audio\sfx\.

Sound effects that emit from an source in 3D space, like footsteps, hitsounds, and utterances, should be exported as mono.

There are two main ways of triggering a sound effect in-game: SFX events and outcomes.

SFX events retrieve SFX from the sfx.ron file. They are mostly triggered by any of the various's in voxygen\src\audio\sfx\.

Outcome SFX are retrieved from sfx.ron and handled in voxygen\src\audio\sfx\ Outcomes are emitted from whichever code is related to it, be it combat, server event, etc. The outcome must also be added to common\src\

UI SFX usually stereo sounds that play directly to the player (i.e. not from a place in the world).

There are is also ambience, used for things like wind and rain. These sounds are always stereo. The code for it is in voxygen\src\audio\, the files are in assets\voxygen\audio\ambient, and its manifest is assets\voxygen\audio\ambient.ron.

If possible, have your SFX tested in-game before trying to merge it; ensure it sounds right and plays at the right volume. Be sure to get a second opinion from the Discord channel!


Music files are found in assets\voxygen\audio\soundtrack\. The game retrieves the files via the soundtrack.ron file. Music should be normalized at -1dB after mastering.

It is customary to check in with one of the audio leads on Discord to get your music approved for the game.

Rough loudness guidelines: For people with LUFS analysis software, try to keep the max LUFS-S (after normalization) between -14 and -13 for exploration tracks, and between -13 and -12 for combat tracks. If in doubt, compare directly with existing tracks.


The game plays exploration music as single, standalone tracks in the background. When one track ends, some time passes before another track plays. Which track is played is determined by which site, biome, and time of day the player is in.

The available sites currently are the overworld, dungeons, caves, and towns.

The available biomes currently are Grassland, Forest, Desert, Tundra, Lake, Mountain, Ocean, Jungle, Savannah and Taiga. A Swamp biome is planned, but doesn't exist yet. For an up-to-date list of biomes, see common\src\terrain\

It is worth noting that biomes are descriptive, not prescriptive, when it comes to code. The world doesn't generate based on biomes, and biomes are determined based on existing chunk data.

Certain biomes supersede others - most notably, snow-covered mountains will count as Tundra. If you want to know exactly how biomes are determined, see get_biome() in world\src\sim\

Also note that music may play in more than one biome and time of day, though we generally want to minimize this as more music gets added, to give each biome a more distinct tone.

The times of day are day and night.

The best way to get a feel for the tone of the soundtrack is to simply listen to it.

Exploration music should have soft starts and endings since they come in at essentially random times.


The current implementation of the combat music system is as follows:

"Combat" as a state is when the player comes within a certain distance of enemies with either high health or high quantity. Currently, combat music is reserved for the old, underground dungeons. Upon the player entering combat, a start segment is played. If it ends and combat continues, a loop segment is immediately played, before either fading out or playing an end segment when combat ends.

  • start is a short intro attached to a loop. If the composer is smart, they can shorten this segment by having it somehow transition perfectly into the loop without playing the entire loop itself.

  • loop is the main portion of the combat music. Since the music only comes in when the player is in a fairly dire situation (mobs of enemies, hard enemies, and bosses), the intensity of the music should be fairly high.

  • end is a very short cadence coming off the end of the loop, and is only played if the fadeout can't complete before the loop ends. Should give a sense of finality.

It is important for the transitions and loops to be smooth. This means the loop must be "exported as loop"; the tail (the residual release/reverb at the end) of the loop (and the start) must also bleed into its beginning, as well as into the end.

Translation working group

Introduction on translating content to your language.

Translating the game

Translation status


Veloren uses the Fluent localization system to translate content. Translation files have the .ftl file extension. Fluent files contain a list of messages in key-value format.

Fluent messages may or may not have variables inside via syntax of placeables.

main-servers-other_error = Server general error: { $raw_error }
main-credits = Credits

Fluent messages may have attributes attached to them.

common-abilities-hammer-leap = Smash of Doom
    .desc = An AOE attack with knockback. Leaps to position of cursor.

Fluent also supports plural selectors via Unicode rules:

NOTE: each language has its own plural-set. Don't copy-paste what English does.

hud-trade-buy_price = { $coin_num ->
  [1] Buy Price: one coin
  *[other] Buy Price: { $coin_formatted } coins

Branch marked with * will be used as default.

The plural selectors allow Fluent to select by "group" (distinct for each language). Fluent can also use literals in the selectors for direct comparison. The same example, in Ukrainian may look like this:

hud-trade-buy_price = { $coin_num ->
  [1] Ціна покупки: одна монета
  [one] Ціна покупки: { $coin_formatted } монета
  [few] Ціна покупки: { $coin_formatted } монети
  *[other] Ціна покупки: { $coin_formatted } монет

NOTE: [1] and [one] are different in most languages, despite being the same in English. In Ukrainian, both 1 and 21 would go to [one], but because here we explicitly put [1] at the beginning, it will match sooner, allowing us to special-case single coin.

Don't overdo it, if something is possible, doesn't mean it's required.

Fluent allows us to handle grammatic genders as well. You can translate sentences using the provided gender of actors. Remember to set a default option with the * character for those cases where messages fail to provide the gender.

hud-chat-offline_msg = { $user_gender ->
    [she] [{ $name }] вийшла з серверу
    [he] [{ $name }] вийшов з серверу
    *[any] [{ $name }] оффлайн

NOTE: not all messages provide genders. If in doubt, check comments in the English translation or ask the translation team. If gender information is not available, try to remake the sentence into one where grammar doesn't require you to specify the gender.

You can learn more about Fluent and its syntax here:

Weblate is the most convenient way to translate Veloren to your language.

The game is translated on Weblate with translation suggestions. These suggestions work differently depending on whether or not a language has any dedicated reviewers.

  • The language has one or more dedicated reviewers.
    • You can only add translation suggestions. Reviewers will decide whether to accept or reject the suggestions.
  • The language has no dedicated reviewers.
    • You can both add and vote for translation suggestions. Suggestions that reach a certain number of upvotes get accepted automatically.
  • The language does not exist on Weblate.

Dedicated reviewers are trusted members of the community who are committed to managing translations of their assigned language(s). They decide what translation strings get into the GitLab repository.

If you would like to become a dedicated reviewer for a language, feel free to discuss it with us.

Using programming tools (old way)

Before Weblate was available for contributors, translating the game was harder because translators needed to make use of the Git version control system to submit their translations.

Some translation tools complemented those older workflows. They are still available, but the only supported way to contribute translations to the game is using Weblate.

Previewing your translation

Veloren supports viewing your changes to translation files in real time. The game must have been compiled with a "debug" build to support this feature. You can compile the game yourself in this mode by following the instructions here:

Compiling Veloren

After you have compiled the game and, effectively, can run a "debug" build of Veloren, any changes you do to the Fluent files will be reflected in the game in real time. These are the files contained inside the assets/voxygen/i18n directory.

Getting information about the translation

Veloren includes a localization test tool if you have compiled the game.

This special tool compares the Fluent keys of your selected language with those of the reference language, English. The tool then classifies, counts and prints these comparisons in a neat way for translators to inspect.

It is the same program we run in our automated CI pipelines, but less verbose.

For example, you can run this command to get information about the Ukrainian translation.

cargo run --bin i18n-check --features=bin -- uk

For more information on how to use this tool, run it with the --help argument:

cargo run --bin i18n-check --features=bin --help

Online localization test

We offer a web service to display translations statistics.

Grafana header

We will use the Ukrainian translation as our example.

Grafana for Ukrainian

Here we have detailed information about all language keys used in the Ukrainian translation (uk directory) in comparison with the reference language translation (English - en/ directory).

The status section displayed for each key has the following possible values:

  • Unused: The key exists in the Ukrainian translation but not in the English translation. These are keys that have been used before in the game but have been removed since they weren't needed or have been renamed. These are safe to remove.

  • NotFound: The key exists in the English translation but doesn't exist in the Ukrainian translation. Here we need your translation!

  • Outdated: Currently not available, means that some changes were made to the English translation, but not to the Ukrainian translation.


I cannot make translation suggestions for Veloren on Weblate

No permission to add suggestions on Weblate

If your user account on Codeberg Translate was created before February 2024, your account might not be granted the required permissions to contribute to the Veloren translation.

Please, contact the translation team, either on Discord or through an issue on GitLab. We will review your permissions and help you resolve the issue.

Some of the text characters are missing or displayed incorrectly

Please, raise an issue on GitLab to add the missing characters to the game fonts for your language.

Managing Weblate

Translation workflow

Veloren translation workflow on Weblate

Sometimes, it's needed to make changes to translation files outside of Weblate, in this case, it's important to comply with the following requirements:

  • Changes that only affect the English source files can be merged at any time.
  • Changes that modify translated language files can only be merged in coordination with Weblate:
    • Translations from Weblate are all committed ("Commit pending changes").
    • The translations are pushed and a merge request is opened.
    • The translations are locked in Weblate for modifications.
    • The Weblate MR is merged, Weblate remains locked.
    • After resolving potential merge conflicts itself, the external changes are merged.
    • After all changes are in the master branch, Weblate is updated and unlocked.
  • Updating translated language files must only happen when they are in sync with Weblate, and Weblate is locked to prevent conflicting modifications.

Language types

Languages are classified into two types:

  1. Languages with one or more dedicated reviewers.
    • Contributors can only add translation suggestions.
    • Reviewers are responsible for checking suggestions and deciding whether to accept or reject them.
  2. Languages without any dedicated reviewers.
    • This is the default type.
    • Contributors can both add and vote for translation suggestions.
    • A suggestion becomes the new translation once it reaches a certain number of upvotes.

Language configuration

Set the language type

Our project on Weblate assumes by default no language has any dedicated reviewers. Only languages with one or more reviewers are configured explicitly by administrators.

Let's imagine the following scenario:

  1. The Turkish language does not have any dedicated reviewers on Weblate.
  2. A member of our community, Mary, requests to be a reviewer for the Turkish translation of Veloren.
  3. The Turkish language must change from the default, implicit, behavior to a new, explicit, behavior. A behavior for languages with dedicated reviewers.

As an administrator of our Weblate project, you would need to follow these steps:

  1. Go to the language settings for Turskish on Weblate.
  2. Make sure only these checkboxes are enabled:
    • Customize translation workflow for this language
    • Turn on suggestions
  3. Add Mary's user on Weblate to the Reviewers: Turkish project team.

The difference now, with respect to default behavior, is that Turkish has Suggestion voting disabled. Thus, reviewers, such as Mary, are the only people capable of managing the translation: what strings make it into the GitLab repository.

If you want to get the default behavior back for a language (no reviewers), follow these steps:

  1. Remove every user from the corresponding reviewer team.
  2. Go to the language settings and disable the Customize translation workflow for this language checkbox.

Adding a language to Weblate

We may get requests from time to time to add languages on Weblate for which there are no translations of the game yet. Administrators of our Weblate project are responsible for attending such requests.

A local installation of Git is required to add new languages to Weblate.


If you need to add a language quickly, follow these steps:

  1. Make sure you have a local copy of the Veloren repository on your device.

    git clone
  2. Create a new branch.

    cd veloren
    git checkout -b <yourusername>/add-<language>
  3. Head to the assets/voxygen/i18n directory.

    cd assets/voxygen/i18n
  4. Make a copy of the en/ directory, named after your language. For example, if you want to translate to Turkish, your directory would be named tr/:

    cp en <ietf_bcp_47_code>
  5. Remove the contents of all the Fluent files inside your new directory. All the files with the .ftl file extension. Make sure the files still exist, but empty.

  6. Open the _manifest.ron file and modify the language_name and language_identifier fields as appropriate (see below for more details about this file.)

  7. Commit your changes locally.

    git commit
  8. Push your local branch upstream.

    git push -u origin <yourusername>/add-<language>
  9. Go to your new branch on GitLab:

  10. Create a merge request (MR) targeting the master branch of the main repository.

About the manifest file

The _manifest.ron file has a metadata section. This section has the display name and the language identifier for your translation. Change language_name to a human readable name in your language with this format:

<name_in_original_language> (<name_in_english>)

For example:

metadata: (
    language_name: "Türkçe (Turkish)",
    language_identifier: "tr",

If the language is a variant spoken in a certain region or country, follow this format:

<name_in_original_language> (<name_in_english> - <region>)

Two examples of this case are:

metadata: (
    language_name: "Español de España (Spanish - Spain)",
    language_identifier: "es",


metadata: (
    language_name: "Español de Hispanoamérica (Spanish - Latin America)",
    language_identifier: "es-419",

Remember to set the value of language_identifier to match the parent directory's name.

Tip: You can set convert_utf8_to_ascii option to true to convert everything to ASCII, so that the missing characters can be seen properly.

Translation system explained

You can see the localization files inside the assets/voxygen/i18n directory. Each subdirectory inside represents a language, or a variant of it. The directories are named after IETF BCP 47 (RFC5646) language tags (e.g. en/, de/, pt-BR/, etc). A language tag is comprised of one or more subtags, separated by hyphens ("-").

This is a comprehensive list of available language subtags:

IANA Language Subtag Registry

They must be formatted in UTF-8, without BOM. Each language directory contains a _manifest.ron file with a metadata section, font settings that will be used in the game and a convert_utf8_to_ascii option, which can be used when translating a language which has characters that aren't in the fonts Veloren uses.

The metadata section includes a display name and an identifier for the language. The display name may be freely changed but the identifier should stay the same after the introduction of a new language:

metadata: (
    language_name: "English",
    language_identifier: "en",

Note: The language identifier must match the name of the containing language folder. This requirement implies the identifier must also comply with the IETF BCP 47 naming standard.


I am receiving hundreds or even thousands of emails from Weblate

Once upon a time, while configuring our Weblate project for the first time, there was an incident where administrators back then received a considerable amount of notifications via email from Weblate. Seemingly, it was caused either by a software bug or by bad configuration.

If you are an administrator of our project on Weblate and want to get notified via email, just in case, we suggest you set up custom Inbox rules to move messages from the following sender to an email folder of your choice:

For Game Designers

Section under construction. Be careful out there.

Writing a Proposal by @Silentium

The first thing to remember when writing a design proposal is that any idea might not make it into the game due to the consensus of the design team. Unfortunately, we can't include all ideas, but with some compromising and some creative thinking, we can usually extract important aspects of the idea. Even ideas that don't get used in their full state can still provide some very important insight into other aspects of the game's design, so do not think that an unused idea is invalid. Every idea is useful, just maybe not necessarily in the way it was intended. The more the better.

The second thing to understand is that the proposal needs to keep from being too detailed. The goal is to do the least amount of work possible to effectively communicate the fundamental principles and reasoning of an idea. This is because if the idea isn't well-received, or if it needs some reworking or changes, they can be done without subverting a large portion of the work done to write the proposal. No idea proposed to the game design team is used verbatim.

The third thing is to be open to changing ideas. As previously stated, no idea is used without some changes being made first. As long as the proposer keeps an open mind about what can be changed, their idea will be very useful to the design of the game. This also helps uphold healthy conversation grounds.

Fourth is to read all preceding documentation. Almost everything we are currently doing is built off previous work. We have a very specific order in which we are designing gameplay elements and systems, and some of them need to be addressed before others. Make sure not to presume we haven't designed an element of play, and make sure not to read too deeply into the potential implications of a system we have designed. The proposals are written to be specific, including only that which has been explicitly been decided on. Items out of its scope may still be up in the air.

The last thing is that everything is changeable, even the stuff we have already written in our official documentation. By this, I do not mean we are open to redesigning the whole thing again. We are very proud of the work we have done and would rather not scrap it. That being said, if anyone thinks there is a problem with a system we have designed or a fundamental fatal design choice we have made, we are open to hearing about the criticism. Not only that, but we fully expect some systems to not prove viable when we start playtesting. As a result of this, we will likely have to rework some of our systems and come up with more iterations.

Each time we begin a new topic of design, I will make a post to let the team members put their ideas into one document. We all collaborate on this to get the final proposal finished so keep an eye out for those in #game-design!

As long as someone can keep these principles in mind while they write their proposal, they will be very effective in contributing their ideas to the game design team. Please let me know if you have any questions about any of this, or if you need clarification. I love when people take an interest in our work, so please don't hesitate to message me!

Cheers ✨👍✨ @Silentium

Writers vocabulary hub

An art style worth a look.

Contribute to this book

You can find the source for this book at our GitLab, feel free to make changes, correct errors and add more content.

Common elements

Consistency is key. Therefore here are common elements used in the book and how they should be styled:


Note: Highlight important notice which the reader should keep in mind.

Short description for experienced people

More detailed description for beginners and newcomers.

Use <br/> for linebreaks.

Rust syntax highlighting works good for .ron files. (Use rust,ignore to avoid making them runnable)

Brown: (
    vox_spec: ("armor.chest.grayscale", (-7.0, -3.5, 2.0)),
    color: Some((90, 49, 43))

Tip: notice which can help reduce time and effort.

DevOps automated introduction

Section under construction. Be careful out there.

Provide a CI runner

We need to host our own CI runners, if you have a spare pc or server and have some spare compute time for Veloren, it would help us a lot.

What is CI?

Continuous Integration (CI) is a set of automated tests and tasks that run on the GitLab repo every time code is added. This means that Merge Requests have a lower chance of breaking the codebase, and we can automatically get builds of the contributed code, among other benefits.

We need your computer to help us with the testing. It's not free to run CI, so we use our own computers to do it.


We use GitLab runners in combination with Docker.


  • = 2 CPU cores. we don't cause constant 100% load, but when a compilation even comes it, more cores help to quickly process them.

  • 50 GiB of free HDD space. The Docker image contains a cache and is about 20 GiB additional caches can take up some more space.
  • = 1 Mbit/s internet. you don't need fast internet, but the runner will connect to the internet from time to time. a flat rate is ideal.

Install a runner

First, you will need to contact a maintainer to get a GitLab runner token. For this, either message @xMAC94x, or @AngelOnFira. We will probably make sure you've been with the project for a bit, as we don't want to give the token to just anyone.

You will need to have Docker installed, as all of the builds use it. You can follow instructions here,

Clone our Veloren CI repo and start the helper script from the runner directory

git clone
cd veloren-docker-ci/runner
# provide the token from above
# provide a name in the style: `<discord-username>-<descriptor>`. So for example, @angelonfira's might be `angelonfira-server-1`.

The script will take about 10 minutes and when it's done a Docker container is started in the background. It will only take processing power when there are Pipelines to be done.

Currently, the script is Linux only, if you run Windows your best bet is to create a Linux VM (e.g. using VirtualBox and Ubuntu Server 20.04)

Update a runner

In order to use caches effectively, we need at least gitlab-runner v13.8.0. If your runner is older, please recreate the runner, you can use the script. Note, it is interactive and requires your input

# 1. update repo veloren-docker-ci repo
git pull
# 2. go in runner folder
cd runner
# 3. execute update script
# provide if you want to prune old images, choose yes except if you have certain images you want to keep or run other Docker containers
# provide the CONTAINER ID that reflects the old image
# see the Install section above for re-setting up the runner

Releasing rock stable software

Introduction release steps per software.

Release cycle

This page aims to document the release process of Veloren. It first describes an overview and has more detailed chapters for single steps.


2 months before release

On the Sunday meeting:

  1. Estimate a release date and communicate it to internal parties. The date is subject to change until it becomes official later on.
  2. Settle the following points:
    1. The theme of the release party.
    2. The features to implement with the release and those which would be nice-to-have.
    3. The people assigned to the party map.
      • The design of the party map.
    4. The people assigned to the release trailer.
      • The contents of the trailer.
    5. The people assigned to writing a blog post about the release.
    6. The people assigned to managing the feature freeze period.
    7. The people assigned to creating and publishing the release binaries.
    8. The people assigned to announcing the release on our social media accounts.
    9. The schedule for the release party:
      • The activities for the party.
      • The duration of each activity.
      • The people responsible for (each of) the activities.
  3. Create a milestone on GitLab to track progress of the release.

1 month before release

On the Sunday meeting:

  1. Choose an official release date when the core developers and the corresponding assignees are available.
  2. Gather feedback about the activities and the trailer.
  3. Discuss with the people responsible for the map:
    • What is the current state of the map?
    • What are their plans for the map?
    • Can they make the schedule?
People in chargeTask
Feature freeze assignee(s)Post the feature freeze schedule
Blog post assignee(s)Write the blog post
Social media assignee(s)Write the social media posts
Social media assignee(s)Create an event on our Open Collective profile for the release party

3 weeks before release

People in chargeTask
Map assignee(s)Prepare the map for the trailer
Activities assignee(s).Prepare the activities for the trailer
Core developersReview the map and the activities
Feature freeze assignee(s)Gather feedback on what features are necessary, who will review them and when merge will be done

2 weeks before release

People in chargeTask
Trailer assignee(s)Prepare the trailer for review
Core developersReview the trailer

1 week before release

People in chargeTask
Feature freeze assignee(s)Apply and watch the schedule over the next week
Map and activities assignee(s)Wait until all tasks are completed
Trailer assignee(s)Publish the trailer
Blog post assignee(s)Publish the blog post

8 hours before release

People in chargeTask
Social media assignee(s)Post the release announcement
Map and activities assignee(s)Upload map and activities to the server
Release binaries assignee(s)Merge the release commit and publish the release binaries

Sunday after release

On Sunday meeting:

  • Discuss how the release party went.
    • What was done well?
    • What could have been done better?

Plan for releasing the binaries

The sample commands in this section would be run for version 0.12.0 of the game. Remember to adjust these commands to your applicable version.

  1. Copy over
  2. Create a release branch from master:
    git checkout -b "r0.12"
  3. Create a release tag:
    git tag -a "v0.12.0" -m "Version 0.12.0"
  4. Push the release tag.
    git push --tag "v0.12.0"
  5. Verify the release tag pipeline executed successfully.
  6. Trigger a scheduled pipeline.
  7. Verify the release container is built.
  8. Add a link on the website to the release.
  9. Create a release on GitLab.
  10. Verify the release binaries have been copied to Wasabi.

Social media cheat sheet

T-1 weekDiscordPing the @NewsPingSquad and @MediaPingSquad roles.
T-30 minsDiscordPing the @everyone role.
T-8 hoursRedditThe subreddit is r/veloren.
T-8 hoursMastodon


GitLab milestone

# v0.xx Release

## People responsible
Blog post:
Feature freeze:
Release binaries:
Social media:

## Overview
Theme is: ``
Rough release day is: ``
Included features are:
Excluded features are:
Party schedule is:
- 18:00 UTC+00 start of party

## Checklist

Sunday meeting:
- [ ] Fixed release day is: `` *(T-1 month)*
- [ ] Map is approved by the core developers
- [ ] Activities are approved by core developers
- [ ] Trailer is approved by core developers

- [ ] Release blog is prepared *(T-1 month)*
- [ ] Release blog is uploaded *(T-1 week)*

- [ ] Trailer is ready for review *(T-2 weeks)*
- [ ] Trailer is uploaded *(T-1 week)*

- [ ] Map is ready for review *(T-3 weeks)*
- [ ] Map is uploaded *(T-8 hours)*

Feature freeze:
- [ ] Freeze period is announced to public in #town-hall *(T-1 month)*
- [ ] Feature freeze is enforced *(T-1 week)*

Release binaries:
- [ ] Release binaries are produced, uploaded and verified *(T-8 hours)*

Social media:
- [ ] Posts are prepared *(T-1 month)*
- [ ] Posts are uploaded *(T-8 hours)*

Feature freeze announcement

Hey @Contributor @DevPingSquad ,

**0.13 release is on Saturday, 2022-07-23 18:00 GMT**

As usual, there will be a **feature freeze** starting from 2022-07-16 18:00 GMT. We recommend submitting critical and large MRs for review now, before the feature freeze.

This release will also have a **stress test event** between the feature freeze and the release. We will be sharing further details of this later.

__Getting your large MR merged before feature freeze__
Please mention @xmac94x in the <#992383235332001942> thread with a short summary with the following details:

* What is complete.
* What needs to be done.
* Can your feature be partially introduced to master in its current state (as multiple MRs)?
* Do you foresee any issues with your MR and if so, which ones?
* Why should this feature be in 0.13?

This is required to align our testing and review strategies to ensure a smooth release.

2022-07-16 18:00:00 GMT Feature freeze — No new feature MRs will be merged.
2022-07-18 18:00:00 GMT Stress test event.
2022-07-22 10:00:00 GMT Total freeze — no new merges will be introduced unless they're critical.
2022-07-22 16:00:00 GMT Release build will be compiled.
2022-07-23 12:00:00 GMT Main server hardware upgrade.
2022-07-23 18:00:00 GMT Release party!

Release a new Version

  1. Copy over CHANGELOG, update only crates. example MR
  2. Create release branch from master git checkout -b "r0.7"
  3. Create release tag git tag -a "v0.7.0" -m "release 0.7.0"
  4. Push release tag git push --tag "v0.7.0"
  5. Verify a release tag pipeline runs:
  6. Verify release container is build:
  7. Verify github/airshipper actions to build a release binary
  8. Create a release on GitHub
  9. Ping @LunarEclipse#3307 for AUR package update & ping @Frinksy#1694 for Flathub version.

Packaging guidelines

This sections contains information useful when packaging Veloren for new platforms.

Packaging the standalone game

The preferred method for shipping Veloren is now Airshipper, but here is information about packaging the standalone game.

This document is focused mainly on packaging Veloren for Linux, but some information will also be helpful for other platforms.

General information

Please refer to this guide for the general setup and compilation instructions.

As additional reference, see the veloren-git AUR package, more specifically the PKGBUILD file.
It should always have an up-to-date buildtime and runtime dependency list.

Rust version and Rustup

The specific version of Nightly Rust a given version of Veloren is intended to be compiled with is specified in the rust-toolchain file. If you use rustup, it will install and use the right version automatically. Otherwise you need to make sure you use the correct one yourself. Veloren will fail to compile on Stable Rust, and we do not support compiling it with Rust versions other than the one specified in the rust-toolchain file.

Compile-time options

  • It is recommended that you use the --release flag so that the resulting binaries are fully optimized.
  • In order for the game to use standard (XDG-compliant) directories to save user data instead of trying to save it next to the executable, you need to set the VELOREN_USERDATA_STRATEGY environment variable to system.
  • To compile specific binaries, you need to pass --bin <NAME> arguments.

The resulting command to compile the game server and client using the above settings would be:
VELOREN_USERDATA_STRATEGY='system' cargo build --release --bin veloren-voxygen --bin veloren-server-cli
In this case the resulting binaries will be target/release/veloren-voxygen and target/release/veloren-server-cli.

Other files

  • You need to include the assets for the game to run. The expected location for them is /usr/share/veloren/assets.

  • In the assets folder, we provide a .desktop[spec] file, an icon and a .metainfo.xml[spec] file. You should place them as follows:

  • assets/voxygen/net.veloren.veloren.png -> /usr/share/pixmaps/net.veloren.veloren.png

  • assets/voxygen/net.veloren.veloren.desktop -> /usr/share/applications/net.veloren.veloren.desktop

  • assets/voxygen/net.veloren.veloren.metainfo.xml -> /usr/share/metainfo/net.veloren.veloren.metainfo.xml


This section of the book will provide guides for common modifications to Veloren like adding new Armor.

Guide: Adding armour to Veloren

\_ made by @Pfau

\_ updated by @BottledByte


What you need

An IDE of your choice (A programme that lets you view and edit code)

Examples: VSCode, Atom, Notepad++

A Voxel Editor (To create the armour model)

Example: Magicavoxel

The character template. (Can be opened with any voxel-editor that supports layers; i.e. Magicavoxel.)

This is also included in the Veloren client’s assets.

Getting Started

Before creating your armour in a voxel editor there are a few things you should know:


In order to place “skin” (parts that are not covered by armour) to your work you have to use whatever colour is stored in the 1st (light tone) and 5th (dark tone) slot/index of your palette.

Note: The important thing is not the colour but the position on the palette to get the right result.


Armour can be coloured in the code, too.

To do that just use grayscale colours in your model. (Later you will learn how to apply the colours with code.)

Another thing you might notice is the neck added to the chest armour. This is needed to not make the head appear disconnected from the body when it’s turned.

Importing the model and adding it as an item to the game

To make the game actually load your creation there are several steps you have to follow.

They can be done in any order.

Copying the .vox into the asset folder

Make sure to export your model(s) as .vox and NOT just copy a saved .vox file from magicavoxel. Just copying will result in a ~10x bigger file size.


The file path inside the assets folder is something like

assets/voxygen/voxel/armor/<Armor Type>/<Model Name>

So for a chest armour called “leather_vest-0.vox” it is:


Naming scheme for .vox files

Single words are parted with an underscore (“_”)

Counting starts at zero.

Numbers are added with a single dash(“-”) in front of them.

Your item name should always end with a number, unless you are absolutely positive there isn't going to be an alternative version/design of the item

Load the file and store it inside the code

Those are the file paths you will need after opening the root folder of Veloren in your IDE:

assets/voxygen/voxel/humanoid_armor_<armour type>_manifest.ron

ONLY needed for armour with .vox files

(sets the filepath and offsets of the .vox)

assets/common/items/armor/<armour type>

(create a new .ron in here to create an in-game item)


(create a new entry in here to add an item image to the item)


Note: ONLY needed for armour with .vox files

(list your new armour style in here)

Veloren has 12 types of armour

Types in bold need a 3D .vox file

  • Head
  • Neck (Necklaces)
  • Tabard
  • Shoulder
  • Chest
  • Hand
  • Lantern
  • Belt
  • Ring
  • Back (Capes, Backpacks...)
  • Legs
  • Feet

Armour types that need a 3D .vox file need to be listed in every file above.

Example for adding a new cape

1. New entry in assets\voxygen\voxel\humanoid_armor_back_manifest.ron


The offset will be determined at a later point! Just keeping the numbers from the example you copied should be good for now.


Copy this part (make sure to include the brackets and comma!) and paste it:


Fill in the name of the item style (kind). This is the name you’ll use to later to match up assets.

Note: color: None indicates that grey parts won’t be recoloured.

To colour those parts put in “color: Some((<R>, <G>, <B>))” here.

Example of recoloured armour
"Brown": (
    vox_spec: ("armor.chest.grayscale", (-7.0, -3.5, 2.0)),
    color: Some((90, 49, 43))

2. New entry in assets/common/items/armor/<armour type>


Copy and paste one of the existing .ron files (Note: Use numbers here too).

    name: "New Cape",
    description: "Example Item",
    kind: Armor(
        kind: Back("NewCape"),
        stats: (20),

Edit the file to have the right kind. (The same kind you put in before.)


description field in Item creates a tooltip text similar to this.

3. Add a new item image in assets\voxygen\item_image_manifest.ron

You can either use a .png or .vox file as an item image.

Example for a .png:

// Lanterns
Lantern("Black0"): Png(

Example for a .vox:

Armor(Back("Short0")): VoxTrans(
    (0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.0,

In order to find the right posing numbers for the .vox it’s often a good idea to look for a similar item.

Armor(Back("NewCape")): VoxTrans(
    (0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.0,

You can use the same .vox as the actual 3D asset shown equipped on the character later.


4. Finding the right offset for your item

In order to test your item in-game you need to compile your game now.

Your new item will only be available locally, so make sure to connect to a local server or choose “Singleplayer”.

To drop the item into your inventory use the chat command /give_item:

/give_item common.items.armor.back.new_cape


When equipping your new item you might be presented with this sight.

To set the right offset you need to revisit ssets/voxygen/voxel/humanoid/<armour type>_manifest.ron

The values in there can be hot-reloaded. That means just saving them will immediately take effect in-game.

"Admin": (
    vox_spec: ("armor.back.admin", (-5.0, -1.0, -0.0)),
    color: None

They represent the coordinates:

(X, Y, Z)

X = Left (lower the number) and Right (increase the number)
Y = Back (lower the number) and Forth (increase the number)
Z = Up (increase the number) and Down (lower the number)

Change the numbers until you get the desired offset.


Done. You added a new armour style and item to Veloren. :)

But just in case something went wrong, a little troubleshooting advice

It may happen that your armor displays as a big pink box with a question mark (in the world or in the inventory).

If this happens, some entry is invalid, probably due to a typo in your style (kind; like "NewCape") or one of the asset paths. See the log for details to pin-point the source.

If the game panics when loading your armor, it mostly means that the syntax of one or more entries in .ron files got garbled (like a missing parenthesis or a quote mark).

Guide: Using multiple Models in one VOX File

\_ made by @Christof



This chapter assumes that you have read the chapter on adding armor and guides you how to keep all pieces of one armor set inside a single VOX file. Using this, it is more easy to see and edit related models in one MagicaVoxel instance.

Combining models from multiple files

The branch symbol in the outline panel opens the menu to work on multiple models. The plus symbol creates new ones, a double click selects a different one. A right click enables editing the name. Only the active model printed in yellow will be edited, pasted into, etc.


To create a single file from a set of armor files, you can copy models from one file and then paste it into another one. One at a time. Remember to first create a new model entry in the list view and select it before pasting the voxels into it.

The up/down arrow top right in the main editor (light blue here) switches between world and voxel editing. To move models relative to another switch to world mode and pull at the arrows of the current selection.


To cut down the size of the generated files we sadly can't use export with multiple models, but we can turn off the optional parts and save then:


Specifying the model index in the manifests

Again like in adding armor, you add an entry to assets/voxygen/voxel/humanoid_armor_<armour type>_manifest.ron for each of the armor parts:

fn main() {
    vox_spec: ("armor.mail.orichalcum", (-4.0, -3.5, 1.0), 2),
    color: None

The last (integral) number in the second line is the model index, if the number is absent, the first model in the file is used. Note that the first model in the file has the number zero.

And in assets\voxygen\item_image_manifest.ron:

fn main() {
Simple("common.items.armor.mail.orichalcum.belt"): VoxTrans(
    (0.0, 0.0, 0.0), (-120.0, 210.0,15.0), 0.9, 2,

Again, the last (optional) number is the model index, starting from zero.

Guide: Adding sprites to Veloren

\_ made by @Pfau


What you need

  • An IDE of your choice (A programme that lets you view and edit code)

    Examples: VSC, Atom, Notepad++

  • A Voxel Editor (To create the sprite model)

    Example: Magicavoxel

  • A guide on how to compile and run Veloren on your OS.

  • A locally cloned branch of Veloren's nightly version.

Getting Started

Before creating your sprites there are a few things you should know:

  • Sprites act like landscape sized blocks that get replaced with small scale models.
    They can either be set to behave like air (no collision at all) or as solid objects.

  • Things like grass should have no collision. While scarecrows and windows should.

  • As of now they will always act like a single row of up to three landscape blocks (33 small scale voxels) above each others. That means you can control the collision height of your sprite but not the width.
    Every part of a sprite that exceeds the x and y-axis bounds of a single block will not clip with figures and objects.

  • Sprites act as immovable objects like blocks. They can't be moved around like figures or objects.

  • Sprites can be set to give players a certain item when picked up.

  • Sprites can have certain spawning and orientation rules.

Naming scheme for .vox files

  • Single words are parted with an underscore (_)
  • Counting starts at zero.
  • Numbers are added with a single dash(-) in front of them.
  • Your model name should always end with a number, unless you are absolutely positive there isn't going to be an alternative version/design of the item

Import the model and add it to the codebase


Here you define how many variations your sprite can have, how much it sways in the wind and which model(s) to load from the asset folders.


Here you define the sprites' properties like collision, orientation, the height of their "collision frame" or if they can be collected.

Step by Step: Addition of an example sprite

  1. Adding a voxel model

    In assets/voxygen/voxel/sprite_manifest.ron copy and paste one of the code blocks, eg:

      Window1: Some((
        variations: [
                model: "voxygen.voxel.sprite.window.window-0",
                offset: (-5.5, -5.5, 0.0),
                lod_axes: (1.0, 1.0, 1.0),
        wind_sway: 0.0,

    ... and put it behind the last entry in the file, making sure to leave the last ) at the very end of the file. Replace the name of the object (eg, Window1), with the name you'd like to call your sprite object (no spaces in the name).

    Next add your .vox model to assets/voxygen/voxel/sprite/, either in the appropriate subfolder or create a new folder if it doesn't fit anywhere else. For example, if your sprite is a piece of furniture, add it to the furniture subfolder. Follow the naming scheme for .vox files mentioned earlier on this page.

    In the new codeblock you pasted, edit the model section to point to your .vox file; making sure to keep the double-quotes and the comma at the end. In the example above, the file window-0.vox was added to the window subfolder and the model was defined as "voxygen.voxel.sprite.window.window-0",

    Next, the center-point of the model needs to be defined in the offset section. In your voxel editor, set the workspace to fit your model. If you're using MagicaVoxel, press the button labeled 'Fit Model Size' to do this. The workspace will shrink to fit your model. The center point is half the number of blocks in the x and y axes. For example, in the Window1 codeblock above, the model is 11 x 11 blocks. So we've entered -5.5, -5.5 for the x-axis and y-axis respectively. Set the z-axis to 0.0 unless the model is supposed to sink into the ground (eg, ore).

    The lod_axes refers to an object's level of detail the further away it is from the player. Reducing the level of detail when an object is far away helps with game performance. This setting tells the game how to scale the level of detail reduction across all three axes (x, y, z). For now, just use 1.0 for all three axes, like the Window1 example above, or find another object that is similar to yours and copy it's lod_axes values.

    If your sprite is designed to sway in the wind (eg, grass or flowers), modify the wind_sway to a number between 0.0 and 1.0. The higher the number the more it will sway. Take a look at some other objects to get an idea of the what value to use.

  2. Telling the game the sprite exists and making it solid

    In common/src/terrain/

    Near the beginning of the file, look for a long list of objects with a hexadecimals number after each object (eg, 0x0A). The name of the objects in this list matches the name in the previous step. For example, in the previous step we were looking at Window1. In the list of objects here, we will find Window1 = 0x28,.

    To add your object to this list, scroll down to the bottom of this list (it's pretty long). At the END of the list add your object name and give it a value of the next hexadecimal number in the sequence.

    Tip: hexadecimal numbers range from 0 to 15, but numbers with two digits are represented by a letter: 0 1 2 3 4 5 6 7 8 9 A B C D E F. Notice how 10 is actually A, 11 is B, and so on. So if the last object in the list had a value of 0xB9, the next object would need to be 0xBA. (0xB9 + 1 = 0xBA). If you need help, you can type 0xB9 + 1 into Google and it will tell you the answer.

    Next, if your sprite is solid, and players should collide with it, you need to add it to a function called pub fn solid_height. Search for this function in the file. This function tells the game how tall the collision box for the object should be. You can skip this if your sprite isn't meant to be collided with and players should move right through it (for example, grass and flowers).

    Within the function you will see a long list of objects that looks like this: SpriteKind::Tomato => 1.65,. Scroll to the bottom of this list and add your sprite at the end. You'll need to calculate what number value to assign your sprite though. This number is simply the height of your sprite in voxels divided by 11. For example, if your voxel model is 18 voxels tall, the calculation is 18/11 = 1.64. You can find the height of your model by going to your voxel editor and counting the number of blocks.

    Note: 3.0 is the maximum value that can go in this list. If you have defined multiple variations of a sprite in the previous step, they will all share the same height.

    Finally, in the pub fn has_ori function, add your sprite to the end of the list. Follow the examples already there and don't forget the | at the start (eg, | SpriteKind::Window1). Adding your sprite to this function will allow it to be rotated (oriented) by code when it's spawned in the world.

  3. Other properties for the sprite

    Other than being solid, sprites can also be collectible or minable.

    A collectible sprite can be picked up from the world by the player (eg, stones). Or can be opened by the player with an item taken from it (eg, a chest).

    A minable sprite requires a mining tool before it can be collected (eg, an ore).

    The steps required to make sprites collectible or minable are too involved for this page and need be addressed in a separate guide.

    However, for those who wish to dive into the code and figure it out for themselves, here are some pointers to get you started.

    • Add sprite to pub fn collectible_id in common/src/terrain/
    • If the sprite requires mining, add it to pub fn mine_tool in common/src/terrain/
    • If your sprite is meant to be opened, and will give the player an item, follow the examples for crates and chests in common/src/terrain/ This will involve creating a .ron file in assets/common/loot_tables.
    • If your sprite is to be collected, and goes into the player's inventory:
      • Create a .ron file for your collectible sprite in subfolder of assets/common/items and use an example that most closely matches what your sprite does (eg, food).
      • Add your item to assets/voxygen/item_image_manifest.ron. You'll also need to add a copy of your voxel model file to another folder, which is defined in this manifest. Find an item which most closely resembles yours and use it as an example.
      • Add your item assets/voxygen/voxel/item_drop_manifest.ron in the appropriate section with similar items.
      • Add your item to common/src/states/ in the section fn from(sprite_kind: SpriteKind) -> Self.

Making sprites spawn in the world

Sprites are spawned into the world through code, rather than being placed manually. This means in order to make your new sprite spawn where you intend (eg, in a house, field, dungeon, etc), you'll need to be able to modify code.

But... if you're looking for a quick way to see what your sprite looks like in the game, without coding, there is an easier way to marvel at your handiwork. This is useful to check if your sprite is the right size, for example.

  • You'll need to compile the code you've written so far in the steps above. There are other parts of the guide that explain how to do this, but in essence you type: cargo run
    • Tip: Don't be surprised if your compile fails with an error, it's usually just a typo. Take a look at the code you wrote, see if there are any obvious mistakes, and repeat the steps above if necessary.
  • Find and remember the name of the sprite you created in step 1 above. We've been using Window1 as an example.
  • Once your local copy has been compiled, and is running, start a singleplayer game.
  • In the game, type: /make_sprite YourSpriteName replacing the word "YourSpriteName" with the name of your sprite in step 1.
    • Example: /make_sprite Window1
  • Your sprite will be spawned where your character is standing. Huzzah!

If you want to take it to the next level, and see your sprite appearing properly in the world, you'll need to get your hands dirty with Rust coding. This is beyond the scope of this page, but here are a few tips to get you started:

  • world/src/layer/ contains code for items such as flowers, twigs, stones, etc. Anything that is 'scattered' about in the environment randomly.
  • world/src/site2/plot/house.rscontains furniture in houses, such as tables, beds and coat racks.
  • Take a look around world/src/ for other examples.
  • The #new-contributors channel on the Veloren Discord server is a good place to ask questions.

Congratulations on adding a new sprite to Veloren!

Guide: Adding Weapons to Veloren

\_ made by @BOB17368


What you need

  1. An IDE of your choice (A programme that lets you view and edit code)

    Examples: VSC, Atom, Notepad++

  2. A Voxel Editor (To create the weapon model)

    Example: Magicavoxel

  3. A compiled version of veloren(So you can edit the game's files)


  1. A character template. (Can be opened with any voxel-editor that supports layers; i.e. Magicavoxel.)

  2. Access to the veloren google drive model directory.

Some things you might want to know before you start creating your weapon

1. Veloren has 12 types of weapons:

  • Polearms
  • Tools
  • Shields
  • Daggers
  • Sword
  • Axe
  • Longbow/Shortbow
  • Staff

The non-bolded ones are either a work in progress or have not started their development yet.

2. The Veloren google drive files are useful because it allows you to use the existing weapon models as format

3. You need to have your model(s) approved by the core-devs if you want your model to make it into the actual game

4. The handelbar for the weapon has to be at the most, three voxels long and three voxels wide

Importing the model and adding it as an weapon to the game

To make the game actually load your creation there are several steps you have to follow.

They can be done in any order.

Step 1: Export and copy the .vox file into the asset folder

Before you export you models please double check that you have...

  1. Exported your model(s) as .vox and NOT just copied a saved .vox file from magicavoxel. Just copying will result in a ~10x bigger file size.

  2. Made sure that there is No extra space can be shaved of without sacrificing voxels.

Go to the file path below and paste your .vox file and rename it according to the naming scheme below.

assets/voxygen/voxel/weapons/<Weapon Type>/<Model Name>

The file path should look something like this by the time you finish


Naming scheme for .vox files

  • Single words are parted with an underscore (“_”)
  • Counting starts at zero.
  • Numbers are added with a single dash(“-”) in front of them.
  • Your weapon name should always end with a number, unless you are absolutely positive there isn't going to be an alternative version/design of the item

Step 2: Create a .ron file

1. Create a New Entry in

assets/common/items/weapons/<weapon type>

Copy and paste one of the existing .ron files of the same type of weapon you aim to create and edit the parts encapsoulated in [ ] to your preference

    name: "[Crude Mallet]",
    description: "[Two-Hand Hammer\n\nPower: 10-12\n\nBreaks bones like sticks and stones.\n\n<Right-Click to use>]",
    kind: Tool(
            kind: Hammer([BasicHammer]),    
            equip_time_millis: 500,
            power: 1.30,

Note: From now on when I refer to the "Weapon Kind" I am talking about the case-sensitive name you put for "BasicHammer"

Step 3: Create a new entry in the weapon manifest file

Go to this file path and open humanoid_main_weapon_manifest in a text editor


Copy and Paste a module of code where the same type of weapons you are adding are grouped (make sure to include the brackets and comma!)

Then adjust WornIronAxe0 with your "Weapon Kind"

Axe(WornIronAxe0): (
        vox_spec: ("weapon.axe.2haxe_worn_iron-0", (-1.5, -3.0, -4.0)),
        color: None

The offset will be explained at a later point!
Just keeping the numbers from the example you copied should be good for now.

Optional: color: None is used for giving a weapon a specific tint. Just specify the rgb values by replacing None with Some((<R>, <G>, <B>))

3. Step 4: Adding the armour style to

Open common/src/comp/inventory/item/ in a text editor

and add your "Weapon Kind" to the respective enum

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ShortbowKind {

Step 5: Add a new item image in image manifest file

Find where the code for your weapon type is located and copypaste it in the same location

You can either use a .png or .vox file as an item image. But it is only practical to use a vox model for weapons.

Example for a .vox:

Tool(Longbow(WoodLongbow1)): VoxTrans(
        (0.0, 0.0, 0.0), (90.0, 90.0, 0.0), 1.0,

In order to find the right positioning values for the weapon, it’s often a good idea to look for a similar item.

Armor(Back(NewCape)): VoxTrans(
    (0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.0,

You can use the same .vox as the actual 3D asset shown equipped on the character later.

Step 6: Finding the right offset for your item

In order to test your weapon in-game you need to compile your game now.

Your new item will only be available locally, so make sure to connect to a local server or choose “Singleplayer”.

Drop the weapon into your inventory by using the following chat command:

Full Command:

/give_item common.items.weapons.<weapon type(ex: staff)>.<Weapon Kind>

Tip: You can type /give_item common.items.weapons. and then press tab to cycle through available weapons

If you don't like how your character holds your weapon you have to mess with the weapons offsets.

To set the right offset you need to revisit assets/voxygen/voxel/humanoid_main_weapon_manifest.ron

And then tweak the offsets marked below until satisfied

Sword(LongFine4): (
    vox_spec: ("weapon.sword.long_2h_fine-4", (<x offset>, <y offset>, <z offset>)),
    color: None

The values in there can be hot-reloaded. That means just saving them will immediately take effect in-game.

They represent the coordinates:

(X, Y, Z)

X = Left (lower the number) and Right (increase the number)
Y = Back (lower the number) and Forth (increase the number)
Z = Up(increase the number) and Down (lower the number)

Change the numbers until you get the desired offset.

Done. You added a new weapon style and item to Veloren.

Guide: Using the const_tweaker crate to modify values at runtime

\_ made by @Pfau

What you can do with it

The const_tweaker crate allows you to modify constants at runtime. This can be used to tweak animations, UI widget positions and much more!

Short guide by example

Add a new const to your file

#[const_tweaker::tweak(min = -100.0, max = 20.0, step = 1.0)]
const EXAMPLE: f64 = 10.0;

Notice the attached attributes above. Every new const needs their own!
This will create an f64 type that can be changed between -100.0 and 20.0 in steps of 1.0.
Adding your changeable value into the code looks like this:

Foo + *EXAMPLE = Sum

Notice how it has to be dereferenced in order to work.

Const_tweaker is feature gated in Veloren/voxygen. So you need to compile with cargo run --features tweak.

Note: go into voxygen folder for this as the compiler won't accept running --features from the root directory.

This will create a local web GUI at where you can play around with the values.


Guide: Adding Weapon Skills to Veloren

\_ written by @Sam with additions from @James

Define your skill

The first thing you need to do is define your skill and figure out what parameters it will need. It is important to do this as sometimes the new skill can be handled by one of the current character states, and if it’s close, then only 1 or 2 additional could be added to a pre-existing character state.

Adding your skill

Weapon attack skills are handled by character states. As of this edit, these are the following character states (though ComboMelee is in the works and TripleStrike is on the way out).

pub enum CharacterAbilityType {

These character states can be (and are) reused for multiple skills. Your new skill may fit easily into one of these states. The state may need to be adjusted slightly to accommodate your skill. The third alternative is the addition of a new character state. All three of these possibilities are covered in the following sections.

If your skill can be handled by an existing character state

Go to common/src/somp/inventory/item/

Once there, add an additional attack to the weapon which you are adding an attack to. Note that a weapon’s abilities are handled by a vector, with the first ability tied to M1, the second to M2, the third to skill bar slot 1, and additional ones to more skill bar slots (only skill bar slot 1 might be implemented right now).

If your skill requires modifying an existing character state

Go to common/src/states/.

Open the corresponding character state file. In the Data struct at the top, add the additional fields you need, you’ll also need to add it to every section in the code that updates the character state data (the compiler will throw errors if you forget). Then proceed through the code and change any logic necessary.

Go to common/src/comp/

Look for where the fields of the character state are defined. They are defined in 3 places. The top one determines what fields are read from, the second one reads from, and the third one constructs the Data struct in the character state file. Sometimes you may only need to add the new field to the 3rd section, though usually you’ll need to add your new field to all 3.

Go to common/src/comp/inventory/item/

Once there add your new attack to the weapon you want. Also, if any weapon already had the attack, update the fields to include the new variable you added.

If your skill requires creating a new character state

Go to common/src/states/.

Create a new file, and give it a name appropriate to the character state you are adding. It can be helpful to start by copying a file from a similar character state. Create the logic for your character state, and determine what fields will need to be passed into the state in the Data struct at the top.

Also, in this section, you will need to determine what kind of attack your character state is. Currently there are systems for melee attacks, projectiles, and explosions. There will soon be support for shockwaves and beams. If you need some other system to handle your attack, ping me (@Sam) for assistance.

Go to common/src/states/

Add your character state to this file, keep it sorted alphabetically

Go to common/src/comp/

In each location every other character state is handled, add your new character state (it can be helpful to search in the file for “leapmelee” or “leap” and just add your character state stuff in each location. The locations to be careful of your logic though are the 3 locations where the fields of your character state are defined (see section for modifying character state for more detail) and where it checks the requirements of entering the character state (though you can almost always just copy what other character states do).

Go to common/src/comp/inventory/item/

Add your new character state as an attack for the weapons you want to add it to. Ensure that the fields in this location match the fields passed into the first section of

Go to common/src/comp/

Add your character state to the CharacterState enum (ideally include a short description too). Look in the implementation of CharacterState, if yours is described by any of the functions, add it there.

Go to common/src/sys/

Search for any character state (e.g. LeapMelee). Add your character state in the 2 locations the other character states are handled with the same logic.

Go to common/src/sys/

Add logic for how your character state affects natural energy regen here. (If it’s an attack or consumes energy it should disable natural energy regen).

Adding an Ability to the skill bar

(When skill trees are implemented this section will be updated)

As every weapon currently implemented already has at least 2 abilities, the chances are high you will need to either add your ability to the skill bar or move a currently existing ability to the skill bar.

In the file, the ordering of abilities in the vector determines what slot they’ll be assigned to. The first slot is M1, the second M2, the third skill bar 1, the fourth skill bar 2, etc. So when adding your ability, ensure that it is in the correct location in the abilities vector.

Go to voxygen/src/hud/

Add the weapon type you are adding the third skill to the logic when determining the value for the bool should be present. It should be as simple as adding:

else if let ToolKind::Hammer(_) = &kind.kind {

Add an icon in assets/voxygen/element/icons. Skill icons should be 20 x 20 pixels with transparent corner pixels. Check the pins in the assets or veloren-art channel on Discord to find the appropriate color pallet. Ping @Pfau on Discord to see if someone will design a better icon or to get yours approved.

Go to voxygen/src/hud/

There is a section around line 140 listing all M1 and M2 icon locations. Add your skill here with the path to its icon. If your skill is going on the skill bar, add your skill/icon pair to the "Icons" section around line 270 instead.

Go to voxygen/src/hud/

If your skill is replacing an M1 or M2 skill, add it to the match around line 620 for M1 and around line 700 for M2.

For M1 and M2, add an arm to the match expression around line 730 to make the skill icon fade when is over the energy drain of your skill. If your skill does not have an energy drain (and should always be available), you do not need to put your skill in this match.

If your skill is going in the hotbar, follow the steps below:

Add a name and description of the skill around line 800 of voxygen/src/hud/ Just look at the logic of the skills currently there. This will add a tooltip and a name for the skill.

Go to voxygen/src/hud/

Around line 90 add your skill to the HotbarImage enum.

Around line 120 make the appropriate weapon match return the proper skill from the HotbarImage enum.

Around line 130 add your skill to the match. Copy the logic of one of the other skills here, but make energy.current() < ENERGY_DRAIN where ENERGY_DRAIN is the energy drain of your skill. This will make the icon fade when the player does not have enough stamina.

In the image_id function around line 165, add the path identifier for your skill (copy the logic of the other skills).


Ping @Slipped on Discord. You can also dig through previous MRs (like this one: if you want to see how to do it yourself (this’ll show where to add stuff, and show you what code for other animations looks like).


Go to Add a line saying you added an attack

Modding the game

You don't always need to know how to code!

Writing a plugin

This guide will show you how to write a simple server-side (and client-side) plugin for Veloren. Please note that both the plugin API and the process for plugin development is under active development and we currently make no stability guarantees about APIs, tooling, etc. If in doubt, please check this page to find the latest information.

It's also important to remember that the plugin API is still very new and not much functionality is supported. We hope that by publishing this tutorial and encouraging people to experiment with the plugin API that we might start to build consensus on a future direction and future features for the API. If you're interested in helping out, reach out to us!

Example code

You can find the code for this example plugin here.


  • Knowledge of basic Rust

  • Ability to use simple Unix-like terminals and commands

  • An up-to-date instance of Veloren (a local repository is preferred for compatibility purposes)

Note: Having problems? Feel free to ask in #learning on the Veloren Discord server.


Plugins for Veloren are written in Web Assembly (herein referred to as 'WASM'), a code format originally designed for high-performance, memory-safe web executables, but also perfectly suited to a variety of other applications. This implies the following things about Veloren plugins:

  • They are sandboxed, and so are safe to run client-side automatically

  • WASM does not yet have a well-defined host ABI, so communication with the game engine is event-driven

  • They are portable and will work on all architectures and platforms

  • (Planned) Plugins are managed by the server and get sent to clients when they connect to a server, so joining a plugin-enabled server is a seamless process.

Setting up

We assume that you're using either a Unix-like system, or some environment with similar properties (like WSL or Cygwin).

Note: from now on, where you see my_plugin, replace this with the name of your plugin.

First, create a new cargo project.

cargo new --lib my_plugin

Plugins have multiple entrypoints (i.e: ways to request things from the plugin) that may be invoked by the game. To ensure we make all of these appropriately accessible to the game, add the following to Cargo.toml:

crate-type = ["cdylib"]

Because Veloren's plugin API is unstable, we're going to depend on Veloren's git repository. In Cargo.toml, add the following to [dependencies]:

veloren-plugin-rt = { git = "" }

The veloren-plugin-rt crate wraps the plugin API, event handler derive macros, and a series of other useful bits and pieces together into what we colloquially call the 'plugin runtime' (rt).

Because we need to compile our plugin to a WASM module, first ensure that the appropriate toolchain is installed (and works) by running the following:

cargo build --target wasm32-wasi

If you get a error[E0463]: can't find crate for 'core', you can install the relevant version of core using the following rustup command:

rustup target add wasm32-wasi

Veloren's codebase currently requires the nightly version of the Rust compiler (we hope for this not to be the case in the future), and so you also need it. If you are not already using nightly, you can set a directory-specific override for this with the following command (ensure you are in the my-plugin directory before running this):

rustup override set nightly

Packaging the plugin

Plugins are packaged in uncompressed (compression may later be supported, but is not currently) tar archives with the extension .plugin.tar. Each archive contains:

  • A file with the name plugin.toml that specifies plugin metadata

  • And any number of WASM modules (conventionally with the extension .wasm)

  |- plugin.toml
  |- foo.wasm
  `- bar.wasm

The format of plugin.toml is TOML. The required fields are quite simple, as the example shown below demonstrates (you can omit the comments):

# The name of the plugin (lowercase, no spaces)
name = "my_plugin"

# A list of paths to WASM modules in the plugin (this can be used to group
# plugins together in a rudimentary way until we implement dependencies).
modules = []

# Plugins required by this plugin (currently unsupported, keep this empty)
dependencies = []

We'll want to start off by creating a single module. Let's give it the same name as our project. Start off by adding it to the modules list like so:

modules = ["my_plugin.wasm"]

To package the plugin, we can copy the compiled WASM module from the previous steps located at target/wasm32-wasi/debug/my_plugin.wasm into a packaging directory of your own making, along with the plugin.toml, and then use the tar command (or your favourite tar-capable archive manager) to package them up. The following command, executed from within the packaging directory, should work fine:

tar -cvf ../my_plugin.plugin.tar *

You might want to automate this process with a script because you'll be doing it often. A simple shell script would likely suffice.

In the future, we'd like to create a cargo subcommand that automates this step, but this hasn't yet been done.

For reference, I just use a simple shell script with the following contents:

cargo build --target wasm32-wasi
cp target/wasm32-wasi/debug/my_plugin.wasm build_dir/.
cd build_dir
tar -cvf ../my_plugin.plugin.tar plugin.toml my_plugin.wasm
cd ..

Running the plugin

To run the plugin, simply copy it into the plugins directory in the asset directory of Veloren. The plugin will be sent over the network to connecting clients, so it's only important that it's accessible to the server (or Voxygen if you wish to run the plugin in singleplayer).

In my case, this just involves copying the final archive to assets/plugins/my_plugin.tar within my local repository and running the game.

When a server starts (or when singleplayer is started) you should see messages similar to the following in the console:

INFO veloren_common_state::plugin: Searching "/home/zesterer/projects/veloren/assets/plugins" for plugins...
INFO veloren_common_state::plugin: Loading plugin at "/home/zesterer/projects/veloren/assets/plugins/my_plugin.plugin.tar"
INFO veloren_common_state::plugin: Loaded plugin 'my_plugin' with 1 module(s)

If you got this far, congratulations: you've officially created a plugin for the game!

Handling events

At this point, it's worth taking a brief look over the documentation for the plugin API, here. Although we are depending on veloren-plugin-rt, the similarly-named veloren-plugin-api crate is exported by it for our convenience. We're now ready to write the first event handler for our plugin.

In, enter the following:

fn main() {
use veloren_plugin_rt::{*, api::{*, event::*}};

pub fn on_load(load: PluginLoadEvent) {
    emit_action(Action::Print(String::from("Hello, Veloren!")));

This is worth taking a little time to explain, especially if you're not so familiar with Rust.

fn main() {
use veloren_plugin_rt::{*, api::{*, event::*}};

Here, we import the necessary macros, types and functions we need to write our plugin.

fn main() {
pub fn on_load(load: PluginLoadEvent) { ... }

Here, we declare a new function that accepts a PluginLoadEvent. We use the event_handler attribute to tell the runtime that we'd like to use this function as an event handler that will be called when the event of the specified type occurs.

In this case, the on_load event simply gets called once when the plugin is first loaded during server startup.

fn main() {
emit_action(Action::Print(String::from("Hello, Veloren!")));

We've already mentioned a way to receive inputs to the plugin, via event handlers. How do we act upon those events? Through Actions! An Action is a thing that you want the server to perform, and you can use the emit_action and emit_actions function to have the server perform them.

If you run the server with the newly compiled plugin, you should now see the following in the server console:

INFO veloren_common_state::plugin::module: Hello, Veloren!

If you're running the game in singleplayer, you'll see this twice: once for the internal server, and once for the internal client (once it's received the plugin from the server).

Chat commands

We're going to expand our plugin such that when we type /ping into the chat, the player gets the response Pong!. Why? No specific reason, but it's a good demonstration of chat functionality.

Add the following to

fn main() {
pub fn on_command_ping(chat_cmd: ChatCommandEvent) -> Result<Vec<String>, String> {

The only thing to explain here is something that might be a little unexpected given the previous example: the return type.

Every implementer of the Event trait (such as PluginLoadEvent, ChatCommandEvent, etc.) also specifies a response that is required of it. In the case of PluginLoadEvent, the response is simply (), which is why we didn't need to explicitly return anything from the on_load event. The return type for ChatCommandEvent is different, however: it expects either a list of message responses to the command, or an error message should the command syntax be invalid.

If you run the game with the newly compiled plugin and then enter the world, you should be able to type /ping into the chat and receive a Pong! as a response.

Global state

There's a final feature of the plugin API to talk about before this tutorial ends: the management of global state.

If you're more than a little familiar with Rust, that might sound like a scary word: but given that event handlers are themselves 'global' (i.e: they're communicating with just a single instance of the game that loaded the plugin they are in), it also makes sense that any data you want to store about the state of the game in your plugin must also be global.

Thankfully, the plugin API has a feature for this!

To define the type of your global state, you can add the global_state attribute above a type like so:

fn main() {
struct State {
    ping_count: u64,

It's also important that it implements the Default trait: this is needed because we do not yet provide a way for the global state to be initialised via the on_load event handler.

To access this global state in an event handler, simply add a second parameter to the event handler like so:

fn main() {
pub fn on_command_ping(chat_cmd: ChatCommandEvent, state: &mut State) -> Result<Vec<String>, String> {
    state.ping_count += 1;
    Ok(vec![format!("Pong! The total number of pings so far is {}", state.ping_count)])

Now any player can use /ping and the server will tell them how many times the command has been used since the server started!

Reducing plugin size

See min-sized-rust for information about reducing the size of Rust binaries.

Future topics

Possible future topics to cover include:

  • More event handlers
  • Modifying entity attributes
  • Persistent plugin state
  • Controlling NPC AI
  • More plugin API features
  • Plugin-specific assets

Adding in-game items from a plugin

To add new armor or weapon types, you don't need to write and compile Rust, this guide will show you the necessary steps.

Plugin metadata

First, start from a new, empty directory. Like described here, we need to create a plugin.toml file:

# The name of the plugin (lowercase, no spaces)
name = "cool-armor"

# A list of paths to WASM modules in the plugin (not needed for items).
modules = []

# Plugins required by this plugin (currently unsupported, keep this empty)
dependencies = []

Please note that all assets are directly stored in this directory, this means that the normal assets/ prefix or directory isn't necessary.

Then follow the guide in armor creation to create a voxel file in voxygen/voxel/armor/<Armor Type>/<Model Name>, see also using multiple models on how you can put all pieces into a single VOX files.

For a weapon please follow this guide instead.

Adding new files like voxygen/voxel/weapon/tool/paddle.vox, common/items/weapons/tool/paddle.ron or common/items/armor/hide/lizard_boots.ron is straightforward and described in the guides above (remember to skip the top level assets/ directory), but voxygen/voxel/biped_weapon_manifest.ron already exists in the game.

Here simply create a new file with the exact same layout as the existing one in assets/:

    Tool("common.items.weapons.tool.paddle"): (
        vox_spec: ("weapon.tool.paddle", (-2.5, -4.0, -4.0)),
        color: None

Veloren will merge the contents of these RON files when it loads the manifest.

voxygen/voxel/humanoid_armor_foot_manifest.ron will also require the default: part, although it won't be used:

    default: (
        vox_spec: ("armor.misc.foot.none", (-2.5, -3.5, -2.0)),
        color: None
    map: {
        "common.items.armor.hide.lizard_boots": (
            vox_spec: ("npc.lizardman.male.foot_r", (-2.5, -3.5, -2.0)),
            color: None

Then, like described here, create a tar file containing all the newly created files and put in inside the assets/plugins/ folder on the server:

tar -cvf ../my_plugin.plugin.tar *

You can find an exemplary plugin on GitHub.

Please keep in mind that for now we don't give any guarantees on plugin compatibility across Veloren versions, although we might write a plugin migration tool in the future, similarly to the database migration tool, once we see the need and resources for it.

For Journalists

If you want to report about us this section will provide some guideline to make your job easier. We prepared a sample press-kit with logos/images to use on the following page.

In case you want to contact us for an interview, our Discord channel is the best way to reach out to us.

Official information is available under Other websites might be 3rd party fan-pages and although containing useful information, e.g. for non-english communities, they shall not be confused for official statements.

Press Kit

The complete press-kit can be downloaded here Alternatively you can download single files from GitLab


We have 1 Full-size logo, as well an icon version of our logo, in 2 sizes.

The Veloren Logo Icon Small

Example Screenshots

Feel free to visit the servers of veloren to do your own screenshots, but you can also always take some of our example screenshots to decorate your text.

Phoenix in the sky Savannah Exploration Caves


| Image source cogs

This section of the book will provide documentation on how inner systems work

Worldgen (WIP)

(this document is constructed from interview with zesterer#3131)

  • Geological stage
  • Filling stage
  • Reshaping stage

Geological stage

  • Using noises "generate" properties like altitude, rock strength, humidity and temperature which are used as inputs.¹
  • Run erosion algorithm basing on inputs generated by noises.²
  • Produced output is an altitude map with a few other simple attributes like humidity (but not much else).³

(It is saved as .bin file in the game's assets)

  1. Noises can be imagined as random texture. You can see an example of translating noise levels straight into heightmap here click here to open an image
  2. You can see a nice simple example of erosion algorithm here (you can skip to 3:52) click here to open YouTube video
  3. You can imagine altitude map as bare map with only "shape" - river valleys, basins, mountain ridges etc.

Filling stage

(Happens when you actually run singleplayer/server)

Using data from Geological stage places lakes and rivers.

Compute tree density, desert dunes...

(e.g. Using "shape" and some metadata it is figuring out if some hole in the ground should be filled with liquid)

The output looks like this:

(at this stage, contains_waypoint, path, cave, sites and place are empty)

Reshaping stage

| local, temporary, natural elements

(Exact quote from zesterer is pretty self-explanatory:)
So these are things like cliffs and caves
We layer these on top of the world using a variety of techniques
Exactly how isn't too important
Caves and paths are actually done using the same system, known as the "way" system
It basically just provides a method of connecting up long elements between chunks


General system overview

Shallow definitions:

  • Circuit component is a backbone of whole system. It stores information about from where and to where data has to be passed.
  • Wire is part of Circuit (one circuit can have many wires) it stores data from what entity and under what field name value has to be passed to what entity and field name.
  • Wiring component is a "worker" it knows what data it has and what has to be performed when executing it.
  • OutputFormula takes inputs (and own config) and produces output.

If something can't be calculated, but given place has to result in some value - it will result in f32 0.

Each wiring component has 3 pieces of information:

  1. Inputs (data injected by Circuit)
  2. Outputs (information of how to compute output)
  3. Actions (information about what should happen if inputs are in given state)

Each wiring tick has 3 stages:

  1. Compute (take each Wiring component, feed inputs into output formulas, produce outputs)
  2. Transport (get outputs of previous step and using Circuit pass them around)
  3. Dispatch (get inputs (note that we are using modified state by transport) and dispatch logic)


  • Take all wiring components and map them
  • Calculate each outputs output formula
  • Construct outputs with type HashMap<E, Hashmap<F, V>> where:
    • E is an specs::Entity that holds certain wiring component.
    • F is a String representing field name.
    • V is a resulting value of OutputFormula. (at the moment, all results are f32)


  • Take circuits and for each circuit take attached wires *
  • Take every wire and for each wire *
  • Get from what entity, from what field, to what entity and to what field from wire.
  • Perform something like to what entity.inputs[to what field] = from what entity[from what field] **

* It is basically "take every wire" in loaded server data

** Keep in mind that we are using product of Compute step as right hand of this simplification.


  • For each action in every wiring component
  • If wiring action formula output* is more or equal to action threshold...
  • Dispatch each effect attached to the wiring action

* Calculated using inputs

Output formulas


Outputs constant value.


Outputs value of input field under given name.


Allows composing output formulas. It takes left and right output formulas which are calculated, and then performs logic on them.

Available logic kinds (I refer to left and right output as side):

  • Min - return value of lower side.
  • Max - return value of higher side.
  • Sub - return value of left - right.
  • Sum - return value of left + right.
  • Mul - return value of left * right.

Sine wave (not implemented)

Takes server time and returns sine of it.


If physics captures collision for attached entity (touching_entities) returns given value.

OnInteract (not implemented)

If something interacts (e.g. player is "pulling" lever) returns given value.


Returns value * count of entities that died in last tick in given radius.


Spawn projectile

Spawns projectile using projectile constructor.

Set block collidability (not implemented)

Modifies properties of block on certain coordinates.

Set light

Changes LightEmitter properties of attached entity.