This is a small library providing basic godot multiplayer replication from kotlin for kotlin. Written for godot kotlin jvm projects.
Note: this library is pretty barebones, and inefficient but should be quite easy to use. There is no lag compensation or similar present atm.
Add the library as a dependency to your project. As it is published to maven central, you should also make sure that you have maven central set up as a repository:
repositories {
mavenCentral()
}
dependencies {
implementation("ch.hippmann.godot:replication:<version>")
}
Its required that you add the following autoload singletons:
- From ch.hippmann.godot:utilities add the DispatcherSingleton
- From this library, add the RemoteListenerReadyRedirector
If you want to have nodes replicated automatically if you add them to a node, implement the Replicated
interface with the Replicator
delegate and add your class to a node:
@RegisterClass
class ExampleReplicator: Node3D(), Replicated by Replicator() {
@RegisterFunction
override fun _enterTree() {
// this line is needed to setup the replication! Needs to happen before _ready
initReplication()
}
}
Nodes of type Replicated
expose an editor property managedScenes
. This you need to fill with all the packed scenes you want to have replicated.
Once such a scene is added as a direct child of Replicated
on the network authority it gets also spawned on all other peers.
So keep in mind to fill this property in the editor and properly define your network authorities for the Replicated
nodes!
If the root node of a managed scene implements Synchronized
, data you defined as syncOnSpawn
in your syncConfig
gets synced automatically on spawn of the child scene on a peer. More on that later.
If you want certain properties to be synchronized across all peers, implement Synchronized
with the delegate Synchronizer
.
You can configure what is to be synchronized and when through overriding of the property syncConfig
:
@RegisterClass
class Player: CharacterBody3D(), Synchronized by Synchronizer() {
override val syncConfig: SyncConfigs = syncConfig {
property(::team)
property(::speed)
property(::jumpVelocity)
property(::velocity) {
shouldSendUpdate = { current, last -> !last.isEqualApprox(current) }
}
// config example:
property(::globalTransform) {
// sync every tick milliseconds
tick = 16 // default 16ms
// send reliable or unreliable (tcp or udp)
syncMethod = SyncConfig.SyncMethod.UNRELIABLE // default: SyncConfig.SyncMethod.RELIABLE
// sync property on spawn
syncOnSpawn = true // defaut: true
// sync property on tick
syncOnTick = true // default: true
// whether to send an update
shouldSendUpdate = { current, last -> !last.isEqualApprox(current) } // default: { current, last -> current != last }
}
}
@Export
@RegisterProperty
var speed: Double = 500.0
@Export
@RegisterProperty
var jumpVelocity: Double = 5.0
var team: Int = 0
@RegisterFunction
override fun _enterTree() {
// needed to init the synchronisation. Needs to happen before _ready
// after this call, no changes to the `syncConfig` can be made!
initSynchronization()
}
@RegisterFunction
override fun _process(delta: Double) {
// call periodically. If this gets called less than tick, the next time this gets called, multiple sync events might be sent at the same time
// sync calls are queued on every tick, but are sent when this function is called. So it is advised that this function gets called more frequently than your lowest tick config
// this calls godot's rpc functions internally. So you as the caller, need to make sure that this call happens at a time when godot can send rpc calls. _progress is a good candidate for this.
performSynchronization()
}
}
Important: For Synchronized
you also need to make sure to properly set up the network authority before adding it to the tree! At the moment, the authority cannot be changed afterward!
Some notes regarding syncOnSpawn:
syncOnSpawn
only has an effect if theSynchronized
node is a direct child ofReplicated
! Otherwise, it will only sync upon first tick.- Sync on spawn takes the initial spawn data from the
syncConfig
after it has been added to the tree as a child ofReplicated
. So in order to make sure that the desired data is set, set all required properties before the next tick.