Initial commit for testing/fixing a deprecated godot-colyseus addon

This commit is contained in:
2026-01-10 11:12:02 -05:00
commit 081a5fcf1a
76 changed files with 3456 additions and 0 deletions

View File

@@ -0,0 +1,308 @@
extends "./schema_interface.gd"
const col = preload("res://addons/godot_colyseus/lib/collections.gd")
const OP = preload("res://addons/godot_colyseus/lib/operations.gd")
const TypeInfo = preload("res://addons/godot_colyseus/lib/type_info.gd")
const END_OF_STRUCTURE = 0xc1
const NIL = 0xc0
const INDEX_CHANGE = 0xd4
const Decoder = preload("res://addons/godot_colyseus/lib/decoder.gd")
const EventListener = preload("res://addons/godot_colyseus/lib/listener.gd")
const SchemaInterface = preload("res://addons/godot_colyseus/lib/schema_interface.gd")
class Field:
const Types = preload("res://addons/godot_colyseus/lib/types.gd")
var index: int
var name: String
var value
var current_type: TypeInfo
func _init(name: String,type: String,schema_type = null):
current_type = TypeInfo.new(type)
if schema_type is String:
current_type.sub_type = TypeInfo.new(schema_type)
elif schema_type is GDScript:
if type == Types.REF:
current_type.sub_type = schema_type
else:
current_type.sub_type = TypeInfo.new(Types.REF, schema_type)
elif schema_type is TypeInfo:
current_type.sub_type = schema_type
self.name = name
func _to_string():
if current_type:
return current_type.to_string()
else:
return 'null'
var _fields: Array = []
var _field_index = {}
var _refs = {}
var _change_listeners = {}
func _get_property_list():
var result = []
for field in _fields:
result.append({
name = field.name,
type = Types.to_gd_type(field.current_type.type),
usage = PROPERTY_USAGE_DEFAULT
})
return result
func _get(property):
if _field_index.has(property):
var value = _field_index[property].value
if value is SchemaInterface:
pass
return value
return null
func _set(property, value):
if _field_index.has(property):
var field = _field_index[property]
var old = field.value
if old is SchemaInterface:
pass
field.value = value
return true
return false
# [event: String, target, key_or_index]
# path format {path}:{action}
# {action} is one of:
# add Create sub object, paramaters [current, new_value, key]
# remove Delete sub object paramaters [current, old_value, key]
# replace Replace sub object paramaters [current, new_value, key]
# delete Current object is deleted, paramaters [current]
# create Current object is created, paramaters [current]
# change Current object's attributes has changed, paramaters [current]
# clear Current Array or Map has cleared, paramaters [current]
func listen(path: String) -> EventListener:
if not _change_listeners.has(path):
_change_listeners[path] = EventListener.new()
return _change_listeners[path]
static func define_fields() -> Array:
return []
func _init():
_fields = self.get_script().define_fields()
var counter = 0
for field in _fields:
field.index = counter
_setup_field(field)
counter += 1
func _setup_field(field: Field):
_field_index[field.name] = field
var type = field.current_type
match type.type:
Types.MAP:
assert(type.sub_type != null) #,"Schema type is requested")
Types.ARRAY:
assert(type.sub_type != null) #,"Schema type is requested")
field.value = col.Collection.new()
Types.SET:
assert(type.sub_type != null) #,"Schema type is requested")
Types.COLLECTION:
assert(type.sub_type != null) #,"Schema type is requested")
Types.REF:
assert(type.sub_type != null) #,"Schema type is requested")
Types.NUMBER, Types.FLOAT32, Types.FLOAT64:
field.value = 0.0
Types.INT8, Types.UINT8, Types.INT16, Types.UINT16, Types.INT32, Types.UINT32, Types.INT64, Types.UINT64:
field.value = 0
Types.STRING:
field.value = ""
func get_fields():
return _fields
func decode(decoder: Decoder) -> int:
var ref_id = 0
var ref: Ref = Ref.new(self, TypeInfo.new(Types.REF))
_refs[ref_id] = ref
var changes = []
var changed_objects = {}
while decoder.has_more():
var byte = decoder.reader.get_u8()
if byte == OP.SWITCH_TO_STRUCTURE:
ref_id = decoder.number()
var next_ref = _refs[ref_id]
assert(next_ref != null) #,str('"refId" not found:', ref_id))
ref = next_ref
continue
var is_schema = ref.type_info.type == Types.REF
var operation = byte
if is_schema:
operation = (byte >> 6) << 6
if operation == OP.CLEAR:
ref.value.clear(true)
if ref.value is SchemaInterface:
changes.append({
target = ref.value,
event = "clear",
argv = []
})
continue
var field_index = byte % _re_replace(operation)
if not is_schema:
field_index = decoder.number()
var ref_value = ref.value
if ref_value is SchemaInterface:
var old = ref_value.meta_get(field_index)
var new
var key = field_index
if ref.type_info.type != Types.MAP:
key = ref_value.meta_get_key(field_index)
if operation == OP.DELETE:
if ref.type_info.type == Types.MAP:
key = ref_value.meta_get_key(field_index)
ref_value.meta_remove(field_index)
else:
if ref.type_info.type == Types.MAP:
key = decoder.read_utf8()
var type: TypeInfo = ref_value.meta_get_subtype(field_index)
if type.is_schema_type():
var new_ref_id = decoder.number()
if _refs.has(new_ref_id):
new = _refs[new_ref_id].value
else:
if operation != OP.REPLACE:
new = type.create()
new.id = new_ref_id
_refs[new_ref_id] = Ref.new(new, type)
else:
new = type.decode(decoder)
if old != new:
if old == null:
changes.append({
target = ref_value,
event = "add",
argv = [new, key]
})
elif new == null:
changes.append({
target = ref_value,
event = "remove",
argv = [old, key]
})
else:
changes.append({
target = ref_value,
event = "replace",
argv = [new, key]
})
if old != null:
if old is SchemaInterface && old.id != null:
changes.append({
target = old,
event = "delete",
argv = []
})
_refs.erase(old.id)
if new != null:
ref_value.meta_set(field_index, key, new)
if new is SchemaInterface:
changes.append({
target = new,
event = "create",
argv = []
})
new.set_parent(ref_value, field_index)
elif old != null:
ref_value.meta_remove(field_index)
changed_objects[ref_value] = true
for change in changes:
var target = change.target
target.trigger(change.event, change.argv)
for target in changed_objects.keys():
target.trigger("change", [])
return 0
func _re_replace(operation):
if operation == OP.REPLACE:
return 255
return operation
func clear(decoding: bool = false):
pass
func meta_get(index):
assert(_fields.size() > index)
var field : Field = _fields[index]
return field.value
func meta_get_key(index):
assert(_fields.size() > index)
var field : Field = _fields[index]
return field.name
func meta_get_subtype(index):
assert(_fields.size() > index)
var field : Field = _fields[index]
return field.current_type
func meta_set(index, key, value):
assert(_fields.size() > index)
var field : Field = _fields[index]
field.value = value
func meta_remove(index):
assert(_fields.size() > index)
var field : Field = _fields[index]
var old = field.value
field.value = null
return old
func _to_string():
var obj = to_object()
return JSON.stringify(obj)
func trigger(event: String, argv: Array = [], path: PackedStringArray = PackedStringArray(), target: Object = self):
var path_copy = PackedStringArray(path)
path_copy.reverse()
var path_str = '/'.join(path_copy) + ":" + event
if _change_listeners.has(path_str):
var ls: EventListener = _change_listeners[path_str]
argv.insert(0, target)
ls.emit(argv)
else:
super.trigger(event, argv, path, target)
func to_object():
var dic = {}
for field in _fields:
if field.value is SchemaInterface:
dic[field.name] = field.value.to_object()
else:
dic[field.name] = field.value
return dic