Skip to content

Commit

Permalink
Network addon now can use tolerance to compare floats
Browse files Browse the repository at this point in the history
  • Loading branch information
Kehom committed May 15, 2020
1 parent 8141084 commit d5a9d21
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 16 deletions.
173 changes: 160 additions & 13 deletions addons/keh_network/entityinfo.gd
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,95 @@ class ReplicableProperty:
name = _name
type = _type
mask = _mask

# Unfortunately must use variant (arguments) here instead of static type
func compare(v1, v2) -> bool:
return v1 == v2

# This is a specialized replicable property for floating point numbers when a tolerance must
# be used when comparing values. In this case the is_equal_approx() function is used
class RPropApprox extends ReplicableProperty:
func _init(_name: String, _mask: int).(_name, TYPE_REAL, _mask) -> void:
pass

func compare(v1: float, v2: float) -> bool:
return is_equal_approx(v1, v2)

# Vector2, Vector3, Quat etc offers a function to perform the is_equal_approx() on each
# component. This specialized ReplicableProperty performs the comparison using that
class RPropApproxi extends ReplicableProperty:
func _init(_name: String, _type: int, _mask: int).(_name, _type, _mask) -> void:
pass

func compare(v1, v2) -> bool:
return v1.is_equal_approx(v2)

# Although a bunch of work to create one specialized replicable property for each one
# of the types bellow, it has been done because there is no easy easy way to directly
# access each component of "compound types" without using the correct names. Moreover,
# instead of creating a new base for each of those, still directly use ReplicableProperty
# as base in order to help with readability and **maybe** performance
# Nevertheless, the specializations bellow are meant to offer custom tolerance values
# to compare floating point values
class RPropTolFloat extends ReplicableProperty:
var tolerance: float
func _init(_name: String, _mask: int, _tolerance: float).(_name, TYPE_REAL, _mask) -> void:
tolerance = _tolerance

func compare(v1: float, v2: float) -> bool:
return (abs(v1 - v2) < tolerance)

class RPropTolVec2 extends ReplicableProperty:
var tolerance: float
func _init(_name: String, _mask: int, _tolerance: float).(_name, TYPE_VECTOR2, _mask) -> void:
tolerance = _tolerance

func compare(v1: Vector2, v2: Vector2) -> bool:
return (abs(v1.x - v2.x) < tolerance &&
abs(v1.y - v2.y) < tolerance)

class RPropTolRec2 extends ReplicableProperty:
var tolerance: float
func _init(_name: String, _mask: int, _tolerance: float).(_name, TYPE_RECT2, _mask) -> void:
tolerance = _tolerance

func compare(v1: Rect2, v2: Rect2) -> bool:
return (abs(v1.position.x - v2.position.x) < tolerance &&
abs(v1.position.y - v2.position.y) < tolerance &&
abs(v1.size.x - v2.size.x) < tolerance &&
abs(v1.size.y - v2.size.y) < tolerance)

class RPropTolQuat extends ReplicableProperty:
var tolerance: float
func _init(_name: String, _mask: int, _tolerance: float).(_name, TYPE_QUAT, _mask) -> void:
tolerance = _tolerance

func compare(v1: Quat, v2: Quat) -> bool:
return (abs(v1.x - v2.x) < tolerance &&
abs(v1.y - v2.y) < tolerance &&
abs(v1.z - v2.z) < tolerance &&
abs(v1.w - v2.w) < tolerance)

class RPropTolVec3 extends ReplicableProperty:
var tolerance: float
func _init(_name: String, _mask: int, _tolerance: float).(_name, TYPE_VECTOR3, _mask) -> void:
tolerance = _tolerance

func compare(v1: Vector3, v2: Vector3) -> bool:
return (abs(v1.x - v2.x) < tolerance &&
abs(v1.y - v2.y) < tolerance &&
abs(v1.z - v2.z) < tolerance)

class RPropTolColor extends ReplicableProperty:
var tolerance: float
func _init(_name: String, _mask: int, _tolerance: float).(_name, TYPE_COLOR, _mask) -> void:
tolerance = _tolerance

func compare(v1: Color, v2: Color) -> bool:
return (abs(v1.r - v2.r) < tolerance &&
abs(v1.g - v2.g) < tolerance &&
abs(v1.b - v2.b) < tolerance &&
abs(v1.a - v2.a) < tolerance)


# Storing registered spawners could be done through dictionaries however
Expand Down Expand Up @@ -163,7 +252,7 @@ func calculate_change_mask(e1: SnapEntityBase, e2: SnapEntityBase) -> int:
var cmask: int = 0

for p in replicable:
if (e1.get(p.name) != e2.get(p.name)):
if (!p.compare(e1.get(p.name), e2.get(p.name))):
cmask |= p.mask

return cmask
Expand Down Expand Up @@ -296,21 +385,17 @@ func _check_properties(cname: String, rpath: String) -> void:
continue

var tp: int = p.type
if (tp == TYPE_INT && obj.has_meta(p.name)):
var mval: int = obj.get_meta(p.name)
match mval:
CTYPE_UINT, CTYPE_BYTE, CTYPE_USHORT:
tp = mval
var rprop: ReplicableProperty = _build_replicable_prop(p.name, tp, mask, obj)

match tp:
TYPE_BOOL, TYPE_INT, TYPE_REAL, TYPE_VECTOR2, TYPE_RECT2, TYPE_QUAT, TYPE_COLOR, TYPE_VECTOR3, CTYPE_UINT, CTYPE_BYTE, CTYPE_USHORT:
# Create the replicable property entry in the internal array
replicable.push_back(ReplicableProperty.new(p.name, tp, mask))
# Advance the mask
mask *= 2
if (rprop):
# Push the replicable property into the internal container
replicable.push_back(rprop)
# Advance the mask
mask *= 2


# After iterating through available properties, verify if there is at least
# one replicable property besides "id" and "class_hash" (taking into account)
# one replicable property besides "id" and "class_hash" taking into account
# the fact that class_hash may be disabled).
if (replicable.size() <= min_size):
_resource = null
Expand Down Expand Up @@ -380,3 +465,65 @@ func _property_writer(repl: ReplicableProperty, entity: SnapEntityBase, into: En
into.write_ushort(val)



func _build_replicable_prop(name: String, tp: int, mask: int, obj: Object) -> ReplicableProperty:
var ret: ReplicableProperty = null

match tp:
TYPE_INT:
# Check if this integer is meant to be used with a different size in bytes
# when encoding/decoding into a byte array
if (obj.has_meta(name)):
var mval: int = obj.get_meta(name)
match mval:
CTYPE_UINT, CTYPE_BYTE, CTYPE_USHORT:
tp = mval

# Use the regular ReplicableProperty because integers don't need tolerance to compare them
ret = ReplicableProperty.new(name, tp, mask)

TYPE_REAL, TYPE_VECTOR2, TYPE_RECT2, TYPE_QUAT, TYPE_VECTOR3, TYPE_COLOR:
# In here, any specialized comparison will be left for later in this function
if (!obj.has_meta(name)):
# This property does not require any special comparison method, so just
# use the default replicable property class
ret = ReplicableProperty.new(name, tp, mask)

TYPE_BOOL:
ret = ReplicableProperty.new(name, tp, mask)

_:
# This is not a supported type. Bail so the test bellow can be done
return null

if (!ret):
# If here, the type is supported but it does require one of the specialized ReplicableProperty
# because a tolerance is required when comparing values. What this means is, the test for the
# existance of the meta has already been done
var tol: float = obj.get_meta(name)

if (tol <= 0.0):
# No custom tolerance is requested so use the is_equal_approx() function
if (tp == TYPE_REAL):
ret = RPropApprox.new(name, mask)
else:
ret = RPropApproxi.new(name, tp, mask)

else:
# A custom tolerance is required. This means the specific type must be known in order to
# create the correct replicable property
match (tp):
TYPE_REAL:
ret = RPropTolFloat.new(name, mask, tol)
TYPE_VECTOR2:
ret = RPropTolVec2.new(name, mask, tol)
TYPE_RECT2:
ret = RPropTolRec2.new(name, mask, tol)
TYPE_QUAT:
ret = RPropTolQuat.new(name, mask, tol)
TYPE_VECTOR3:
ret = RPropTolVec3.new(name, mask, tol)
TYPE_COLOR:
ret = RPropTolColor.new(name, mask, tol)

return ret
3 changes: 0 additions & 3 deletions addons/keh_network/network.gd
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ class_name Network
# properties defined within SnapEntityBase derived classes
# - A function to "whisper" a message to the specified player in a way that the
# message goes through the server first. This can be useful for logging purposes
# - One way to allow error margins to be used during the comparison of snapshot entities,
# more specifically when comparing floating point numbers.
# - Replicated event system.


# Limitations:
Expand Down
21 changes: 21 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Some smaller commits related to minor fixes (specially comment corrections) are not going to be listed here.

#### 2020 May 15
* (Network) Replicated floating point numbers (even compound ones like Vector2, Vector3 etc) can use tolerance to compare them. Tutorial (http://kehomsforge.com/tutorials/multi/GodotAddonPack) has been updated to show how to use this (topic `Floating Point Comparison`)

#### 2020 May 13
* Added a new UI control, the `FancyLineEdit`.
* (Megademo) Changed the "clutter barrel" from CSGPrimitives to a crude "barrel" 3D model.
* (Megademo) projectiles now use client side prediction code.

#### 2020 May 05
* (Network) A rejected player is now properly disconnected.
* (Megademo) Fixed prediction code.

#### 2020 May 04
* (Network) Fixed wrong remote call in the chat system.
* (Network) Slightly improved the function to retrieve custom replicated properties.
* (Megademo) Fixed problem that prevented the main scene to be directly tested (F6 key)

#### 2020 April 17
* Initial release of the Addon Pack.
6 changes: 6 additions & 0 deletions demos/mega/scripts/megasnappchar.gd
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ func _init(uid: int, h: int).(uid, h) -> void:
vertical_vel = 0.0
pitch_angle = 0.0
stamina = 0.0

# Set so position, orientation and vertical velocity are compared with is_equal_approx(),
# which incorporates a tolerance.
set_meta("position", 0)
set_meta("orientation", 0)
set_meta("vertical_vel", 0)


func apply_state(to_node: Node) -> void:
Expand Down
5 changes: 5 additions & 0 deletions project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ gdscript/completion/autocomplete_setters_and_getters=true

enabled=PoolStringArray( "keh_network", "keh_smooth", "keh_ui" )

[global]

warning=true

[input]

move_forward={
Expand Down Expand Up @@ -248,6 +252,7 @@ multiselect={
[physics]

common/physics_fps=30
common/physics_jitter_fix=0.0
3d/physics_engine="Bullet"

[rendering]
Expand Down

0 comments on commit d5a9d21

Please sign in to comment.