Fresh start: replace with naxIO/netfox-cs-sample foundation

Complete replacement of the tactical-shooter project with the
netfox-cs-sample (MIT) — a CS 1.6 inspired multiplayer FPS built
with Godot 4 and netfox.

## What's new
- Full CS-style gameplay: teams (T/CT), rounds, economy, buy menu
- 6 weapons: Knife, Glock, USP, AK-47, M4A1, AWP
- Bomb plant/defuse with 2 bombsites
- Flashbang & smoke grenades
- Proper netfox rollback netcode at 64 tick
- Network popup UI for host/join
- HUD, crosshair, round timer, scoreboard
- All netfox singletons registered as autoloads (works in exported builds)

## Architecture
- Listen-server (host from client, no dedicated server binary)
- Multiplayer-fps game lives at examples/multiplayer-fps/
- Netfox addons registered as autoloads for exported build compat
- Godot 4.7 with Forward+ renderer

## Removed
- Old headless-server architecture (client_main, server_main, player.gd, etc.)
- Custom netfox bootstrap with ENet fallback
- Old ChaffGames FPS template (2,420 lines, 844 KB)
- SimulationServer GDExtension stub
- Godot-jolt physics (netfox sample uses default Godot physics)
- Duplicate weapon_data.gd, anti_cheat.gd, round_manager.gd, etc.
- Server browser API Python venv (87 MB)
- test_range map and modular assets

## Preserved
- Git history
- Server config at config/default_server_config.cfg
- Windows export preset
- Build directory (gitignored)

Co-authored-by: naxIO <naxIO@users.noreply.github.com>
This commit is contained in:
2026-07-02 20:55:20 -04:00
parent ce39b237c3
commit b0c83af092
4416 changed files with 57418 additions and 902676 deletions
@@ -0,0 +1,21 @@
extends RefCounted
class_name NetworkSchemaSerializer
## Base class for serializers, to use with [NetworkSchemas]
##
## Each serializer must be able to encode and decode values passed to it.
## Data is stored in [StreamPeerBuffer] objects.
## [br][br]
## To implement a custom serializer, extend this class and pass an instance of
## it in place of a NetworkSchemaSerializer, for example to [method
## RollbackSynchronizer.set_schema].
##
## @tutorial(Network schemas): https://foxssake.github.io/netfox/latest/netfox/guides/network-schemas/
## Encode [param value] into [param buffer]
func encode(value: Variant, buffer: StreamPeerBuffer) -> void:
pass
## Decode a value from [param buffer] and return it
func decode(buffer: StreamPeerBuffer) -> Variant:
return null
@@ -0,0 +1 @@
uid://btmpightc21cy
+36
View File
@@ -0,0 +1,36 @@
extends RefCounted
class_name _NetworkSchema
var _serializers := {} # subject to (property to NetworkSchemaSerializer)
var _fallback: NetworkSchemaSerializer
func _init(fallback: NetworkSchemaSerializer = NetworkSchemas.variant()) -> void:
_fallback = fallback
func add(subject: Object, property: NodePath, serializer: NetworkSchemaSerializer) -> void:
if not _serializers.has(subject):
_serializers[subject] = { property: serializer }
else:
_serializers[subject][property] = serializer
func erase(subject: Object, property: NodePath) -> void:
if not _serializers.has(subject):
return
var subject_schema := _serializers[subject] as Dictionary
subject_schema.erase(property)
if subject_schema.is_empty():
_serializers.erase(subject)
func erase_subject(subject: Object) -> void:
_serializers.erase(subject)
func encode(subject: Object, property: NodePath, value: Variant, buffer: StreamPeerBuffer) -> void:
_get_serializer(subject, property).encode(value, buffer)
func decode(subject: Object, property: NodePath, buffer: StreamPeerBuffer) -> Variant:
return _get_serializer(subject, property).decode(buffer)
func _get_serializer(subject: Object, property: NodePath) -> NetworkSchemaSerializer:
return _serializers.get(subject, {}).get(property, _fallback)
@@ -0,0 +1 @@
uid://cmqrteshb5sop
+882
View File
@@ -0,0 +1,882 @@
extends Object
class_name NetworkSchemas
## Provides various schema serializers
##
## While some method names are abbreviated, they use a few naming schemes. For
## example: [br][br]
## [method uint16] - unsigned integer, 16 bits[br]
## [method vec2t] - [Vector2], component of specified [i]type[/i][br]
## [method vec3f32] - [Vector3], each component as a [method float32][br]
## [br]
## To handle collections, see [method array_of] and [method dictionary].
##
## @tutorial(Network schemas): https://foxssake.github.io/netfox/latest/netfox/guides/network-schemas/
## Serialize any data type supported by [method @GlobalScope.var_to_bytes].
## [br][br]
## Final size depends on the value.
static func variant() -> NetworkSchemaSerializer:
return _VariantSerializer.new()
## Serialize strings in UTF-8 encoding.
## [br][br]
## Final size depends on the string, the string itself is zero-terminated.
static func string() -> NetworkSchemaSerializer:
return _StringSerializer.new()
## Serialize booleans as 8 bits.
## [br][br]
## Final size is 1 byte.
static func bool8() -> NetworkSchemaSerializer:
return _BoolSerializer.new()
## Serialize unsigned integers as 8 bits.
## [br][br]
## Final size is 1 byte.
static func uint8() -> NetworkSchemaSerializer:
return _Uint8Serializer.new()
## Serialize unsigned integers as 16 bits.
## [br][br]
## Final size is 2 bytes.
static func uint16() -> NetworkSchemaSerializer:
return _Uint16Serializer.new()
## Serialize unsigned integers as 32 bits.
## [br][br]
## Final size is 4 bytes.
static func uint32() -> NetworkSchemaSerializer:
return _Uint32Serializer.new()
## Serialize unsigned integers as 64 bits.
## [br][br]
## Final size is 8 bytes.
static func uint64() -> NetworkSchemaSerializer:
return _Uint64Serializer.new()
## Serialize an unsigned integer as a variable amount of bytes.
## [br][br]
## Each byte contains 7 bits of data. The 8th bit indicates whether there are
## more bytes left. Thus, small numbers fitting into 7 bits will be encoded as
## a single byte, while larger numbers take more space as they increase.
## [br][br]
## Final size is 1 byte for every 7 bits of numeric data.
static func varuint() -> NetworkSchemaSerializer:
return _VaruintSerializer.instance
static func _varbits() -> NetworkSchemaSerializer:
return _VariableBitsetSerializer.instance
## Serialize signed integers as 8 bits.
## [br][br]
## Final size is 1 byte.
static func int8() -> NetworkSchemaSerializer:
return _Int8Serializer.new()
## Serialize signed integers as 16 bits.
## [br][br]
## Final size is 2 bytes.
static func int16() -> NetworkSchemaSerializer:
return _Int16Serializer.new()
## Serialize signed integers as 32 bits.
## [br][br]
## Final size is 4 bytes.
static func int32() -> NetworkSchemaSerializer:
return _Int32Serializer.new()
## Serialize signed integers as 64 bits.
## [br][br]
## Final size is 8 bytes.
static func int64() -> NetworkSchemaSerializer:
return _Int64Serializer.new()
## Serialize floats in half-precision, as 16 bits.
## [br][br]
## This is only supported in Godot 4.4 and up, earlier versions fall back to
## [method float32].
## [br][br]
## Final size is 2 bytes, 4 if using fallback.
static func float16() -> NetworkSchemaSerializer:
return _Float16Serializer.new()
## Serialize floats in single-precision, as 32 bits.
## [br][br]
## Final size is 4 bytes.
static func float32() -> NetworkSchemaSerializer:
return _Float32Serializer.new()
## Serialize floats in double-precision, as 64 bits.
## [br][br]
## Final size is 8 bytes.
static func float64() -> NetworkSchemaSerializer:
return _Float64Serializer.new()
## Serialize signed fractions in the [code][-1.0, +1.0][/code] range as 8 bits.
## [br][br]
## Final size is 1 byte.
static func sfrac8() -> NetworkSchemaSerializer:
return _QuantizingSerializer.new(uint8(), -1., 1., 0, 0xFF)
## Serialize signed fractions in the [code][-1.0, +1.0][/code] range as 16 bits.
## [br][br]
## Final size is 2 bytes.
static func sfrac16() -> NetworkSchemaSerializer:
return _QuantizingSerializer.new(uint16(), -1., 1., 0, 0xFFFF)
## Serialize signed fractions in the [code][-1.0, +1.0][/code] range as 32 bits.
## [br][br]
## Final size is 4 bytes.
static func sfrac32() -> NetworkSchemaSerializer:
return _QuantizingSerializer.new(uint32(), -1., 1., 0, 0xFFFFFFFF)
## Serialize signed fractions in the [code][0.0, 1.0][/code] range as 8 bits.
## [br][br]
## Final size is 1 byte.
static func ufrac8() -> NetworkSchemaSerializer:
return _QuantizingSerializer.new(uint8(), 0., 1., 0, 0xFF)
## Serialize signed fractions in the [code][0.0, 1.0][/code] range as 16 bits.
## [br][br]
## Final size is 2 bytes.
static func ufrac16() -> NetworkSchemaSerializer:
return _QuantizingSerializer.new(uint16(), 0., 1., 0, 0xFFFF)
## Serialize signed fractions in the [code][0.0, 1.0][/code] range as 32 bits.
## [br][br]
## Final size is 4 bytes.
static func ufrac32() -> NetworkSchemaSerializer:
return _QuantizingSerializer.new(uint32(), 0., 1., 0, 0xFFFFFFFF)
## Serialize degrees as 8 bits. The value will always decode to the
## [code][0.0, 360.0)[/code] range.
## [br][br]
## Final size is 1 byte.
static func degrees8() -> NetworkSchemaSerializer:
return _ModuloSerializer.new(uint8(), 360., 0xFF)
## Serialize degrees as 16 bits. The value will always decode to the
## [code][0.0, 360.0)[/code] range.
## [br][br]
## Final size is 2 bytes.
static func degrees16() -> NetworkSchemaSerializer:
return _ModuloSerializer.new(uint16(), 360., 0xFFFF)
## Serialize degrees as 32 bits. The value will always decode to the
## [code][0.0, 360.0)[/code] range.
## [br][br]
## Final size is 4 bytes.
static func degrees32() -> NetworkSchemaSerializer:
return _ModuloSerializer.new(uint32(), 360., 0xFFFFFFFF)
## Serialize radians as 8 bits. The value will always decode to the
## [code][0.0, TAU)[/code] range.
## [br][br]
## Final size is 1 byte.
static func radians8() -> NetworkSchemaSerializer:
return _ModuloSerializer.new(uint8(), TAU, 0xFF)
## Serialize radians as 16 bits. The value will always decode to the
## [code][0.0, TAU)[/code] range.
## [br][br]
## Final size is 2 bytes.
static func radians16() -> NetworkSchemaSerializer:
return _ModuloSerializer.new(uint16(), TAU, 0xFFFF)
## Serialize radians as 32 bits. The value will always decode to the
## [code][0.0, TAU)[/code] range.
## [br][br]
## Final size is 4 bytes.
static func radians32() -> NetworkSchemaSerializer:
return _ModuloSerializer.new(uint32(), TAU, 0xFFFFFFFF)
## Serialize [Vector2] objects, using [param component_serializer] to
## serialize each component of the vector.
## [br][br]
## Serializes 2 components, size depends on the [param component_serializer].
static func vec2t(component_serializer: NetworkSchemaSerializer) -> NetworkSchemaSerializer:
return _GenericVec2Serializer.new(component_serializer)
## Serialize [Vector2] objects, with each component being a half-precision
## float.
## [br][br]
## This is only supported in Godot 4.4 and up. Earlier versions fall back to
## [method vec2f32].
## [br][br]
## Final size is 4 bytes, 8 if using fallback.
static func vec2f16() -> NetworkSchemaSerializer:
return vec2t(float16())
## Serialize [Vector2] objects, with each component being a single-precision
## float.
## [br][br]
## Final size is 8 bytes.
static func vec2f32() -> NetworkSchemaSerializer:
return vec2t(float32())
## Serialize [Vector2] objects, with each component being a double-precision
## float.
## [br][br]
## Final size is 16 bytes.
static func vec2f64() -> NetworkSchemaSerializer:
return vec2t(float64())
## Serialize [Vector3] objects, using [param component_serializer] to
## serialize each component of the vector.
## [br][br]
## Serializes 3 components, size depends on the [param component_serializer].
static func vec3t(component_serializer: NetworkSchemaSerializer) -> NetworkSchemaSerializer:
return _GenericVec3Serializer.new(component_serializer)
## Serialize [Vector3] objects, with each component being a half-precision
## float.
## [br][br]
## This is only supported in Godot 4.4 and up. Earlier versions fall back to
## [method vec3f32].
## [br][br]
## Final size is 6 bytes, 12 if using fallback.
static func vec3f16() -> NetworkSchemaSerializer:
return vec3t(float16())
## Serialize [Vector3] objects, with each component being a double-precision
## float.
## [br][br]
## Final size is 12 bytes.
static func vec3f32() -> NetworkSchemaSerializer:
return vec3t(float32())
## Serialize [Vector3] objects, with each component being a double-precision
## float.
## [br][br]
## Final size is 24 bytes.
static func vec3f64() -> NetworkSchemaSerializer:
return vec3t(float64())
## Serialize [Vector4] objects, using [param component_serializer] to
## serialize each component of the vector.
## [br][br]
## Serializes 4 components, size depends on the [param component_serializer].
static func vec4t(component_serializer: NetworkSchemaSerializer) -> NetworkSchemaSerializer:
return _GenericVec4Serializer.new(component_serializer)
## Serialize [Vector4] objects, with each component being a half-precision
## float.
## [br][br]
## This is only supported in Godot 4.4 and up. Earlier versions fall back to
## [method vec4f32].
## [br][br]
## Final size is 8 bytes, 16 if using fallback.
static func vec4f16() -> NetworkSchemaSerializer:
return vec4t(float16())
## Serialize [Vector4] objects, with each component being a double-precision
## float.
## [br][br]
## Final size is 16 bytes.
static func vec4f32() -> NetworkSchemaSerializer:
return vec4t(float32())
## Serialize [Vector4] objects, with each component being a double-precision
## float.
## [br][br]
## Final size is 32 bytes.
static func vec4f64() -> NetworkSchemaSerializer:
return vec4t(float64())
# Normals
## Serialize normalized [Vector2] objects, using [param component_serializer] to
## serialize each component of the vector.
## [br][br]
## Serializes 1 component, size depends on the [param component_serializer].
static func normal2t(component_serializer: NetworkSchemaSerializer) -> NetworkSchemaSerializer:
return _Normal2Serializer.new(component_serializer)
## Serialize normalized [Vector2] objects, with each component being a
## half-precision float.
## [br][br]
## This is only supported in Godot 4.4 and up. Earlier versions fall back to
## [method normal2f32].
## [br][br]
## Final size is 2 bytes, 4 if using fallback.
static func normal2f16() -> NetworkSchemaSerializer:
return normal2t(float16())
## Serialize normalized [Vector2] objects, with each component being a
## single-precision float.
## [br][br]
## Final size is 4 bytes.
static func normal2f32() -> NetworkSchemaSerializer:
return normal2t(float32())
## Serialize normalized [Vector2] objects, with each component being a
## double-precision float.
## [br][br]
## Final size is 8 bytes.
static func normal2f64() -> NetworkSchemaSerializer:
return normal2t(float64())
## Serialize normalized [Vector3] objects, using [param component_serializer] to
## serialize each component of the vector.
## [br][br]
## Serializes 2 components, size depends on the [param component_serializer].
static func normal3t(component_serializer: NetworkSchemaSerializer) -> NetworkSchemaSerializer:
return _Normal3Serializer.new(component_serializer)
## Serialize normalized [Vector3] objects, with each component being a
## half-precision float.
## [br][br]
## This is only supported in Godot 4.4 and up. Earlier versions fall back to
## [method normal3f32].
## [br][br]
## Final size is 4 bytes, 8 if using fallback.
static func normal3f16() -> NetworkSchemaSerializer:
return normal3t(float16())
## Serialize normalized [Vector3] objects, with each component being a
## single-precision float.
## [br][br]
## Final size is 8 bytes.
static func normal3f32() -> NetworkSchemaSerializer:
return normal3t(float32())
## Serialize normalized [Vector3] objects, with each component being a
## double-precision float.
## [br][br]
## Final size is 16 bytes.
static func normal3f64() -> NetworkSchemaSerializer:
return normal3t(float64())
# Quaternion
## Serialize [Quaternion] objects, using [param component_serializer] to
## serialize each component of the quaternion.
## [br][br]
## Serializes 4 components, size depends on the [param component_serializer].
static func quatt(component_serializer: NetworkSchemaSerializer) -> NetworkSchemaSerializer:
return _GenericQuaternionSerializer.new(component_serializer)
## Serialize [Quaternion] objects, with each component being a half-precision
## float.
## [br][br]
## This is only supported in Godot 4.4 and up. Earlier versions fall back to
## [method quat32f].
## [br][br]
## Final size is 8 bytes, 16 if using fallback.
static func quatf16() -> NetworkSchemaSerializer:
return quatt(float16())
## Serialize [Quaternion] objects, with each component being a single-precision
## float.
## [br][br]
## Final size is 16 bytes.
static func quatf32() -> NetworkSchemaSerializer:
return quatt(float32())
## Serialize [Quaternion] objects, with each component being a double-precision
## float.
## [br][br]
## Final size is 32 bytes.
static func quatf64() -> NetworkSchemaSerializer:
return quatt(float64())
# Transforms
## Serialize [Transform2D] objects, using [param component_serializer] to
## serialize each component of the transform.
## [br][br]
## Serializes a 2x3 matrix in 6 components, final size depends on [param
## component_serializer].
static func transform2t(component_serializer: NetworkSchemaSerializer) -> NetworkSchemaSerializer:
return _GenericTransform2DSerializer.new(component_serializer)
## Serialize [Transform2D] objects, with each component being a half-precision
## float.
## [br][br]
## This is only supported in Godot 4.4 and up. Earlier versions fall back to
## [method transform2f32].
## [br][br]
## Final size is 12 bytes, 24 if using fallback.
static func transform2f16() -> NetworkSchemaSerializer:
return transform2t(float16())
## Serialize [Transform2D] objects, with each component being a single-precision
## float.
## [br][br]
## Final size is 24 bytes.
static func transform2f32() -> NetworkSchemaSerializer:
return transform2t(float32())
## Serialize [Transform2D] objects, with each component being a double-precision
## float.
## [br][br]
## Final size is 48 bytes.
static func transform2f64() -> NetworkSchemaSerializer:
return transform2t(float64())
## Serialize [Transform3D] objects, using [param component_serializer] to
## serialize each component of the transform.
## [br][br]
## Serializes a 3x4 matrix in 12 components, final size depends on [param
## component_serializer].
static func transform3t(component_serializer: NetworkSchemaSerializer) -> NetworkSchemaSerializer:
return _GenericTransform3DSerializer.new(component_serializer)
## Serialize [Transform3D] objects, with each component being a half-precision
## float.
## [br][br]
## This is only supported in Godot 4.4 and up. Earlier versions fall back to
## [method transform3f32].
## [br][br]
## Final size is 24 bytes, 48 if using fallback.
static func transform3f16() -> NetworkSchemaSerializer:
return transform3t(float16())
## Serialize [Transform3D] objects, with each component being a single-precision
## float.
## [br][br]
## Final size is 48 bytes.
static func transform3f32() -> NetworkSchemaSerializer:
return transform3t(float32())
## Serialize [Transform2D] objects, with each component being a double-precision
## float.
## [br][br]
## Final size is 96 bytes.
static func transform3f64() -> NetworkSchemaSerializer:
return transform3t(float64())
# Collections
## Serialize homogenoeous arrays, using [param item_serializer] to
## serialize each item, and [param size_serializer] to serialize the array's
## size.
## [br][br]
## To serialize heterogenoeous arrays, use [method variant] as the item
## serializer.
## [br][br]
## Final size is [code]sizeof(size_serializer) + array.size() * sizeof(item_serializer)[/code]
static func array_of(item_serializer: NetworkSchemaSerializer = variant(), size_serializer: NetworkSchemaSerializer = uint16()) -> NetworkSchemaSerializer:
return _ArraySerializer.new(item_serializer, size_serializer)
## Serialize homogenoeous dictionaries, using [param key_serialize] and
## [param value_serializer] to serialize key-value pairs, and
## [param size_serializer] to serialize the number of entries.
## [br][br]
## If either the keys or values are not homogenoeous, use [method variant].
## [br][br]
## Final size is [code]sizeof(size_serializer) + dictionary.size() * (sizeof(key_serializer) + sizeof(value_serializer))[/code]
static func dictionary(key_serializer: NetworkSchemaSerializer = variant(),
value_serializer: NetworkSchemaSerializer = variant(),
size_serializer: NetworkSchemaSerializer = uint16()) -> NetworkSchemaSerializer:
return _DictionarySerializer.new(key_serializer, value_serializer, size_serializer)
# Serializes [_NetworkIdentityReference] objects
static func _netref() -> NetworkSchemaSerializer:
return _NetworkIdentityReferenceSerializer.new()
# Serializer classes
class _VariantSerializer extends NetworkSchemaSerializer:
func encode(v: Variant, b: StreamPeerBuffer) -> void:
b.put_var(v, false)
func decode(b: StreamPeerBuffer) -> Variant:
return b.get_var(false)
class _StringSerializer extends NetworkSchemaSerializer:
func encode(v: Variant, b: StreamPeerBuffer) -> void:
b.put_utf8_string(str(v))
func decode(b: StreamPeerBuffer) -> Variant:
return b.get_utf8_string()
class _BoolSerializer extends NetworkSchemaSerializer:
func encode(v: Variant, b: StreamPeerBuffer) -> void:
b.put_u8(1 if v else 0)
func decode(b: StreamPeerBuffer) -> Variant:
return b.get_u8() > 0
class _Uint8Serializer extends NetworkSchemaSerializer:
func encode(v: Variant, b: StreamPeerBuffer) -> void: b.put_u8(v)
func decode(b: StreamPeerBuffer) -> Variant: return b.get_u8()
class _Uint16Serializer extends NetworkSchemaSerializer:
func encode(v: Variant, b: StreamPeerBuffer) -> void: b.put_u16(v)
func decode(b: StreamPeerBuffer) -> Variant: return b.get_u16()
class _Uint32Serializer extends NetworkSchemaSerializer:
func encode(v: Variant, b: StreamPeerBuffer) -> void: b.put_u32(v)
func decode(b: StreamPeerBuffer) -> Variant: return b.get_u32()
class _Uint64Serializer extends NetworkSchemaSerializer:
func encode(v: Variant, b: StreamPeerBuffer) -> void: b.put_u64(v)
func decode(b: StreamPeerBuffer) -> Variant: return b.get_u64()
class _Int8Serializer extends NetworkSchemaSerializer:
func encode(v: Variant, b: StreamPeerBuffer) -> void: b.put_8(v)
func decode(b: StreamPeerBuffer) -> Variant: return b.get_8()
class _Int16Serializer extends NetworkSchemaSerializer:
func encode(v: Variant, b: StreamPeerBuffer) -> void: b.put_16(v)
func decode(b: StreamPeerBuffer) -> Variant: return b.get_16()
class _Int32Serializer extends NetworkSchemaSerializer:
func encode(v: Variant, b: StreamPeerBuffer) -> void: b.put_32(v)
func decode(b: StreamPeerBuffer) -> Variant: return b.get_32()
class _Int64Serializer extends NetworkSchemaSerializer:
func encode(v: Variant, b: StreamPeerBuffer) -> void: b.put_64(v)
func decode(b: StreamPeerBuffer) -> Variant: return b.get_64()
class _VaruintSerializer extends NetworkSchemaSerializer:
static var instance := _VaruintSerializer.new()
func encode(v: Variant, b: StreamPeerBuffer) -> void:
var value := v as int
for __ in 8: # Bounded while loop
var nominator := value & 0b0111_1111 # Grab the lowest 7 bits
var continuator := value > 0b0111_1111 # Continue if more bits
var cont_bit := 0b1000_0000 if continuator else 0
var byte := nominator | cont_bit # Combine into 1 byte
value = value >> 7 # Discard lower 7 bits
b.put_u8(byte) # Save byte
# Stop if no more bytes to write
if not continuator:
break
func decode(b: StreamPeerBuffer) -> Variant:
var value := 0
for i in 8:
var byte := b.get_u8()
var nominator := byte & 0b0111_1111
var continuator := (byte & 0b1000_0000) != 0
value += nominator << (i * 7)
if not continuator:
break
return value
class _VariableBitsetSerializer extends NetworkSchemaSerializer:
static var instance := _VariableBitsetSerializer.new()
func encode(v: Variant, b: StreamPeerBuffer) -> void:
var bitset := v as _Bitset
if bitset.is_empty():
b.put_u8(0)
return
for i in range(0, bitset.bit_count(), 7):
var byte := 0
# Set bits
if bitset.bit_count() > i + 0 and bitset.get_bit(i + 0): byte |= 0x01
if bitset.bit_count() > i + 1 and bitset.get_bit(i + 1): byte |= 0x02
if bitset.bit_count() > i + 2 and bitset.get_bit(i + 2): byte |= 0x04
if bitset.bit_count() > i + 3 and bitset.get_bit(i + 3): byte |= 0x08
if bitset.bit_count() > i + 4 and bitset.get_bit(i + 4): byte |= 0x10
if bitset.bit_count() > i + 5 and bitset.get_bit(i + 5): byte |= 0x20
if bitset.bit_count() > i + 6 and bitset.get_bit(i + 6): byte |= 0x40
# Set highest bit if there's more bytes to read
if bitset.bit_count() > i + 7: byte |= 80
b.put_u8(byte)
func decode(b: StreamPeerBuffer) -> Variant:
var bools := []
while true:
var byte := b.get_u8()
bools.append(byte & 0x01)
bools.append(byte & 0x02)
bools.append(byte & 0x04)
bools.append(byte & 0x08)
bools.append(byte & 0x10)
bools.append(byte & 0x20)
bools.append(byte & 0x40)
# Stop if no more data to read
if byte & 0x80 == 0:
break
return _Bitset.of_bools(bools)
class _Float16Serializer extends NetworkSchemaSerializer:
func encode(v: Variant, b: StreamPeerBuffer) -> void:
if Engine.get_version_info().hex >= 0x040400:
b.put_half(v)
else:
b.put_float(v)
func decode(b: StreamPeerBuffer) -> Variant:
if Engine.get_version_info().hex >= 0x040400:
return b.get_half()
else:
return b.get_float()
class _Float32Serializer extends NetworkSchemaSerializer:
func encode(v: Variant, b: StreamPeerBuffer) -> void: b.put_float(v)
func decode(b: StreamPeerBuffer) -> Variant: return b.get_float()
class _Float64Serializer extends NetworkSchemaSerializer:
func encode(v: Variant, b: StreamPeerBuffer) -> void: b.put_double(v)
func decode(b: StreamPeerBuffer) -> Variant: return b.get_double()
class _GenericVec2Serializer extends NetworkSchemaSerializer:
var component: NetworkSchemaSerializer
func _init(p_component: NetworkSchemaSerializer):
component = p_component
func encode(v: Variant, b: StreamPeerBuffer) -> void:
component.encode(v.x, b)
component.encode(v.y, b)
func decode(b: StreamPeerBuffer) -> Variant:
return Vector2(component.decode(b), component.decode(b))
class _GenericVec3Serializer extends NetworkSchemaSerializer:
var component: NetworkSchemaSerializer
func _init(p_component: NetworkSchemaSerializer):
component = p_component
func encode(v: Variant, b: StreamPeerBuffer) -> void:
component.encode(v.x, b)
component.encode(v.y, b)
component.encode(v.z, b)
func decode(b: StreamPeerBuffer) -> Variant:
return Vector3(
component.decode(b), component.decode(b), component.decode(b)
)
class _Normal2Serializer extends NetworkSchemaSerializer:
var component: NetworkSchemaSerializer
func _init(p_component: NetworkSchemaSerializer):
component = p_component
func encode(v: Variant, b: StreamPeerBuffer) -> void:
component.encode((v as Vector2).angle(), b)
func decode(b: StreamPeerBuffer) -> Variant:
return Vector2.RIGHT.rotated(component.decode(b))
class _Normal3Serializer extends NetworkSchemaSerializer:
var component: NetworkSchemaSerializer
func _init(p_component: NetworkSchemaSerializer):
component = p_component
func encode(v: Variant, b: StreamPeerBuffer) -> void:
var uv := (v as Vector3).octahedron_encode()
component.encode(uv.x, b)
component.encode(uv.y, b)
func decode(b: StreamPeerBuffer) -> Variant:
return Vector3.octahedron_decode(
Vector2(component.decode(b), component.decode(b))
)
class _GenericVec4Serializer extends NetworkSchemaSerializer:
var component: NetworkSchemaSerializer
func _init(p_component: NetworkSchemaSerializer):
component = p_component
func encode(v: Variant, b: StreamPeerBuffer) -> void:
component.encode(v.x, b)
component.encode(v.y, b)
component.encode(v.z, b)
component.encode(v.w, b)
func decode(b: StreamPeerBuffer) -> Variant:
return Vector4(
component.decode(b), component.decode(b), component.decode(b), component.decode(b)
)
class _GenericQuaternionSerializer extends NetworkSchemaSerializer:
var component: NetworkSchemaSerializer
func _init(p_component: NetworkSchemaSerializer):
component = p_component
func encode(v: Variant, b: StreamPeerBuffer) -> void:
component.encode(v.x, b)
component.encode(v.y, b)
component.encode(v.z, b)
component.encode(v.w, b)
func decode(b: StreamPeerBuffer) -> Variant:
return Quaternion(
component.decode(b), component.decode(b), component.decode(b), component.decode(b)
)
class _GenericTransform2DSerializer extends NetworkSchemaSerializer:
var component: NetworkSchemaSerializer
func _init(p_component: NetworkSchemaSerializer):
component = p_component
func encode(v: Variant, b: StreamPeerBuffer) -> void:
var t := v as Transform2D
component.encode(t.x.x, b); component.encode(t.x.y, b)
component.encode(t.y.x, b); component.encode(t.y.y, b)
component.encode(t.origin.x, b); component.encode(t.origin.y, b)
func decode(b: StreamPeerBuffer) -> Variant:
return Transform2D(
Vector2(component.decode(b), component.decode(b)),
Vector2(component.decode(b), component.decode(b)),
Vector2(component.decode(b), component.decode(b)),
)
class _GenericTransform3DSerializer extends NetworkSchemaSerializer:
var component: NetworkSchemaSerializer
func _init(p_component: NetworkSchemaSerializer):
component = p_component
func encode(v: Variant, b: StreamPeerBuffer) -> void:
var t := v as Transform3D
component.encode(t.basis.x.x, b); component.encode(t.basis.x.y, b); component.encode(t.basis.x.z, b)
component.encode(t.basis.y.x, b); component.encode(t.basis.y.y, b); component.encode(t.basis.y.z, b)
component.encode(t.basis.z.x, b); component.encode(t.basis.z.y, b); component.encode(t.basis.z.z, b)
component.encode(t.origin.x, b); component.encode(t.origin.y, b); component.encode(t.origin.z, b)
func decode(b: StreamPeerBuffer) -> Variant:
return Transform3D(
Basis(
Vector3(component.decode(b), component.decode(b), component.decode(b)),
Vector3(component.decode(b), component.decode(b), component.decode(b)),
Vector3(component.decode(b), component.decode(b), component.decode(b)),
),
Vector3(component.decode(b), component.decode(b), component.decode(b))
)
class _QuantizingSerializer extends NetworkSchemaSerializer:
var component: NetworkSchemaSerializer
var from_min: Variant
var from_max: Variant
var to_min: Variant
var to_max: Variant
func _init(
p_component: NetworkSchemaSerializer, p_from_min: Variant,
p_from_max: Variant, p_to_min: Variant, p_to_max: Variant
):
component = p_component
from_min = p_from_min
from_max = p_from_max
to_min = p_to_min
to_max = p_to_max
func encode(v: Variant, b: StreamPeerBuffer) -> void:
var f := inverse_lerp(from_min, from_max, v)
var s := lerp(to_min, to_max, f)
component.encode(s, b)
func decode(b: StreamPeerBuffer) -> Variant:
var s := component.decode(b)
var f := inverse_lerp(to_min, to_max, s)
return lerp(from_min, from_max, f)
class _ModuloSerializer extends NetworkSchemaSerializer:
var component: NetworkSchemaSerializer
var value_max: Variant
var component_max: Variant
func _init(p_component: NetworkSchemaSerializer, p_value_max: Variant, p_component_max: Variant):
component = p_component
value_max = p_value_max
component_max = p_component_max
func encode(v: Variant, b: StreamPeerBuffer) -> void:
var f = fposmod(float(v), value_max) / value_max
var s = f * component_max
component.encode(s, b)
func decode(b: StreamPeerBuffer) -> Variant:
var s = float(component.decode(b))
return (s / component_max) * value_max
class _ArraySerializer extends NetworkSchemaSerializer:
var component: NetworkSchemaSerializer
var size: NetworkSchemaSerializer
func _init(p_component: NetworkSchemaSerializer, p_size: NetworkSchemaSerializer):
component = p_component
size = p_size
func encode(v: Variant, b: StreamPeerBuffer) -> void:
var array := v as Array
size.encode(array.size(), b)
for item in array:
component.encode(item, b)
func decode(b: StreamPeerBuffer) -> Variant:
var array := []
var item_count = size.decode(b)
array.resize(item_count)
for i in item_count:
array[i] = component.decode(b)
return array
class _DictionarySerializer extends NetworkSchemaSerializer:
var key_serializer: NetworkSchemaSerializer
var value_serializer: NetworkSchemaSerializer
var size_serializer: NetworkSchemaSerializer
func _init(p_key_serializer: NetworkSchemaSerializer, p_value_serializer: NetworkSchemaSerializer, p_size_serializer: NetworkSchemaSerializer):
key_serializer = p_key_serializer
value_serializer = p_value_serializer
size_serializer = p_size_serializer
func encode(v: Variant, b: StreamPeerBuffer) -> void:
var dictionary := v as Dictionary
size_serializer.encode(dictionary.size(), b)
for key in dictionary:
var value = dictionary[key]
key_serializer.encode(key, b)
value_serializer.encode(value, b)
func decode(b: StreamPeerBuffer) -> Variant:
var dictionary := {}
var size = size_serializer.decode(b)
for i in size:
var key = key_serializer.decode(b)
var value = value_serializer.decode(b)
dictionary[key] = value
return dictionary
class _NetworkIdentityReferenceSerializer extends NetworkSchemaSerializer:
static var varuint := _VaruintSerializer.new()
func encode(v: Variant, b: StreamPeerBuffer) -> void:
var ref := v as _NetworkIdentityReference
if ref.has_id():
varuint.encode(ref.get_id(), b)
else:
b.put_u8(0)
# TODO(#562): Get rid of Godot's prepended 32 bits of string length
# TODO(#562): Write is easy, prefer not manually iterating till \0 on read
b.put_utf8_string(ref.get_full_name())
func decode(b: StreamPeerBuffer) -> Variant:
var id := varuint.decode(b) as int
if id == 0:
var full_name := b.get_utf8_string()
return _NetworkIdentityReference.of_full_name(full_name)
else:
return _NetworkIdentityReference.of_id(id)
@@ -0,0 +1 @@
uid://byaxeh31f2i6m