Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions addons/netfox.extras/job-queue/network-job-queue.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
@tool
extends Node
class_name NetworkJobQueue

## Halt processing any items
@export var paused: bool = false

# An internal list to hold our queued jobs (as Dictionaries).
var queue: Array[Dictionary] = []

# A mapping of worker_name -> worker_node, so we can find the right worker.
var _workers := {}
var _id_counter := 0

func _get_configuration_warnings():
const MISSING_SYNCHRONIZER_ERROR := \
"NetworkJobQueue is not managed by a RollbackSynchronizer! Add it as a sibling node to fix this."
const INVALID_SYNCHRONIZER_CONFIG_ERROR := \
"RollbackSynchronizer configuration is invalid, it can't manage this job queue!" + \
"\nNote: You may need to reload this scene after fixing for this warning to disappear."
const MISSING_PROPERTY_ERROR := \
"Queue is not managed by RollbackSynchronizer! Add `queue` property to the synchronizer to fix this. " + \
"\nNote: You may need to reload this scene after fixing for this warning to disappear."

# Check if there's a rollback synchronizer
var rollback_synchronizer_node = get_parent().find_children("*", "RollbackSynchronizer", false).pop_front()
if not rollback_synchronizer_node:
return [MISSING_SYNCHRONIZER_ERROR]

var rollback_synchronizer := rollback_synchronizer_node as RollbackSynchronizer

# Check if its configuration is valid
# TODO: Expose this as a property?
if not rollback_synchronizer.root:
return [INVALID_SYNCHRONIZER_CONFIG_ERROR]

# Check if it manages our `queue` property
for state_property_path in rollback_synchronizer.state_properties:
var property = PropertyEntry.parse(rollback_synchronizer.root, state_property_path)
if property.node == self and property.property == "queue":
return []

return [MISSING_PROPERTY_ERROR]

func _get_uid() -> int:
_id_counter += 1
return _id_counter

func get_queue_position(uid: int) -> int:
for i in range(queue.size()):
var job: Dictionary = queue[i]
if job._uid == uid:
return i
return 0

## Call this method so workers can "register" themselves with the queue.
func register_worker(worker_name: String, worker_node: NetworkJobWorker) -> void:
if !worker_node.queue:
worker_node.queue = self
_workers[worker_name] = worker_node

## Add a dictionary job to the queue. For example: enqueue_job({"worker": "MyWorker", "payload": "Hello World!"})
func enqueue_job(job: Dictionary, worker: NetworkJobWorker = null) -> int:
var uid: int = _get_uid()
job[&"_uid"] = uid

if worker:
job[&"worker"] = worker.worker_name
worker.job_enqueued(job)

queue.append(job)
return uid

## Process the next jobs in the queue
func process_jobs():
if queue.size() == 0: return

for worker_name in _workers.keys():
var jobs: Array[Dictionary] = queue.filter(func(x): return x["worker"] == worker_name)
var worker: NetworkJobWorker = _workers[worker_name]
if worker.busy: continue

var next_job = jobs[0]
for job_index in range(queue.size()):
var job = queue[job_index]
if job._uid == next_job._uid:
queue.remove_at(job_index)
break

worker.process_job(next_job)

func _rollback_tick(delta: float, tick: int, is_fresh: bool) -> void:
if paused or queue.size() == 0: return

process_jobs()
37 changes: 37 additions & 0 deletions addons/netfox.extras/job-queue/network-job-worker.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
@tool
extends Node
class_name NetworkJobWorker

@export var worker_name: String = "Worker"
@export var queue: NetworkJobQueue: set = _set_queue

var busy: bool = false

func _get_configuration_warnings():
return [] if queue else ["This NetworkJobWorker should be registered with a queue."]

## Register the worker with the queue if the parent is a NetworkJobQueue.
func _notification(what: int):
if what == NOTIFICATION_ENTER_TREE:
if !queue and get_parent() is NetworkJobQueue:
queue = get_parent()

func _set_queue(value: NetworkJobQueue) -> void:
queue = value
register_with_queue()

## Call this method to register the worker with the queue.
func register_with_queue() -> void:
if queue:
queue.register_worker(worker_name, self)

## This method is called by the NetworkJobQueue when a job is enqueued.
func job_enqueued(job: Dictionary) -> void:
pass

## This method is called by the NetworkJobQueue when a job is ready to be processed. You should extend this node and override this method in your own worker.
func process_job(job: Dictionary) -> void:
busy = true
# Do something with the job here
busy = false
pass

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[remap]

importer="scene"
importer_version=1
type="PackedScene"
uid="uid://cuv6otw6ngypp"
path="res://.godot/imported/Block_Brick.gltf-a7288c40b5964ef2c2e64faf38870c59.scn"

[deps]

source_file="res://examples/multiplayer-job-queue/models/Quaternius Cube World Kit/Block_Brick.gltf"
dest_files=["res://.godot/imported/Block_Brick.gltf-a7288c40b5964ef2c2e64faf38870c59.scn"]

[params]

nodes/root_type="Node3D"
nodes/root_name="Scene Root"
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={
"nodes": {
"PATH:Block_Brick2": {
"generate/physics": true,
"physics/shape_type": 3
}
}
}
gltf/embedded_image_handling=1
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[remap]

importer="texture"
type="CompressedTexture2D"
uid="uid://lakdf2352wpm"
path.s3tc="res://.godot/imported/Block_Brick_Atlas.png-d0247e9df7f4ef117d2cc0231d217068.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
generator_parameters={}

[deps]

source_file="res://examples/multiplayer-job-queue/models/Quaternius Cube World Kit/Block_Brick_Atlas.png"
dest_files=["res://.godot/imported/Block_Brick_Atlas.png-d0247e9df7f4ef117d2cc0231d217068.s3tc.ctex"]

[params]

compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
{
"asset" : {
"generator" : "Khronos glTF Blender I/O v1.7.33",
"version" : "2.0"
},
"scene" : 0,
"scenes" : [
{
"name" : "Scene",
"nodes" : [
0
]
}
],
"nodes" : [
{
"mesh" : 0,
"name" : "Block_Grass",
"rotation" : [
0,
-0.7071068286895752,
0,
0.7071068286895752
]
}
],
"materials" : [
{
"doubleSided" : true,
"name" : "Atlas",
"pbrMetallicRoughness" : {
"baseColorTexture" : {
"index" : 0
},
"metallicFactor" : 0,
"roughnessFactor" : 0.5
}
}
],
"meshes" : [
{
"name" : "Cube.375",
"primitives" : [
{
"attributes" : {
"POSITION" : 0,
"NORMAL" : 1,
"TEXCOORD_0" : 2
},
"indices" : 3,
"material" : 0
}
]
}
],
"textures" : [
{
"sampler" : 0,
"source" : 0
}
],
"images" : [
{
"bufferView" : 4,
"mimeType" : "image/png",
"name" : "Atlas"
}
],
"accessors" : [
{
"bufferView" : 0,
"componentType" : 5126,
"count" : 72,
"max" : [
1,
1,
1
],
"min" : [
-1,
-1,
-1
],
"type" : "VEC3"
},
{
"bufferView" : 1,
"componentType" : 5126,
"count" : 72,
"type" : "VEC3"
},
{
"bufferView" : 2,
"componentType" : 5126,
"count" : 72,
"type" : "VEC2"
},
{
"bufferView" : 3,
"componentType" : 5123,
"count" : 108,
"type" : "SCALAR"
}
],
"bufferViews" : [
{
"buffer" : 0,
"byteLength" : 864,
"byteOffset" : 0
},
{
"buffer" : 0,
"byteLength" : 864,
"byteOffset" : 864
},
{
"buffer" : 0,
"byteLength" : 576,
"byteOffset" : 1728
},
{
"buffer" : 0,
"byteLength" : 216,
"byteOffset" : 2304
},
{
"buffer" : 0,
"byteLength" : 3567,
"byteOffset" : 2520
}
],
"samplers" : [
{
"magFilter" : 9728,
"minFilter" : 9984
}
],
"buffers" : [
{
"byteLength" : 6088,
"uri" : "data:application/octet-stream;base64,AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAvwAAAL8AAIA/AACAvwAAAL8AAIA/AACAvwAAAL8AAIA/AACAvwAAAL8AAIA/AACAvwAAAAAAAIA/AACAvwAAAAAAAIA/AACAvwAAAAAAAIA/AACAvwAAAAAAAIA/AACAvwAAAD8AAIA/AACAvwAAAD8AAIA/AACAvwAAAD8AAIA/AACAvwAAAD8AAIA/AACAvwAAAD8AAIC/AACAvwAAAD8AAIC/AACAvwAAAD8AAIC/AACAvwAAAD8AAIC/AACAvwAAAAAAAIC/AACAvwAAAAAAAIC/AACAvwAAAAAAAIC/AACAvwAAAAAAAIC/AACAvwAAAL8AAIC/AACAvwAAAL8AAIC/AACAvwAAAL8AAIC/AACAvwAAAL8AAIC/AACAPwAAAD8AAIC/AACAPwAAAD8AAIC/AACAPwAAAD8AAIC/AACAPwAAAD8AAIC/AACAPwAAAAAAAIC/AACAPwAAAAAAAIC/AACAPwAAAAAAAIC/AACAPwAAAAAAAIC/AACAPwAAAL8AAIC/AACAPwAAAL8AAIC/AACAPwAAAL8AAIC/AACAPwAAAL8AAIC/AACAPwAAAD8AAIA/AACAPwAAAD8AAIA/AACAPwAAAD8AAIA/AACAPwAAAD8AAIA/AACAPwAAAAAAAIA/AACAPwAAAAAAAIA/AACAPwAAAAAAAIA/AACAPwAAAAAAAIA/AACAPwAAAL8AAIA/AACAPwAAAL8AAIA/AACAPwAAAL8AAIA/AACAPwAAAL8AAIA/AACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/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VDIwOjUzOjMwLTAzOjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgcGhvdG9zaG9wOklDQ1Byb2ZpbGU9Iiogd3NSR0IiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODQ0YTAzYjktY2FjYy04ZjRlLWIwZmMtMzRlZDcxMTIxNDFjIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjQ4Nzk3NDZkLWY3NzQtODg0NC1hZjRiLWRiNDcxOTVhYzQ5MCIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjQ4Nzk3NDZkLWY3NzQtODg0NC1hZjRiLWRiNDcxOTVhYzQ5MCI+IDx4bXBNTTpIaXN0b3J5PiA8cmRmOlNlcT4gPHJkZjpsaSBzdEV2dDphY3Rpb249ImNyZWF0ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6NDg3OTc0NmQtZjc3NC04ODQ0LWFmNGItZGI0NzE5NWFjNDkwIiBzdEV2dDp3aGVuPSIyMDIzLTA3LTMwVDE5OjUyOjI2LTAzOjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjIyZmRhZDQ2LTEzYWUtYTg0Yy04MTAyLWRjZDdiYzBhMTIzOCIgc3RFdnQ6d2hlbj0iMjAyMy0wNy0zMVQyMDoxOToyMi0wMzowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTggKFdpbmRvd3MpIiBzdEV2dDpjaGFuZ2VkPSIvIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo4NDRhMDNiOS1jYWNjLThmNGUtYjBmYy0zNGVkNzExMjE0MWMiIHN0RXZ0OndoZW49IjIwMjMtMDctMzFUMjA6NTM6MzAtMDM6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6pks37AAACHElEQVRIidWWW0jTURyAv81hW5sRstJ5qVxMpKyNZahd6IIPEcsYFVaQMLpBK5cEFSNDMYqgeqgelIkVZNhyiLoe7KX2YjIqFErLrYwWq4iZczboxnoIjtBLjPwPdp6+H+dwvvO7PJyMw3VHf8SjXS22zByzbToQrtjjPfv1zWTJmYYmQ/nTU0Rz1/k02ryuhmLjktwd+baiMrlGm+duVm6yNkbWH5gXHt53XFUy5bBoVJnGnFuXawqePXecr52IK93NylZPRJZIJJByySW9/W9B4kRk1gWy1h7t9MMK/TLdYk1fyPUhsHJbkS57MPHA172oxuNpc7WMNJ37L4HT6Vy7IDgajPwKv61qDw7HyH5Sst36crYyUOj1er/XO2Gaunp9HDDPh8JZux2QfIoUQzc3z0TKrQL3jk4K3tV5TXB/2X7Bgx1X/ilI7ZimpUBx8cYnERhNQ4LVA68E39t9TLA2nJGUIP1LJH0Pij++F8GWSpvgvqGZHlTKOwT749akBOlfIul78LhwhQg+u+8L/h6fOWSRzxXsT1KQ/iWSXJD+3xZZfe1GoNSgAzofvQNWl28ADAYDcOd2G7C01AyUm8yAKRQCDvb2Aqt0c4AXgTFAlV8MfIl+A1zV1cBJX39KMrjksACvR8aAhWolMBDLEtt/XmS328XbD3V1A0fq64DxC3cB9fIAULXzJ3C6vQBYkxUDGruHU5JB2k/Rb2W5qvX1uRw3AAAAAElFTkSuQmCCAA=="
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[remap]

importer="scene"
importer_version=1
type="PackedScene"
uid="uid://cflboecqww4q5"
path="res://.godot/imported/Block_Grass.gltf-0c80bf6343b483203e0dd4861fffea5b.scn"

[deps]

source_file="res://examples/multiplayer-job-queue/models/Quaternius Cube World Kit/Block_Grass.gltf"
dest_files=["res://.godot/imported/Block_Grass.gltf-0c80bf6343b483203e0dd4861fffea5b.scn"]

[params]

nodes/root_type="Node3D"
nodes/root_name="Scene Root"
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
import_script/path=""
_subresources={
"nodes": {
"PATH:Block_Grass2": {
"generate/physics": true,
"physics/shape_type": 3
}
}
}
gltf/embedded_image_handling=1
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading