b0c83af092
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>
883 lines
30 KiB
GDScript
883 lines
30 KiB
GDScript
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)
|