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.
| Taken by @Piedro0
| Taken by @Pfau
| Taken by @Pfau
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.
| Taken by @Pfau
Veloren is fully open-source, licensed under GPL 3. It uses original graphics, musics 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.
Website
The Veloren website contains weekly blog updates, developer information and download links. You can find it at www.veloren.net
Discord
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 Twitter.
Download
Visit veloren.net 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 day 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
- First thing to do will be to check our gitlab issues if this bug is already known.
- If not create an issue with the
Bug template
and try to describe the bug as good as possible, include screenshots if needed. - 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)
- 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
Airshipper
- Start airshipper with
-vv
argument. - When the game starts it will print to the terminal the location of the log file. Check Airshipper page.
Compiled
- Start voxygen with
TRACE
level in terminal:RUST_LOG="trace" ./target/debug/veloren-voxygen # or RUST_LOG="trace" cargo run
- Copy trace from terminal or the log file mentioned above.
Windows
Airshipper
- Opening a CMD.
On Windows press
Windows key + R
. Then typecmd
and hitenter
. - Type
airshipper run -vv
and hit enter. - Run the game (till you encounter the problem).
- The logs should be located in
%Appdata%/airshipper/profiles/default/userdata/voxygen/logs
Or check Airshipper page.
Compiled
Git Bash
-> See Linux/Compiled above
Cmd
- Open a CMD.
- Go to your veloren folder with the
cd
command, e.g.cd C:\Users\<Your Username>\Desktop\veloren
. - Write
set RUST_LOG=trace&& veloren-voxygen.exe
and hit enter (exactly like here, without whitespace before&&
) - 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
- Create a folder that to hold the trace. (e.g.
wgpu-trace
)mkdir wgpu-trace
- Run the game with the envionment 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
- Reproduce the bug/crash and then exit the game (the trace will be larger if this takes a while).
- Zip up the trace folder for easy sharing.
For more details about wgpu's API tracing see https://github.com/gfx-rs/wgpu/wiki/Debugging-wgpu-Applications#tracing-infrastructure
Dx12/Dx11 debug layer output
First, check that you are using the dx12 or dx11 graphics backend.
Using DebugView++
- Force the debug layer on for Voxygen (Note: if you compiled the game yourself without
--release
then this step can be skipped):- Run
dxcpl
. - Click "edit list".
- Add
veloren-voxygen.exe
and click ok. - Make sure "Force On" is selected in the debug layer section.
- Click "Apply".
Warning: Enabling debug layers adds extra overhead, make sure to follow the last step to disable them again.
- Run
- Setup DebugView++:
- Download the latest
DebugView++.exe
version from this page: https://github.com/CobaltFusion/DebugViewPP/releases. - Download the filter settings here: View.xml
- Run
DebugView++.exe
. - Open filter settings screen with
F5
. - Click "Load" button, select the downloaded filter settings file, click "Open", and then click "Ok" to close the filter settings screen.
- Download the latest
- Start voxygen (with the dx backend has issues) and run until the crash/error occurs.
- In DebugView++, press
Ctrl + S
to save the current view containing all the debug messages from voxygen. - Share the saved file.
- Run
dxcpl
again and remove voxygen from the list.
Using Visual Studio
- Install visual studio https://visualstudio.microsoft.com/downloads/.
- Force the debug layer on for Voxygen (Note: if you compiled the game yourself without
--release
then this step can be skipped):- Open visual studio.
- Go to Debug > Graphics > Directx control panel.
- Click the
Edit List...
button.. - Add
veloren-voxygen.exe
to the list (be sure to remove this when finished). - Change the Debug Layer setting to Force On.
- Click apply and exit the control panel.
- Open the Voxygen executable as a project (original instructions):
- In visual studio: File > Open > Project.
- Navigate to veloren-voxygen.exe, select it, and click open.
- Run the project (green arrow and or option under the Debug menu).
- Reproduce the issue.
- 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).
Changelog
The changelog can be found in the repository, and in the Airshipper launcher.
Roadmap
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!
That said, there are a number of features and objectives we'd like to see implemented before the game leaves 'alpha' status:
Roleplaying and character development
-
More passive skills and abilities (fishing, metallurgy, farming, animal taming, etc.)
-
More horizontal progression, allowing players to specialise in many different ways and build up a character that reflects their preferred style of play
-
A wider variety of weapons, tools, and skills
World and simulation
-
More detailed world simulation: NPC and player factions, rich history generation, diplomacy, simulated economics that respond to player actions, sieges, wars, etc. all simulated in real-time during normal gameplay
-
Improved world generation: a wider variety of geographic features, procedural locations, biomes, and a 'layered' world (many co-existing layers within the same world space such as caves, the overworld, canopy layers, etc.)
-
Detailed world ecology: simulation of animal populations, plant growth, and changing world geography. A Veloren world should evolve with, and in response to, the actions of players
Questing and interaction
-
Better dialogue options with NPCs that feel like they're active participants in the world, not simply props
-
Quests that are procedurally generated in response to the state of the world and that have a meaningful impact on the state of the world: player actions should influence the world
-
Player-created quests, player bounties, etc.
Multiplayer
- Improved efficiency of the game (and in particular, the server) with the long-term goal of hosting 1,000 players on a single server at once
Out of scope (for now)
There are a few features that we're like to see eventually, but that we don't consider to be essential for a beta release.
- Server federations, where servers can opt in to sharing characters and economies in a 'circle of trust', allowing for truly enormous player-driven economies
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
- Is there a death punishment?
- Is there voxel building?
- Is the map infinite?
- Is there fast travel?
- Can we have cosmetic armor above actual armor?
- Will there be flying mounts?
- Is there a roadmap?
- Will the game release on steam?
- Will we have shields?
- How to donate?
- Will we be able to build in the game?
- How do I become a moderator?
- Will Veloren contributors add NFT and crypto to the game?
- Will the game ever have paying content?
- Can I use boats or airships
- Will dungeons change?
- When will the âXâ feature come out?
Technical Issues/Questions
- Airshipper crashes on launch.
- Game crashes on launch.
- Cannot connect to the server.
- Game is lagging.
- What software do you use for models?
- How to download the game on Mac and Linux?
- How to host a server?
- Will there be mods?
- Can I add an email to my account to change my password?
- How frequently is the game updated?
- How to change account password
- Will there be a User Access panel on the website for accounts?
- Can I transfer my character between servers?
- "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.?
Answers
Is there a death punishment?
No, not right now. But there will be in the future, presumably losing durability.
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?
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: https://opencollective.com/veloren. 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
orvulkan
.
- In windows cmd:
set WGPU_BACKEND="vulkan"
- In powershell:
$env:WGPU_BACKEND="vulkan"
- On Mac and Linux:
export WGPU_BACKEND="vulkan"
Then running the game throughairshipper 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: https://ephtracy.github.io/ However, you can also use other softwares if you feel like it (Goxel, etc) but some features we use might not be available.
How to download the game on Mac and Linux?
Mac: Steps to run Airshipper on Mac
- Download airshipper for mac
- Open the zip to get the file
- Open terminal and write chmod +x ~/Downloads/airshipper-macos/airshipper
- Double click the file
- Enable running in system preferences>Security & Privacy>Allow Linux: You can download the Linux Airshipper here: https://veloren.net/download/
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 clientside with the auth domain as a salt using argon2id and then once again serverside with a randomized 256 bit salt. The clientside prehash is to prevent third party auth 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
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.
Download
Visit the download page to download Airshipper.
Files
Airshipper stores its files in the following directories depending on your operating system:
OS | Path |
---|---|
Windows | %appdata%/airshipper |
Linux | ~/.local/share/airshipper |
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.
Troubleshooting
If airshipper does not open or display correctly, you can use the CLI by
-
Opening a terminal
On Windows press
[Windows] + [R]
. Then typecmd
and hitenter
. -
Type
airshipper run
and hit enter -
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.
settings.ron
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.
Commands
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
.
Command | Description | Requires | Arguments |
---|---|---|---|
/adminify | Temporarily gives a player a restricted admin role or removes the current one (if not given) | Admin | <player> [role] |
/airship | Spawns an airship | Admin | [destination_degrees_ccw_of_east] |
/alias | Change your alias | Moderator | <name> |
/buff | Cast a buff on player | Admin | <buff> [strength] [duration] |
/ban | Ban 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] |
/battlemode | Set your battle mode to: * pvp (player vs player) * pve (player vs environment). If called without arguments will show current battle mode. | [battle mode] | |
/battlemode_force | Change your battle mode flag without any checks | Admin | <battle mode> |
/build | Toggles build mode on and off | ||
/build_area_add | Adds a new build area | Admin | <name> <xlo> <xhi> <ylo> <yhi> <zlo> <zhi> |
/build_area_list | List all build areas | Admin | |
/build_area_remove | Removes specified build area | Admin | <name> |
/campfire | Spawns a campfire | Admin | |
/debug_column | Prints some debug information about a column | Moderator | <x> <y> |
/disconnect_all_players | Disconnects all players from the server | Admin | <confirm> |
/dropall | Drops all your items on the ground | Moderator | |
/dummy | Spawns a training dummy | Admin | |
/explosion | Explodes the ground around you | Admin | <radius> |
/faction | Send messages to your faction | [message] | |
/give_item | Give yourself some items. For an example or to auto complete use Tab. | Admin | <item> [num] |
/goto | Teleport to a position | Admin | <x> <y> <z> |
/group | Send messages to your group | [message] | |
/group_invite | Invite a player to join a group | <player> | |
/group_kick | Remove a player from a group | <player> | |
/group_leave | Leave the current group | ||
/group_promote | Promote a player to group leader | <player> | |
/health | Set your current health | Admin | <hp> |
/help | Display information about commands | [[/]command] | |
/home | Return to the home town | Moderator | |
/join_faction | Join/leave the specified faction | [faction] | |
/jump | Offset your current position | Admin | <x> <y> <z> |
/kick | Kick a player with a given username | Moderator | <player> [message] |
/kill | Kill yourself | ||
/kill_npcs | Kill the NPCs | Admin | |
/kit | Place a set of items into your inventory. | Admin | <kit_name> |
/lantern | Change your lantern's strength and color | Admin | <strength> [r] [g] [b] |
/light | Spawn entity with light | Admin | [r] [g] [b] [x] [y] [z] [strength] |
/make_block | Make a block at your location with a color | Admin | <block> [r] [g] [b] |
/make_npc | Spawn entity from config near you. For an example or to auto complete use Tab. | Admin | <entity_config> [num] |
/make_sprite | Make a sprite at your location | Admin | <sprite> |
/motd | View the server description | [message] | |
/object | Spawn an object | Admin | <object> |
/permit_build | Grants player a bounded box they can build in | Admin | <area_name> |
/players | Lists players currently online | ||
/region | Send messages to everyone in your region of the world | [message] | |
/reload_chunks | Reloads all chunks loaded on the server | Admin | |
/remove_lights | Removes all lights spawned by players | Admin | [radius] |
/revoke_build | Revokes build area permission for player | Admin | <area_name> |
/revoke_build_all | Revokes all build area permissions for player | Admin | |
/safezone | Creates a safezone | Moderator | [range] |
/say | Send messages to everyone within shouting distance | [message] | |
/server_physics | Set/unset server-authoritative physics for an account | Moderator | <player> [enabled] |
/set_motd | Set the server description | Admin | [message] |
/ship | Spawns a ship | Admin | [destination_degrees_ccw_of_east] |
/site | Teleport to a site | Moderator | <site> |
/skill_point | Give yourself skill points for a particular skill tree | Admin | <skill tree> [amount] |
/skill_preset | Gives your character desired skills. | Admin | <preset_name> |
/spawn | Spawn a test entity | Admin | <alignment> <entity> [amount] [ai] |
/sudo | Run command as if you were another player | Moderator | <player> <[/]command> [args...] |
/tell | Send a message to another player | <player> [message] | |
/time | Set the time of day | Admin | [time] |
/tp | Teleport to another player | Moderator | [player] |
/unban | Remove the ban for the given username | Moderator | <player> |
/version | Prints server version | ||
/waypoint | Set your waypoint to your current position | Admin | |
/whitelist | Adds/removes username to whitelist | Moderator | <add/remove> <player> |
/wiring | Create wiring element | Admin | |
/world | Send messages to everyone on the server | [message] | |
/make_volume | Create a volume (experimental) | Admin | |
/location | Teleport to a location | <name> | |
/create_location | Create a location at the current position | Moderator | <name> |
/delete_location | Delete a location | Moderator | <name> |
References
All the parameters that can be used in the commands that can be executed in-game are listed below.
Parameter | Description | Link |
---|---|---|
ai | spawned entity has an agent/ai, true/false | |
alignment | wild , enemy , npc , pet | code reference |
amount | number | |
area_name | name of an area | |
args... | additional parameters, e.g. in /sudo player tell Hello, how are you? args... would be Hello, how are you? | |
ban duration | duration of the ban, e.g. 3d2h30m | |
battle mode | "pvp" (player vs player) or "pve" (player vs environment) | |
block | name of block | blocks |
buff | Name of Buff; be careful, docs use CamelCase and command expects snake_case, e.g. docs: "IncreaseMaxHealth" command: "increase_max_health" | docs reference |
[/]command | e.g. give_item or /give_item | |
confirm | "confirm", to confirm | |
destination_degrees_ccw_of_east | ||
duration | duration in seconds | |
enabled | boolean, true/false | |
entity_config | path to the entity starting from veloren.assets.common.entity with . as seperator of directory names; with the prefix common.entity. ! e.g.: common.entity.dungeon.fallback.boss | folder with the enities |
faction | String of Characters, e.g. "Hello" | |
hp | Health Points as number | |
item | path to the item starting from veloren.assets.common.items with . as seperator of directory names; with the prefix common.items. ! e.g.: common.items.armor.assassin.belt | folder with the items |
kit_name | name of a kit, e.g. debug | definition of the kits |
message | String of Characters, e.g. "Hello" | |
name | String of Characters, e.g. "Hello" | |
num | number | |
object | name of the object | definition of objects |
overwrite | set to true to overwrite previous ban | |
player | Name of Player's Character | |
preset_name | path to the skillset starting from veloren.assets.common.skillset with . as seperator of directory names; with the prefix common.skillset. ! e.g.: common.skillset.preset.max.sceptre | folder with the skillset |
radius | a number to define the radius, has to be higher than 0 and lower than 512 | |
r, g, b | red, green, blue; numbers used to define a color | |
role | "admin" or "moderator" | |
skill tree | name of a skill tree, e.g. general | skill tree names from code |
sprite | name of the sprite | definition of sprites |
strength | number | |
time | options: midnight , night , dawn , morning , day , noon , dusk or %H:%M format e.g. 12:21 | code reference |
username | username of a player | |
xhi | point x on hi | |
xlo | point x on lo | |
x | point x | |
yhi | point y on hi | |
ylo | point y on lo | |
y | point y | |
zhi | point z on hi | |
zlo | point z on lo | |
z | point 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.
- voxygen
- logs
- voxygen.log.<date of log>
- settings.ron
- profile.ron
- logs
- singleplayer
- saves
- db.sqlite
- server_config
- settings.ron (Some entries ignored)
- description.ron
- whitelist.ron (Ignored)
- banlist.ron (Ignored)
- admins.ron (Ignored)
- saves
- server
- saves
- db.sqlite
- server_config
- saves
- server-cli
voxygen/settings.ron
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.
profile.ron
Contains hotbar infomation, per-character and per-server. Should never need to be manually modified.
server/server_config/settings.ron
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.
Setting | Description | Default value |
---|---|---|
gameserver_address | Address 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. | "0.0.0.0:14004" |
metrics_address | Address and port the game server will expose prometheus metrics. | "0.0.0.0:14005" |
auth_server_address | When 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("https://auth.veloren.net") |
max_players | Maximum number of players connected to the game server. | 100 |
world_seed | seed number used to setup the random generation of the world. | 59686 |
server_name | displayed server name | "Veloren Alpha" |
start_time | Server daylight start time in seconds. | 32400 |
map_file | Sets which map to load. See here for allowed values. | None |
max_view_distance | The maximum view distance that clients may request. Useful for low-RAM servers. | Some(30) |
banned_words_files | List of files containing words to be censored. None are distributed by default. | [] (Empty array) |
max_player_group_size | The maximum party size players can have, for purposes of XP sharing and ignoring friendly fire. | 6 |
client_timeout | (secs: 40, nanos: 0,) | |
battle_mode | Can 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) |
server/server_config/description.ron
Contains the introductory chat message clients get when entering the server, as a quoted string. Can be multiple lines.
Example:
"This is the best Veloren server"
server/server_config/whitelist.ron
Contains a list of whitelisted account IDs, and is considered disabled if empty. Heavily recommended to use the /whitelist add/remove
ingame command, rather than manual editing.
Example: Result of using /whitelist add Treeco
and /whitelist add treeco2
.
[
"6f15b915-074f-f78d-df88-34fb33e4e13f",
"3445349e-d03c-64bf-6ecf-a15806275a1f",
]
server/server_config/banlist.ron
Contains a list of banned accounts, and reasons. Heavily recommended to use the /ban
and /unban
ingame 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",
),
}
server/server_config/admins.ron
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
.
[
"ee193d08-8f5a-4862-a279-1a8c4bd357f3",
]
If you have the TUI disabled or are otherwise unable to use it, you can instead use the server CLI to add/remove admins.
Example:
veloren-server-cli admin add Treeco
server-cli/settings.ron
The settings in this file govern the warning period the server gives for automatic shutdowns for updates.
Hosting a Veloren Server
Introduction
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
- Follow one of the Setup Guides:
- Head over to the Configuring The Server page to learn how to set it up according to your needs and preferences.
- (Optional) Generate a custom world.
Available Setup Guides
Choose the instructions for the runtime platform on which you want to run Veloren:
- Running a Server on Your PC
- Running a Server using Docker (For Dedicated Servers)
- Running a Server on a Raspberry Pi
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).
- Start the server
- Find your local IP address and share it with your friends. They will need to enter it in-game to join the server.
- 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.
- Forward port
14004
TCP and UDP on your router. - Start the server
- Find your public IP address and share it with your friends. They will need to enter it in-game to join the server.
- 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.
- Find your game installation folder.
- Go into
profiles/default
. - 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.
- Open the folder with extracted game files.
- Make sure you have the
assets
folder in the same place as the server executable. - Launch
veloren-server-cli[.exe]
.
Finding your local IP address
Tip: Generally local IPv4 addresses have the form of
192.168.xxx.xxx
or, more rarely,10.xxx.xxx.xxx
. For IPv6 addresses, local ones generally start withfe80:
On Linux and MacOS
- Open the Terminal.
- Type
ip addr || ifconfig
and press enter. - You will see all of your computer's IP addresses, grouped by network card/interface.
Interface names starting withe
are generally ethernet while ones starting withw
are generally wireless. Lines starting withinet
andinet6
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 a127.0.0.1
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
- Open CMD (type
cmd.exe
into the start menu and press enter). - Type
ipconfig
and press enter. - You will see all of your computer's IP addresses, grouped by network card/interface.
Lines starting withIPv4 address
orIPv6 address
show the respective address types. Likely, the first address which isn't127.0.0.1
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
anddocker-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.
Setup
Note: The default
docker_compose.yml
will automatically keep the game server updated to the latest nightly release.
- Create a folder for the server data and
cd
into it. - Download the sample
docker-compose.yml
from the repository into the folder.
wget https://gitlab.com/veloren/veloren/-/raw/master/server-cli/docker-compose.yml
- If needed, open port
14004
(14005
for metrics) in your firewall. - To create and start the containers, run
sudo docker-compose up -d
.
If you modify thedocker-compose.yml
file, you'll need to run that command again for it to take effect. - 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 todocker-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:
- Run
docker attach <CONTAINER_ID>
(rundocker ps
to find the ID of the game server container, then if the ID is for examplee002d350ab26
, rundocker attach e002d350ab26
). - You can now run server CLI commands. To see the available options type
help
and press enter. - 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 eitherAdmin
orModerator
.
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 2GB 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 https://sh.rustup.rs | 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 https://gitlab.com/veloren/veloren.git
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.
./target/release/veloren-server-cli
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 removingplugins = ["server/plugins"]
fromserver-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 https://gitlab.com/veloren/veloren
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 https://gitlab.com/veloren/veloren/-/releases. 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 https://gitlab.com/veloren/veloren
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 eitheraarch64-unknown-linux-gnu
orarmv7-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"
[Unit]
Description=Veloren Server
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
User=<username>
WorkingDirectory=/home/<username>/veloren
ExecStart=/home/<username>/veloren/target/release/./veloren-server-cli
[Install]
WantedBy=multi-user.target
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 everytime 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:
userdata
âââ server
â  âââ saves
â  â  âââ db.sqlite
â  âââ server_config
â  âââ admins.ron
â  âââ banlist.ron
â  âââ description.ron
â  âââ settings.ron
â  âââ whitelist.ron
âââ server-cli
âââ settings.ron
server/server_config
This folder is the most interesting to us. It contains various important configuration files.
admins.ron
This file contains a list of UUIDs of players with administrator privileges.
You need access to server console to modify it.
Example:[ "f60e23c6-345c-449b-b05a-e431d53fc65c", ]
banlist.ron
This file contains the banlist, and associated information about each ban.
Server admins can use in-game commands to modify it.
Example:{ "7ea1a4cd-3002-4fe6-957e-4483f3fda3e7": ( username_when_banned: "YuriMomo", reason: "No testing bugs on this server >:(", ), }
description.ron
This file contains the server description - a single quoted string of text. You need direct access to the server files to modify it. Example:
"This is the best Veloren server"
settings.ron
This is the file containing most of the configuration options.
Most of the options are self-explanatory. You need direct access to the server files to modify it. Example:( gameserver_address: "0.0.0.0:14004", metrics_address: "0.0.0.0:14005", auth_server_address: Some("https://auth.veloren.net"), 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 eitherSome(value)
orNone
.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 toNone
means the server will never broadcast kill messages globally.
whitelist.ron
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 it.
Example:[ "f60e23c6-345c-449b-b05a-e431d53fc65c", ]
server/saves
This folder contains the server database.
server-cli
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.
Building
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.
Regions
TODO: Add documentation for region manipulation commands
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.
Persistence
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.
Enabling
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.
VELOREN_ASSETS
Optional variable to point to veloren assets directory. Not needed if you use Airshipper, but may be useful in more more exotic scenarios.
VELOREN_ASSETS_OVERRIDE
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.
WGPU_BACKEND
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
-
Open your singleplayer or server's settings file. See here.
-
Set your custom
world_seed
, andmap_file
toSome(Save(()))
. -
Launch your game as normal, whether you're doing it through singleplayer or the server cli.
-
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.
-
The world will be saved in a
maps
folder, as a binary file. Setmap_file
toSome(Load("maps/<filename>.bin")),
, else it will try to regenerate it each time.
map_file Options
Value | Description |
---|---|
None | Loads 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
-
Change the world seed, e.g.
world_seed: 40382,
-
Change
map_file
to something like
map_file: Some(Load("userdata/server/maps/map_1624935538562.bin")),
-
Optionally you can also set a spawn town:
spawn_town: Some("Elden"),
Make sure to use the correct filepath (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 filepath 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.
Unix-like:
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.
Troubleshooting
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).
Troubleshooting
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:
-
Switch to another graphics backend
-
Try disabling audio
đš 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.
Drivers
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.
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
To fix this, you may need to update your graphics drivers.
Graphical glitches in-game
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 withpacman -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:
- making sure Veloren is closed.
- locating
settings.ron
(See where Airshipper stores files) - editing it and replacing
output: Automatic
withoutput: Off
. It should look like:audio: ( master_volume: 1, music_volume: 1 sfx_volume: 1, max_sfx_channels: 10, output: Off, // The important line! ),
- 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
toAdwaita
when running the game -
If running via the command line, prepend
XCURSOR_THEME=Adwaita
to the command you use to run the game, likeXCURSOR_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
tox11
when running the game -
If running via the command line, prepend
WINIT_UNIX_BACKEND=x11
to the command you use to run the game, likeWINIT_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.
Performance
On this page you'll find tips and tricks to help you get the most out of Veloren.
Introduction
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.
Fragment-limited
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
Vertex-limited
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
CPU-limited
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 artifically 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.
Installation
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 alot of commands. Therefore we highly recommend getting comfortable with a terminal.
Git
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
.
Git LFS
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.
-
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 viaport install git-lfs
. -
Git LFS needs to be set up by running
git lfs install
orgit-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.
Rust
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 https://gitlab.com/veloren/dev/veloren.git
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 developement branch
git checkout <branch_name>
To switch back to master
git checkout master
Updating
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's a quick way to install most of these
- Download and run Visual Studio Build Tools and install "C++ tools" and "Windows 10 SDK", you won't actually be needing Visual Studio itself.
- Open Powershell (you should have it installed by default) and run the following commands:
The first line installs the Scoop package manager and the second line installs CMake, Ninja and Python through Scoop in one go.iwr -useb get.scoop.sh | iex scoop install cmake ninja python
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 ld.gold linker) - media-libs/mesa (with the
vulkan
use 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.
Linux
Prerequisites
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
.
Cross-Compiling
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:
[target.X]
linker="Y"
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.
Note
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/key_layout.rs
and replace all instances of
unsafe { &*(utf_key as *const [i8] as *const [u8]) }
with
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:
- Join our collaboration group: https://gitlab.com/veloren/dev.
- 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.
- Head over to https://gitlab.com/veloren/dev/veloren and clone the repository to your computer.
- 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:
-
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"
-
Add Veloren as your upstream remote:
git remote add upstream https://gitlab.com/veloren/veloren
-
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, rungit add
and then rungit commit --amend
andgit 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, sometimescargo 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
orgit 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.
- Count how many commits your branch contains, e.g. in
git status
. - Run
git rebase -i HEAD~N
, whereN
is the number of commits you counted in step 1. - 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. - 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
- Count how many commits your branch contains, e.g. in
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
- First, make sure you have no uncommitted work, e.g. by creating a new commit.
- Run
git fetch --all
to get all the latest changes. - 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. - 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
- Once your feature is ready for review, create an MR in GitLab from your branch
your-nickname/your-branch-name
toveloren/veloren/master
. - 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.
- 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.
For future contributions develop on a feature branch, in the Veloren repository, such as our CI tests can run through and assure you that your work is following the basic rules.
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.
Audio (led by Aeronic (@Aeronic#8377) & badbbad (@badbbad#5150))
Discussing, sharing and approving of music and SFX that will be featured in Veloren.
Members:
- alfy (@alfy#2440)
- Anthonyhme (@Anthonyhme#7923)
- BearPrince (@BearPrince#9687)
- Belosceani (@Belosceani#2722)
- CinchBlue (@CinchBlue#4950)
- DaforLynx (@DaforLynx#0296)
- Dan Tomlinson (@Dan Tomlinson#3395)
- Dean (@Dean#8369)
- desttinghim (@desttinghim#7648)
- djleo (@djleo#9001)
- Eden (@Eden#5844)
- Ellinia (@Ellinia#3221)
- GameTracks (@GameTracks#8088)
- ilijapantelic (@ilijapantelic#7530)
- jimbles (@jimbles#1407)
- jey133 (@jey133#8652)
- Juli199696 (@Juli199696#4232)
- MisterTeapot (@MisterTeapot#6718)
- octoshrimpy (@octoshrimpy#4419)
- Ryxalis (@Ryxalis#2269)
- sharpie (@sharpie [UTC+1]#4797)
- sheldon_K (@sheldon_K#0637)
- Snow (@Snow#6325)
- TheBoiRoy (@TheBoiRoy#6737)
- TheSadFish (@TheSadFish#0395)
- tumor (@tumor#3144)
- wraithlord_koto (@wraithlord_koto#8366)
- æȘæ„ă·ă«ăăŒ (@æȘæ„ă·ă«ăăŒ#9339)
Assets & Visual Design (led by @Pfau#4686)
3D models, 2D pixel art/icons, UI design, concept art.
Members:
- Demonic (@Demonic#5646)
- Gemu (@Gemu#3901)
- SrMizuki (@SrMizuki#7663)
- WelshPixie (@WelshPixie#9174)
- zesterer (@zesterer#3131)
Combat (led by Sam (@GoldFalcon9#7302))
Weapons, armor, combat abilities, enemies, and other combat-related things.
Members:
- Adam (@Adam#3081)
- CinchBlue (@CinchBlue#4950)
- Demonic (@Demonic#5646)
- James (@James M#8698)
- Jollyfish (@Jollyfish#9021)
- Nancok (@Nancok#4576)
- Nero (@Nero#6962)
- Pfau (@Pfau#4686)
- Qutrin (@MCLowicz#3632)
- Sam (@GoldFalcon9#7302)
- Shinji (@Shinji#2986)
- Slipped (@Slipped#6555)
- Timo (@Timo#6669)
- xMAC94x (@xMAC94x#2493)
- zesterer (@zesterer#3131)
Game Design (led by Silentium (@Silentium#2318))
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.
Members:
- Adam (@Adam#3081)
- Irvin Rivas (@BrownSugar (Irvin Rivas)#8843)
- Comfy (@Comfy#8528)
- Cutler (@Cutler (Callial)#9296)
- DaforLynx (@DaforLynx#0296)
- DoNeo (@DoNeo#1402)
- Felixander (@Felixader#2540)
- Jollyfish (@Jollyfish#9021)
- dorf (@dorf#0022)
- Kalculate (@Kalculate#1997)
- Mr. Dan (@Mr. Dan#9231)
- Nancok (@Nancok#4576)
- Sgt-Chef Nightwalk (@Sgt-Chef Nightwalk#7734)
- RonVal4 (@RonVal4#5635)
- Sam (@GoldFalcon9#7302)
- Sharp (@Sharp [GMT +2]#3429)
- Slipped (@Slipped#6555)
- The Dip (@The Dip#5237)
- Timo (@Timo#6669)
- Tortolonch (@Tortolonch#2150)
- Warspawn (@Warspawn#9707)
- zesterer (@zesterer#3131)
Meta (led by AngelOnFira (@AngelOnFira#8441))
Heads up CI, the website, the Discord, and lots inbetween.
Members:
- Acrimon (@Acrimon#2954)
- Mckol (@Mckol#3307)
- Sharp (@Sharp [GMT +2]#3429)
- Songtronix (@Songtronix#4790)
- Timo (@Timo#6669)
- xMAC94x (@xMAC94x#2493)
- zesterer (@zesterer#3131)
Rendering (led by imbris (@imbris#4559))
Graphics, windowing, and UI logic for Voxygen.
Members:
- Capucho (@Capucho#9388)
- Sharp (@Sharp [GMT +2]#3429)
- xMAC94x (@xMAC94x#2493)
- zesterer (@zesterer#3131)
Server & Multiplayer (led by xMAC94x (@xMAC94x#2493))
Create servers that can host many people, and make multiplayer experience as great as possible.
Members:
- Acrimon (@Acrimon#2954)
- Geno (@Geno#5369)
- xMAC94x (@xMAC94x#2493)
- zesterer (@zesterer#3131)
Testing (led by YuriMomo (@YuriMomo#3795))
Testing the game by using specialized tools and making sure new features don't introduce any bugs.
Members:
- AsyncTheory (@ProTheory8#3931)
- James (@James M#8698)
- Sharp (@Sharp [GMT +2]#3429)
- Songtronix (@Songtronix#4790)
- Treeco (@đ¶Treecođ¶#1412)
- xMAC94x (@xMAC94x#2493)
- YuriMomo (@YuriMomo#3795)
- zesterer (@zesterer#3131)
UX (led by Songtronix (@Songtronix#4790))
We improve Veloren's user experience 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.
Members:
- Gemu (@Gemu#3901)
- Snow (@Snow#6325)
- YuriMomo (@YuriMomo#3795)
- zesterer (@zesterer#3131)
Worldgen (led by zesterer (@zesterer#3131))
World generation, world simulation and terrain generation.
Members:
- Acrimon (@Acrimon#2954)
- Geno (@Geno#5369)
- Sharp (@Sharp [GMT +2]#3429)
- Treeco (@đ¶Treecođ¶#1412)
- xMAC94x (@xMAC94x#2493)
- zesterer (@zesterer#3131)
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.
Troubleshooting
Incase you've hit an issue this section might help you resolve it.
Git LFS
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
To setup LFS and download the asset files on Linux or Windows
git lfs install
git lfs fetch
git lfs checkout
MacOs
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 "GIT_ASKPASS=%SSH_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 commiting if your IDE doesn't support it by default.
Just create a file .git/hooks/pre-commit
with the following content.
#!/bin/sh
#
# 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" ]
then
exec cargo fmt --all -- --check
else
echo "change files via fmt"
cargo fmt --all --
echo "adding all files via git add ."
exec git add .
fi
# enable change to make fmt change files instead of just warn
# git config hooks.changefmt true
Dependencies
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!
Features
- đŠ Weather
- đ Player-driven building
- đ° Server browser
- đ Translations
- đČ Balancing and tiers
- đž Economy rework
- đŁ Chat
- đ Build mode
- â° Worldgen
- đ„ Hitboxes
- đč Aiming (ranged weapons)
- đĄ Scrolling combat text (SCT)
- đč Trading improvements
- đą Creature variants
- đ„· Stealth
- đ§© Plugins
- đȘŽ Sprites & item models
- đĄ Auras
- đ NPC sound effects
- đ Sound effects
- đ¶ Pets
- đĄ Combat
- đ§ NPC/enemy AI
- â Server-side anti-cheat
- đ GDPR and Privacy
Platform Support
Internals
Developers bug-free sky
Introducing the power of Rust development
- Installing an IDE
- Learning Rust
- ECS
- The codebase structure
- Coordinate Systems
- Debugging
- Performance Analysis
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.
ECS
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:
#![allow(unused)] fn main() { struct Entity { position: Vec3<f32>, velocity: Vec3<f32>, } }
When representing multiple entities, it's common to use an array-like data structure.
#![allow(unused)] 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.
#![allow(unused)] 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
Crates
Veloren is split into several Rust crates. The purpose of this is twofold.
-
Reduce compilation time by allowing parallel processing of crates during compilation
-
Allow users of the Veloren ecosystem to only depend on specific parts of the project
Frontends
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:
- Teloren, a command-line frontend with nethack-style graphics
chat-cli
, a chat-only command-line frontend
(Is something missing from this list? Feel free to add it)
voxygen
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.
server-cli
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.
Backends
As mentioned, Veloren implements core gameplay functionality through headless developer-facing libraries. These are:
server
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.
client
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.
world
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)
Implements behaviour and contains definitions that are common to both client and server.
network
Contains the raw implementation of Veloren's networking utilities.
Plugins
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:
plugin-rt
The core plugin runtime. This crate facilitates communication with the host engine and manages plugin hooks and IO.
plugin-api
Contains type defintions 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.
plugin-derive
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 neccesarily 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/lod.rs
)
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.
Debugging
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 vscode installation.
After that make the following modifcations 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 :P.
Troubleshooting
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 'panicking.rs': Unable to read file (Error: File not found
(c:\rustc\7dbfb0a8ca4ab74ee3111e57a024f9e6257ce37c\src\libstd\panicking.rs)).
Performance Analysis
You want to improve velorens performance? But you don't know how to best measure velorens 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
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 velorens performance, but is not very detailed.
Prometheus statics are exported by default whenever you run veloren-server-cli
Open your webbrowser http://localhost:14005 to see the raw values.
You can import this data into prometheus via this tutorial: https://prometheus.io/docs/prometheus/latest/getting_started/
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: https://prometheus.io/docs/visualization/grafana/ You'll find example dashboards in the veloren infrastructure repo (not yet available): https://gitlab.com/veloren/infrastructure/-/blob/master/veloren-infra/templates/grafana-dashboads-gameserver.yaml
Tracy
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 https://github.com/wolfpld/tracy/releases/latest/download/tracy.pdf.
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: https://github.com/wolfpld/tracy/releases
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 theCargo.lock
file at the repo root and checked against this table https://github.com/nagisa/rust_tracy_client#version-support-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 indling projects.
External tooling
rust: flamegraph
follow the installation tutorial here: https://github.com/flamegraph-rs/flamegraph
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 Comminity Edition (Windows only)
visual studio has a build in profiler, follow this tutorial and attach it to the running veloren program: https://docs.microsoft.com/de-de/visualstudio/profiling/cpu-usage?view=vs-2019
valgrind/cachegrind
you can use valgrind/cachegrind profiler to generate a output file and later analyse it via valgrind. Tutorial: https://www.valgrind.org/docs/manual/cg-manual.html
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:
#![allow(unused)] 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:
#![allow(unused)] fn main() { ( name: "Original Title", source_link: "https://fonts.com/fancyfont/", authors: ["Author One"], asset_path: "relative/path/to/fancyfont.ttf", license: "CC BY-SA 3.0", license_link: "https://creativecommons.org/licenses/by-sa/3.0/", modifications: "Trivial modification", ) }
Derivative work can be formatted in the current scheme like:
#![allow(unused)] fn main() { ( name: "Derivative Title", source_link: "https://fonts.com/fancyfont/", authors: ["Author Two (derivative)", "Author One (original)"], asset_path: "relative/path/to/fancyfont.ttf", license: "CC BY-SA 3.0", license_link: "https://creativecommons.org/licenses/by-sa/3.0/", 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:
- https://wiki.creativecommons.org/wiki/Best_practices_for_attribution
- https://creativecommons.org/faq/#attribution
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 Magica.
At some point we might create our own voxel editor with built in model rigging and animating.
Getting started - Useful links
Magica 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 Magica 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, shwoing 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 .ogg format, 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 a .ogg 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 mod.rs
's in voxygen\src\audio\sfx\
.
Outcome sfx are retrieved from sfx.ron
and handled in voxygen\src\audio\sfx\mod.rs
. 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\outcome.rs
.
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\ambient.rs
, 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
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.
Exploration
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, Snowland, 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\biome.rs
.
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 supercede others - most notably, snow-covered mountains will count as Snowland. If you want to know exactly how biomes are determined, see
get_biome()
inworld\src\sim\mod.rs
.
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.
Combat
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 aloop
. If the composer is smart, they can shorten this segment by having it somehow transition perfectly into theloop
without playing the entireloop
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 theloop
, and is only played if the fadeout can't complete before theloop
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
.
Translators multilingual society
Introduction on translating content to your language.
Translate the Game
Preparation
There are different ways to contribute translations, but the most straightforward way is using git and rust. You don't need to compile the game, although debug builds have useful features like hot-reloading for translations, that allow you to translate the game while running it. Tooling to check the status of your translations doesn't require compiling the full game, but it still requires the Rust toolchain. Read this guide on basic tooling (git lfs is important), working with git (git is not most user friendly thing, ask if you don't understand something), compile instructions, and contribution instructions (most important).
Alternatively, you can just work on directly on assets shipped by Airshipper. Beware that updating your game will purge all your work, so think about using VELOREN_ASSETS_OVERRIDE
File and directory structure explained
You can see the localization files inside the assets/voxygen/i18n
directory.
Each directory in this directory represents a language (or a variant of it).
The directories are named after the ISO 639-3 codes.
(en/
, de_DE/
, pt_BR/
etc.)
Veloren uses a key-value system to translate content. Files use the Fluent
localization format (.ftl
). Check examples at the
main page and syntax guide.
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. Don't be afraid to ask for the addition of these
characters to the fonts used by the game via our Discord community
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: language identifier must correspond to the name of language folder, which implies that it must correspond to ISO 639-3 standard.
.ftl 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
Some messages may have multiple attributes attached to them. Attributes can have various uses, as of the time of writing we use it to create randomized messsages.
loading-tips =
.a0 = Press '{ $gameinput-togglelantern }' to light your lantern.
.a1 = Press '{ $gameinput-help }' to see all default keybindings.
.a2 = You can type /say or /s to only chat with players directly around you.
.a3 = You can type /region or /r to only chat with players a couple of hundred blocks around you.
Fluent also supports plural selectors via unicode rules.
hud-trade-buy_price = Buy Price: {$coins ->
[1] 1 coin
*[other] { $coins } coins
}
Localization test explained
Veloren includes a localization test for translated languages. This test
gathers information about every key and compares them with the reference
language (English, en/
directory). Then it classifies and counts these
comparisons and prints them in a neat way for translators to inspect.
This guide explains where to find the test and how to read the results of it.
We have this fancy web service
to display translations statistics.
We will use the Ukrainian translation as our example.
Here we have detailed information about all language keys used in the Ukrainian
translation (uk_UA
directory) in comparison with the reference English
translation (en
directory). Here is what the status
section for keys mean:
-
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
: Currenty not available, means that some changes were made to the English translation, but not to the Ukrainian translation.
Guide to translating the game
Guides to help you translate the game, for certain situations. If you get stuck at any step or need more help (or just have questions) ask us in our Discord server.
If you are not familiar with Gitlab or Git, feel free to ping @git-wizard
,
who will always be on deck to help with this.
Create a translation from scratch
If there is no translation for your language, you can create one by following these instructions. Remember to replace the Turkish language example with your own language!
First of all, you need a copy of the Veloren repository. Refer to the working with git section for this.
After you have obtained a copy of the repository, navigate to the assets/voxygen/i18n
directory. Here you'll see a list of translations, and the reference English directory
(en/
).
Make a copy of the en/
directory, named after your language. For example, if you want
to translate Turkish, your directory would be named tr_TR/
.
Then, you can start editing the file! First go to the metadata section in _manifest.ron
.
This section has the display name and the identifier for your translation. Change
language_name
to a human readable name in your language (eg. TĂŒrkçe (TĂŒrkiye)
,
means Turkish (Turkey)
in English) and change language_identifier
to the
identifier of your language (usually same with the file name, eg. tr_TR
).
And that's it! No code changes required. You can now start translating any key you want. Don't forget to preview the changes ingame by compiling and running the game, and setting the language setting to your new in-translation language. If there are missing characters, don't worry, you can ask us about these in our Discord server.
Tip: you don't need to compile game to test your changes, you can
just copy your changes to assets
directory in app folder.
If you have installed the game via Airshipper look in these
directories
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.
After you are happy with your translation, commit your changes with a proper
commit message, such as Added Turkish (Turkey) translation
. Create a new
branch with name <yourusername>/add-<language>
. Then push your changes and
create a merge request (don't forget to read and tick all the boxes!). You can
notify us on the Discord server that there is a new translation available
(in the #translation channel).
Improving an existing translation
If you are lucky, you may already find that there is a translation for your language. If you see that it has some missing, incorrect translations or you think that you have a better translation for something, then this guide is for you! Don't forget to replace the Ukrainian example with your own language (if you aren't translating the Ukrainian language).
Okay, let's say we want to add the correct translation for the Ukrainian of
buff-desc-cursed
.
So we first want to look it up in the reference language (English)
assets/voxygen/i18n/en/buff.ftl
.
After the key we find this English sentence: Cursed
. We know that
the Ukrainian equivalent would be ĐŃĐŸĐșĐ»ŃĐœ
(Well, some of us do :P).
Then, we open the translated language (Ukrainian)
assets/voxygen/i18n/uk_UA/buff.ron
.
Tip: Keep both the reference language and the translated langauge open, so that you can find in which place your entry is missing by looking at the line numbers.
Once you are editing the file on Gitlab, go to the place where our entry is missing and add it here:
buff-title-cursed = ĐŃĐŸĐșĐ»ŃĐœ
buff-desc-cursed = ĐĐ°Ń ĐżŃĐŸĐșĐ»ŃлО
Getting information about translation
If you are able to compile, you can use special tool to get information about translation. Basically, it is the same programm that runs on our CI, but you can cut out unneded information. For example, you want to get information about Ukrainian translation.
$ cargo run --bin i18n-check --features=bin -- uk_UA
You can also run it with --help
argument to find out more ways to use it.
Note: arguments go after --
, it's where cargo
arguments end and actual
arguments start.
Note: you need to commit your changes for veloren-i18n
to know about it.
Push changes
When you're done (or even before you start), create a branch with name
<yourusername>/update-<language>
. An example would be juliancoffee/update-uk_UA
.
Then create a commit and give it specific commit message such as update the <language> translation
. In our example this would be update the Ukrainian translation
.
Finally, you'll need to create a merge request. Note that you need to push your
branch to the developer repository, while making a MR from developer repository
to main one.
Read and check the boxes to agree that your code will be under the GPL3 license.
If you have Contributor role, use /review command in #new-contributors channel. If you don't have it, ask for it and use /review command.
You now requested to change the files, and we will then take a look at it and if
we found it okay we will merge it into the game! From that point on your
contribution will land in the master
branch, and in at most a week will be
shipped to players via Airshipper.
Help review pending translations
Someone may have done a translation for your language already. To check this,
you can take a look at the Merge Requests page.
See if you can find a pending merge request with your language (e.g. de_DE
).
Ask in our Discord server for reporter privileges so you can open it and add
your thoughts / reviews to it.
If you found one, clicking on the Changes
tab when you're in the MR page you
can see the details of this change. Red lines are old ones that are removed
and replaced by green lines. If you disagree with something that was added,
you can start a discussion by clicking on the respective line. If you don't
see any issues with the proposed changes, feel free to approve the MR or
comment on it. It's important that you approve the MR for translations as we
the developers don't have the knowledge to verify the language (and we don't
want to put everything through Google Translate). So you help us to verify
others contributions resulting in improved game quality.
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:
content
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))
),
content
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 benifits.
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.
Technology
We use gitlab runners in combination with docker.
Requirements
-
= 2 cpu cores. we don't cause constant 100% load, but when a compilation even comes it, more cores help to quickly process them.
- 50gb of free hdd space. The docker image contains a cache and is about 20gb 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 https://gitlab.com/veloren/veloren-docker-ci
cd veloren-docker-ci/runner
./launch-runner.sh
# 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 update-runner.sh
script.
Note, it is interactive and requieres your input
# 1. update repo veloren-docker-ci repo
git pull
# 2. go in runner folder
cd runner
# 3. execute update script
./update-runner.sh
# 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
Tasks
When: 2 month before release
Where: Sunday Meeting
- roughly select a release-date and communicate that to internal parties (Note: it might be changed is not official yet!)
- The following questions are answered:
- What is the theme of this party
- what features should be definitely in it, what features might get in
- a map responsible is chosen, we plan how it will look like
- a trailer responsible is chosen, we plan what it should contain
- a release blog writer is chosen
- a responsible for the feature freeze is chosen
- a responsible for the release-binary is chosen
- a responsible for social-media posts is chosen
- a schedule for the party is created, we plan activities, how long they will take and responsibles for those activities
- a gitlab Milestone is created to track progress of this release.
When: 1 month before release
Where: Sunday Meeting
- pick a final release date when core devs (e.g. Angle, xMac) are available and responsibles can make it.
- feedback from the activities, trailer and map responsibles is discussed, what is their state, what do they plan. Do they need to adjust? Can they make the schedule?
Who: feature freeze-responsible
- feature freeze schedule is posted
Who: Blog post responsible
- Blog is prepared and written
Who: Social Media responsible
- Posts are prepared and written
When: 3 weeks before release
Who: Map responsible
- Map is ready enough for the trailer
Who: Activities responsible
- Activities are ready enough for the trailer
Who: Core Devs
- Map and Activities are reviewed by Core Devs
Who: Feature Freeze responsible
- Features that are necessary are collected and are planned who reviews and merging is done.
When: 2 weeks before release
Who: trailer responsible
- Trailer is ready enough to be reviewed
Who: Core Devs
- Trailer is reviewed by Core Devs
When: 1 week before release
Who: Feature Freeze responsible
- Schedule is applied over the next week and watched by responsible
Who: map/activities
- all tasks are completed and are waiting to be executed
Who: trailer responsible
- the trailer is uploaded and live
Who: Blog post responsible
- the Blog post is uploaded and live
When: 8 hours before release
Who: Social Media Responsible
- Posts are done
Who: map/activities
- upload map and activities to the server
Who: release-binary responsible
- Release commit is merged and Release Binaries are distributed
When: Sunday after release
Where: Sunday Meeting
- Discuss pro and contra of the release party
Details:
Gitlab Milestone
# v0.xx Release
## Responsibles
blog:
trailer:
map:
feature-freeze:
release-binary:
social-media:
## Overview
Theme is: ``
Rough Release day is: ``
Included features are:
-
Excluded features are:
-
Party Schedule is:
- 18:00 GMT+0 start of party
## Checklist
Sunday Meeting:
- [ ] Fixed Release day is: `` *(T-1 month)*
- [ } Map is approved by CoreDevs
- [ } Activities are approved by CoreDevs
- [ } Trailer is approved by CoreDevs
Blog:
- [ ] release blog is prepared *(T-1 month)*
- [ ] release blog is uploaded *(T-1 week)*
Trailer:
- [ ] trailer is ready for review *(T-2 weeks)*
- [ ] trailer is uploaded *(T-1 week)*
Map:
- [ ] 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-Binary:
- [ ] Release Binaries are producuded uploaded and verified *(T-8 hours)*
Social-Media:
- [ ] posts are prepared *(T-1 month)*
- [ ] posts are uploaded uploaded *(T-8 hours)*
Social-Media plan
- T-1 week @NewsPingSquad @MediaPingSquad
- T-30 mins @everyone
- T-8 hours reddit/
- T-8 hours twitter
Feature Freeze Posts
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#2493 in the <#992383235332001942> thread with a short summary with the following details (the more, the better):
* 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.
**Schedule**
``
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!
``
Binary Release Plan
- Copy over CHANGELOG, update only
server
,client
,server-cli
,voxygen
crates - the others are on a independent semver. example MR - create release branch from master
git checkout -b "r0.12"
- create release tag
git tag -a "v0.12.0" -m "release 0.12.0"
- push release tag
git push --tag "v0.12.0"
- verify a release tag pipeline runs: https://gitlab.com/veloren/veloren/-/pipelines
- verify release container is build: https://gitlab.com/veloren/veloren/container_registry
- add link to https://veloren.net/download-other/
- create a release on gitlab
- verify a release binary is copied to wasabi
Release a new Version
- Copy over CHANGELOG, update only crates. example MR
- create release branch from master
git checkout -b "r0.7"
- create release tag
git tag -a "v0.7.0" -m "release 0.7.0"
- push release tag
git push --tag "v0.7.0"
- verify a release tag pipeline runs: https://gitlab.com/veloren/airshipper/-/pipelines
- verify release container is build: https://gitlab.com/veloren/airshipper/container_registry
- verify github/airshipper actions to build a release binary
- create a release on github
- 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.
Note:
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.
Tip:
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 tosystem
. - 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
Guides
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 greyscale 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:
assets/voxygen/voxel/armor/chest/leather_vest-0.vox
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 ingame item)
assets\voxygen\item_image_manifest.ron
(create a new entry in here to add an item image to the item)
common/src/comp/inventory/item/armor.rs
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).
Item(
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(
"element.icons.lantern_black-0",
),
Example for a .vox:
Armor(Back("Short0")): VoxTrans(
"voxel.armor.back.short-0",
(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(
"voxel.armor.back.new_cape-0",
(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 ingame.
"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: Adding sprites to Veloren
\_ made by @Pfau
What you need:
-
An IDE of your choice (A programme that lets you view and edit code)
-
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 lanscape 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
assets/voxygen/voxel/sprite_manifest.ron
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.
common/src/terrain/sprite.rs
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
-
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 thefurniture
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 filewindow-0.vox
was added to thewindow
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 to0.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. -
Telling the game the sprite exists and making it solid
In
common/src/terrain/sprite.rs
Near the beginning of the file, look for a long list of objects with a heaxdecimals 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 findWindow1 = 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 thesprite.rs
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 definied 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. -
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
incommon/src/terrain/sprite.rs
. - If the sprite requires mining, add it to
pub fn mine_tool
incommon/src/terrain/sprite.rs
. - 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/sprite.rs
. This will involve creating a .ron file inassets/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/sprite_interact.rs
in the sectionfn from(sprite_kind: SpriteKind) -> Self
.
- Create a .ron file for your collectible sprite in subfolder of
- Add sprite to
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
- Example:
- 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/scatter.rs
contains code for items such as flowers, twigs, stones, etc. Anything that is 'scattered' about in the environment randomly.world/src/site2/plot/house.rs
contains 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:
-
An IDE of your choice (A programme that lets you view and edit code)
-
A Voxel Editor (To create the weapon model)
Example: Magicavoxel
-
A compiled version of veloren(So you can edit the game's files)
Optional:
-
A character template. (Can be opened with any voxel-editor that supports layers; i.e. Magicavoxel.)
-
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 becuase 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...
-
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.
-
Made sure that there is No extra space can be shaved of without sacrificing voxels.
Go to the filepath below and paste your .vox file and rename it according to the naming scheme below.
assets/voxygen/voxel/weapons/<Weapon Type>/<Model Name>
The filepath to the file should look something like this by the time you finish
assets/voxygen/voxel/weapon/sword/long_2h_fine-0.vox
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
Item(
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
assets/voxygen/voxel/humanoid_main_weapon_manifest.ron
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 tool.rs
Open common/src/comp/inventory/item/tool.rs
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 {
BasicShortbow,
WoodShortbow0,
WoodShortbow1,
LeafyShortbow0,
}
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 pratical to use a vox model for weapons.
Example for a .vox:
Tool(Longbow(WoodLongbow1)): VoxTrans(
"voxel.weapon.longbow.longbow_wood-1",
(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(
"voxel.armor.back.new_cape-0",
(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 dont 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 ingame.
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 127.0.0.1:9938 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 {
BasicMelee,
BasicRanged,
Boost,
ChargedRanged,
ChargedMelee,
DashMelee,
BasicBlock,
TripleStrike(Stage),
LeapMelee,
SpinMelee,
}
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 accomodate 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/tool.rs
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 skillbar slot 1, and additional ones to more skillbar slots (only skillbar 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/ability.rs
.
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 tool.rs, the second one reads from tool.rs, 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/tool.rs
.
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/mod.rs
.
Add your character state to this file, keep it sorted alphabetically
Go to common/src/comp/ability.rs
.
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/tool.rs
.
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 ability.rs.
Go to common/src/comp/character_state.rs
.
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/character_behavior.rs
.
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/stats.rs
.
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 Skillbar
(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 skillbar or move a currently existing ability to the skillbar.
In the tool.rs 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 skillbar 1, the fourth skillbar 2, etc. So when adding your ability, ensure that it is in the correct location in the abilities vector.
Go to voxygen/src/hud/hotbar.rs
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 {
true
}
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/img_ids.rs
.
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 skillbar, add your skill/icon pair to the "Icons" section around line 270 instead.
Go to voxygen/src/hud/skillbar.rs
.
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 self.energy.current()
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/skillbar.rs
. 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/slots.rs
.
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 herebut 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).
Animations
Ping @Slipped on Discord.
You can also dig through previous MRs (like this one: https://gitlab.com/veloren/veloren/-/merge_requests/1171/diffs
) 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).
Changelog
Go to CHANGELOG.md
Add a line saying you added an attack
Modding the game
You don't always need to know how to code!
- Writing a plugin
- [Adding server-side assets with manifests]
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.
Requirements
-
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.
Overview
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
-
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
:
[lib]
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 = "https://gitlab.com/veloren/veloren.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-unknown-unknown
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-unknown-unknown
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
)
my_plugin.plugin.tar
|- 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-unknown-unknown/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-unknown-unknown
cp target/wasm32-unknown-unknown/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 lib.rs
, enter the following:
#![allow(unused)] fn main() { use veloren_plugin_rt::{*, api::{*, event::*}}; #[event_handler] 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.
#![allow(unused)] fn main() { use veloren_plugin_rt::{*, api::{*, event::*}}; }
Here, we import the necessary macros, types and functions we need to write our plugin.
#![allow(unused)] fn main() { #[event_handler] pub fn on_load(load: PluginLoadEvent) { ... } }
Here, we declare a new functon 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.
#![allow(unused)] 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 Action
s! 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 lib.rs
:
#![allow(unused)] fn main() { #[event_handler] pub fn on_command_ping(chat_cmd: ChatCommandEvent) -> Result<Vec<String>, String> { Ok(vec![String::from("Pong!")]) } }
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:
#![allow(unused)] fn main() { #[global_state] #[derive(Default)] 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:
#![allow(unused)] fn main() { #[event_handler] 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
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 a interview, our discord channel is the best way to reach out to us.
Official information is available under https://veloren.net/. 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
Logos
We have 1 Full-size logo, as well an icon version of our logo, in 2 sizes.
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.
Internals
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, 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)
* 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
** You can see a nice simple example of erosion algorithm here (you can skip to 3:52) click here to open youtube video
*** 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-explainatory:)
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
Wiring
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 informations.
- Inputs (data injected by Circuit)
- Outputs (information of how to compute output)
- Actions (information about what should happen if inputs are in given state)
Each wiring tick has 3 stages:
- Compute (take each Wiring component, feed inputs into output formulas, produce outputs)
- Transport (get outputs of previous step and using Circuit pass them around)
- Dispatch (get inputs (note that we are using modified state by transport) and dispatch logic)
Compute
- 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. (atm all results are
f32
)
- E is an
Transport
- 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
andto 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.
Dispatch
- 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
Constant
Outputs constant value.
Input
Outputs value of input field under given name.
Logic
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.
OnCollide
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.
OnDeath
Returns value * count of entities that died in last tick in given radius
.
Actions
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.