Skip to content

Commit

Permalink
fixes ordering issue on map schema. refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
endel committed Oct 4, 2019
1 parent 9ac707c commit 544e45b
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 79 deletions.
27 changes: 27 additions & 0 deletions colyseus/serialization/schema/array_schema.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
local array_schema = {}

function array_schema:new(obj)
obj = obj or {}
setmetatable(obj, self)
self.__index = self
return obj
end

function array_schema:trigger_all()
if type(self) ~= "table" or self['on_add'] == nil then return end
for key, value in ipairs(self) do
if key ~= 'on_add' and key ~= 'on_remove' and key ~= 'on_change' then
self['on_add'](value, key)
end
end
end

function array_schema:clone()
local cloned = array_schema:new(table.clone(self))
cloned['on_add'] = self['on_add']
cloned['on_remove'] = self['on_remove']
cloned['on_change'] = self['on_change']
return cloned
end

return array_schema
74 changes: 74 additions & 0 deletions colyseus/serialization/schema/map_schema.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
local map_schema = {}
map_schema.__index = map_schema

function map_schema:new(obj)
obj = { __keys = {} }
setmetatable(obj, map_schema)
return obj
end

function map_schema:set(key, value)
if value == nil then
-- delete!
for i, k in pairs(self.__keys) do
if k == key then
table.remove(self.__keys, i)
break
end
end

self[key] = nil
else
-- insert!
if not self[key] then
table.insert(self.__keys, key)
end
self[key] = value
end
end

function map_schema:length()
return #self.__keys
end

function map_schema:keys()
return self.__keys
end

function map_schema:values()
local values = {}
for _, key in ipairs(self.__keys) do
table.insert(values, self[key])
end
return values
end

function map_schema:each(cb)
for _, key in ipairs(self.__keys) do
cb(self[key], key)
end
end

function map_schema:trigger_all()
if type(self) ~= "table" or self['on_add'] == nil then return end
for key, value in pairs(self) do
if key ~= 'on_add' and key ~= 'on_remove' and key ~= 'on_change' and key ~= '__keys' then
self['on_add'](value, key)
end
end
end

function map_schema:clone()
local cloned = map_schema:new()

for _, key in ipairs(self.__keys) do
cloned:set(key, self[key])
end

cloned['on_add'] = self['on_add']
cloned['on_remove'] = self['on_remove']
cloned['on_change'] = self['on_change']
return cloned
end

return map_schema
95 changes: 16 additions & 79 deletions colyseus/serialization/schema/schema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
local bit = require 'colyseus.serialization.bit'
local ldexp = math.ldexp or mathx.ldexp

local array_schema = require 'colyseus.serialization.schema.array_schema'
local map_schema = require 'colyseus.serialization.schema.map_schema'

-- START SPEC --
local spec = {
END_OF_STRUCTURE = 193,
Expand Down Expand Up @@ -516,60 +519,6 @@ function table.keys(orig)
end
-- END UTIL FUNCTIONS --

-- START MAP SCHEMA
local MapSchema = {}
function MapSchema:new(obj)
obj = obj or {}
setmetatable(obj, self)
self.__index = self
return obj
end

function MapSchema:trigger_all()
if type(self) ~= "table" or self['on_add'] == nil then return end
for key, value in pairs(self) do
if key ~= 'on_add' and key ~= 'on_remove' and key ~= 'on_change' then
self['on_add'](value, key)
end
end
end

function MapSchema:clone()
local cloned = MapSchema:new(table.clone(self))
cloned['on_add'] = self['on_add']
cloned['on_remove'] = self['on_remove']
cloned['on_change'] = self['on_change']
return cloned
end
-- END MAP SCHEMA

-- START ARRAY SCHEMA
local ArraySchema = {}
function ArraySchema:new(obj)
obj = obj or {}
setmetatable(obj, self)
self.__index = self
return obj
end

function ArraySchema:trigger_all()
if type(self) ~= "table" or self['on_add'] == nil then return end
for key, value in ipairs(self) do
if key ~= 'on_add' and key ~= 'on_remove' and key ~= 'on_change' then
self['on_add'](value, key)
end
end
end

function ArraySchema:clone()
local cloned = ArraySchema:new(table.clone(self))
cloned['on_add'] = self['on_add']
cloned['on_remove'] = self['on_remove']
cloned['on_change'] = self['on_change']
return cloned
end
-- END ARRAY SCHEMA

-- START CONTEXT CLASS --
local Context = {}
function Context:new(obj)
Expand Down Expand Up @@ -677,7 +626,7 @@ function Schema:decode(bytes, it)
local typeref = ftype[1]
change = {}

local value_ref = self[field] or ArraySchema:new()
local value_ref = self[field] or array_schema:new()
value = value_ref:clone() -- create new reference for array


Expand All @@ -692,7 +641,7 @@ function Schema:decode(bytes, it)

-- ensure current array has the same length as encoded one
if #value >= new_length then
local new_values = ArraySchema:new()
local new_values = array_schema:new()
new_values['on_add'] = value_ref['on_add']
new_values['on_remove'] = value_ref['on_remove']
new_values['on_change'] = value_ref['on_change']
Expand All @@ -704,7 +653,7 @@ function Schema:decode(bytes, it)
item["on_remove"]()
end

-- call on_remove from ArraySchema
-- call on_remove from array_schema
if value_ref["on_remove"] ~= nil then
value_ref["on_remove"](item, i)
end
Expand Down Expand Up @@ -761,7 +710,7 @@ function Schema:decode(bytes, it)
if decode.nil_check(bytes, it) then
it.offset = it.offset + 1

-- call on_remove from ArraySchema
-- call on_remove from array_schema
if value_ref['on_remove'] ~= nil then
value_ref['on_remove'](item, new_index)
end
Expand All @@ -776,7 +725,7 @@ function Schema:decode(bytes, it)
value[new_index] = decode_primitive_type(typeref, bytes, it)
end

-- add on_add from ArraySchema
-- add on_add from array_schema
if is_new then
if value_ref['on_add'] ~= nil then
value_ref['on_add'](value[new_index], new_index)
Expand All @@ -801,8 +750,7 @@ function Schema:decode(bytes, it)
-- decode map
local typeref = ftype['map']

local maporder_key = "_" .. field .. "_maporder"
local value_ref = self[field] or MapSchema:new()
local value_ref = self[field] or map_schema:new()
value = value_ref:clone()

local length = decode.number(bytes, it)
Expand All @@ -826,7 +774,7 @@ function Schema:decode(bytes, it)
local previous_key
if decode.index_change_check(bytes, it) then
decode.uint8(bytes, it)
previous_key = self[maporder_key][decode.number(bytes, it)+1]
previous_key = value.__keys[decode.number(bytes, it)+1]
has_index_change = true
end

Expand All @@ -837,7 +785,7 @@ function Schema:decode(bytes, it)
local map_index
if has_map_index then
map_index = decode.number(bytes, it) + 1
new_key = self[maporder_key][map_index]
new_key = value.__keys[map_index]
else
new_key = decode.string(bytes, it)
end
Expand Down Expand Up @@ -866,16 +814,14 @@ function Schema:decode(bytes, it)
value_ref['on_remove'](item, new_key)
end

value[new_key] = nil
table.remove(self[maporder_key], map_index)
value:set(new_key, nil)
break -- continue

elseif not is_schema_type then
value[new_key] = decode_primitive_type(typeref, bytes, it)
value:set(new_key, decode_primitive_type(typeref, bytes, it))

else
item:decode(bytes, it)
value[new_key] = item
value:set(new_key, item:decode(bytes, it))
end

if is_new then
Expand All @@ -887,15 +833,6 @@ function Schema:decode(bytes, it)
value_ref['on_change'](value[new_key], new_key)
end

if is_new then
-- LUA-specific keep track of keys ordering (lua tables doesn't keep then)
if self[maporder_key] == nil then
self[maporder_key] = {}
end
table.insert(self[maporder_key], new_key)
--
end

break -- continue
until true

Expand Down Expand Up @@ -1047,9 +984,9 @@ local reflection_decode = function (bytes, it)

elseif type(field_type) == "table" then
if field_type.map ~= nil then
root_instance[field_name] = MapSchema:new()
root_instance[field_name] = map_schema:new()
else
root_instance[field_name] = ArraySchema:new()
root_instance[field_name] = array_schema:new()
end
end
end
Expand Down

0 comments on commit 544e45b

Please sign in to comment.