Skip to content

How-To GDNative

For those of you who are comfortable compiling or want to give it a shot, here are some steps to follow.

Set Up Tools

Follow Godot's documentation to setup the required tools for your operating system.

Get GodotSteam GDNative

This is a little different from the modules as we get GodotSteam's source first and then Godot's.

Cloning the Source

You can clone the source into a folder called godotsteam_gdnative like so:

git clone -b gdnative https://github.com/GodotSteam/GodotSteam.git godotsteam_gdnative

Cloning the repo should also pull the sub-module for Godot CPP, so you can skip to Get the Steamworks SDK.

However, you may want to change the version of Godot CPP, depending on your target version. If so, read the next section Get Godot CPP.

Downloading the Source

Alternatively, you can download the GDNative source from our repository then unpack it into a folder named godotsteam_gdnative. You will need to pull the Godot CPP source yourself if you use this method.

Get Godot CPP

Cloning the Source

If you changed your target version or manually downloaded the GDNative source, you can head into the godotsteam_gdnative folder and clone the latest Godot CPP source in a folder called godot-cpp like so:

git clone https://github.com/godotengine/godot-cpp.git -b godot-3.5.1-stable godot-cpp

You may need to change the given tag(s) above from whatever it is to whatever the current version or whatever version you need.

Downloading the Source

Alternatively, you can download and unpack the Godot CPP source from their Github in a folder called godot-cpp.

Compile the Bindings

In either case, you will want to head into the godot-cpp folder and compile the bindings for your platform. Make sure your slashes are OS appropriate:

scons platform=<your platform> generate_bindings=yes target=release

Get the Steamworks SDK

Download the Steamworks SDK from Valve's partners site. This requires a Steam developer account.

Move the public and redistributable_bin folders from the unzipped Steamworks SDK into the godotsteam_gdnative/godotsteam/sdk/ so you have the following layout:

godotsteam_gdnative/
└─ godotsteam/
   └─ sdk/
      ├─ public/*
      └─ redistributable_bin/*

Double-Checking Folder / File Structure

Before we start compiling, let us make sure everything is in place. Your godotsteam_gdextension directory should look something like this:

godotsteam_gdnative
│─ bin/
├─ godot-cpp/
│  ├─ bin/*
│  ├─ godot-headers/*
│  ├─ include/*
│  ├─ misc/*
│  ├─ src/*
│  ├─ test/*
│  ├─ binding_generator.py
│  └─ SConstruct
├─ godotsteam/
│  ├─ sdk/
│    ├─ public/steam/*
│    └─ redistributable_bin/*
│  ├─ godotsteam.h
│  ├─ godotsteam.cpp
│  ├─ gdootsteam_constants.h
│  └─ init.cpp
├─ VisualC/*
└─ SConstruct
You probably will not have the bin/ folder in the root so go ahead and create that.

Compiling Time

Just run the following command for your operating system from the godotsteam_gdextension folder root:

scons platform=windows production=yes target=release

Follow these steps for Visual Studio (big thanks to willnationsdev):

  • Create a new Visual Studio project.
  • Name it GDNative and make sure it DOES NOT create a directory.
    • Uncheck the box here.
  • Select the GDNative folder we were working in.
  • Choose Win32 Desktop Wizard template.
  • Select options for both a dynamic library (.dll) and an empty project.
  • Things should look like this:
    GDNative -godot-cpp -godot_headers -lib -GDNative --.vs --GDNative.sln --GDNative.vcxproj --GDNative.vcsproj.filters -src
    
  • Make sure you have a debug, x64 configuration for the solution.
    • The options are located in the toolbar at the top left.
  • Go to "Project > GDNative Properties" to open the project properties.
  • Ensure you are on the x64 Debug configurations at the top and make these changes:
    • VC++ Directories > Include Directories. Add 'GDNative\godot-cpp\include', 'GDNative\godot-cpp\include\core', and 'GDNative\godot-cpp\godot-headers' to the list.
    • VC++ Directories > Library Directories. Add 'GDNative\godotsteam'.
    • VC++ Directories > Source Directories. Add 'GDNative\godotsteam'.
    • C/C++ > Linker > System. Subsystem = "Console (/SUBSYSTEM:CONSOLE)"
    • C/C++ > Linker > Input. Add "godot-cpp.windows.64.lib" (without quotes) to the Additional Dependencies parameter.
  • Click on Apply and then Save.
  • Now build the solution.
scons platform=linux production=yes target=release
scons platform=osx production=yes target=release

All Together Now

When compiling is finished, create a brand new folder somewhere called addons and, inside that, create a folder called godotsteam.

Now copy the whole win64/, linuxbsd/, or osx/ folder(s) from within the godotsteam_gdnative/bin/ folder into addons/godotsteam/. We will want to rename that linuxbsd folder to x11.

You will also want to copy the matching Steamworks API file(s) from godotsteam_gdnative/godotsteam/sdk/redistributable_bin/ and put them in with the corresponding platform's folder.

This all sound a little confusing? It should look a little something like this:

addons
└─ godotsteam
   └─ win64
      │─ godotsteam.dll
      └─ steam_api64.dll
addons
└─ godotsteam
   └─ x11
      │─ libgodotsteam.so
      └─ libsteam_api.so
addons
└─ godotsteam
   └─ osx
      │─ libgodotsteam.dylib
      └─ libsteam_api.dylib

Making godotsteam.gdnlib

In a text editor, create a file called godotsteam.gdnlib and place the following inside this file then save it in the addons/godotsteam/ folder:

[general]
singleton=false
load_once=true
symbol_prefix="godot_"
reloadable=true

[entry]
(read below)

[dependencies]
(read below)

Replace (read below) with the following, based on platform. You can also use all three if you have the right files.

[entry]
Windows.64="res://addons/godotsteam/win64/godotsteam.dll"

[dependencies]
Windows.64=[ "res://addons/godotsteam/win64/steam_api64.dll" ]
[entry]
X11.64="res://addons/godotsteam/x11/libgodotsteam.so"

[dependencies]
X11.64=[ "res://addons/godotsteam/x11/libsteam_api.so" ]
[entry]
OSX.64="res://addons/godotsteam/osx/libgodotsteam.dylib"

[dependencies]
OSX.64=[ "res://addons/godotsteam/osx/libsteam_api.dylib" ]

To double-check this worked, place the addons folder in a Godot project then open the .gdnlib file in the Inspector. It will have the correct data in the GUI editor that pops up in the bottom panel.

Making godotsteam.gdns

In a text editor, create a file called godotsteam.gdns and place the following inside this file then save it in the addons/godotsteam/ folder:

[gd_resource type="NativeScript" load_steps=2 format=2]

[ext_resource path="res://addons/godotsteam/godotsteam.gdnlib" type="GDNativeLibrary" id=1]

[resource]

resource_name = "godotsteam"
class_name = "Steam"
library = ExtResource( 1 )
script_class_name = "Steam"

Making steam.gd

In a text editor, create a file called steam.gd and place the following inside this file then save it in the addons/godotsteam/ folder:

extends Node

onready var Steam: Object = preload("res://addons/godotsteam/godotsteam.gdns").new()
var steam_app_id: int = 480   # or your game's app ID


func _init() -> void:
  OS.set_environment("SteamAppId", str(steam_app_id))
  OS.set_environment("SteamGameId", str(steam_app_id))

func _ready():
  var initialize_response: Dictionary = Steam.steamInitEx()
  print(initialize_response)

After placing the addons/ folder into your project, you will want to navigate to Project > Project Settings in the editor and click on Autoload then add your steam.gd as a singleton, with the name Steam.

Good to Go

GodotSteam GDNative will behave a little differently than the modules or GDExtension since it has to be loaded in and passed to an object in the steam.gd file.

While you can call functions from Steam like you would normally with the GodotSteam modules, they have to be added to your steam.gd script like this:

name = Steam.getPersonaName()
country = Steam.getIPCountry()
running = Steam.isSteamRunning()

func setAchievement(achieve: String) ->v void:
  Steam.setAchievement( achieve )

If you call Steamworks function outside of that script, however they must be prefaced with another Steam. like this:

name = Steam.Steam.getPersonaName()
country = Steam.Steam.getIPCountry()
running = Steam.Steam.isSteamRunning()

func setAchievement(achieve: String) -> void:
  Steam.Steam.setAchievement( achieve )

It may be less verbose and messy to write your functions in the steam.gd file then just reference them in other scripts.

From here you should have access to all of the Steamworks SDK functions and callbacks.

You should be able to read the Steamworks API documentation to see what all is available and cross-reference with GodotSteam's documentation.

Feel free to check out our tutorials if you want to learn some basics or just start tinkering!

Final Notes

GDNative on Windows has some odd glitch with setRichPresence() where sometimes the key is sent as the value; this bug does not exist in the Linux or OSX versions of GodotSteam GDNative nor in any versions of the GodotSteam module nor any versions of the GodotSteam GDExtension. In this case it is deemed unfixable.