Skip to content

Commit 7148fc0

Browse files
committed
@colyseus/schema: improve instance sharing and ref count tracking.
1 parent 5c13071 commit 7148fc0

File tree

5 files changed

+49
-47
lines changed

5 files changed

+49
-47
lines changed

Assets/Colyseus/Runtime/Colyseus/Serializer/Schema/Decoder.cs

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -124,17 +124,17 @@ protected void DecodeValue(byte[] bytes, Iterator it, IRef _ref, int fieldIndex,
124124
//
125125
if ((operation & (byte)OPERATION.DELETE) == (byte)OPERATION.DELETE)
126126
{
127-
if (operation != (byte)OPERATION.DELETE_AND_ADD)
128-
{
129-
_ref.DeleteByIndex(fieldIndex);
130-
}
131-
132127
// Flag `refId` for garbage collection.
133128
if (previousValue != null && previousValue is IRef)
134129
{
135130
Refs.Remove(((IRef)previousValue).__refId);
136131
}
137132

133+
if (operation != (byte)OPERATION.DELETE_AND_ADD)
134+
{
135+
_ref.DeleteByIndex(fieldIndex);
136+
}
137+
138138
value = null;
139139
}
140140

@@ -152,20 +152,6 @@ protected void DecodeValue(byte[] bytes, Iterator it, IRef _ref, int fieldIndex,
152152
var __refId = Convert.ToInt32(Utils.Decode.DecodeNumber(bytes, it));
153153
value = Refs.Get(__refId);
154154

155-
if (previousValue != null)
156-
{
157-
var previousRefId = ((IRef)previousValue).__refId;
158-
if (
159-
previousRefId > 0 &&
160-
__refId != previousRefId &&
161-
// FIXME: we may need to check for REPLACE operation as well
162-
((operation & (byte)OPERATION.DELETE) == (byte)OPERATION.DELETE)
163-
)
164-
{
165-
Refs.Remove(previousRefId);
166-
}
167-
}
168-
169155
if ((operation & (byte)OPERATION.ADD) == (byte)OPERATION.ADD)
170156
{
171157
System.Type concreteChildType = GetSchemaType(bytes, it, childType);
@@ -210,9 +196,11 @@ protected void DecodeValue(byte[] bytes, Iterator it, IRef _ref, int fieldIndex,
210196
__refId != ((IRef)previousValue).__refId
211197
)
212198
{
213-
Refs.Remove(((IRef)previousValue).__refId);
214-
215199
((ISchemaCollection)previousValue).ForEach((key, value) => {
200+
if (value is IRef) {
201+
Refs.Remove(((IRef)value).__refId);
202+
}
203+
216204
AllChanges.Add(new DataChange
217205
{
218206
RefId = __refId,
@@ -225,7 +213,10 @@ protected void DecodeValue(byte[] bytes, Iterator it, IRef _ref, int fieldIndex,
225213
}
226214
}
227215

228-
Refs.Add(__refId, (IRef)value, valueRef != previousValue);
216+
Refs.Add(__refId, (IRef)value, (
217+
valueRef != previousValue || // increment ref count if value has changed
218+
(operation == (byte)OPERATION.DELETE_AND_ADD && valueRef == previousValue) // increment ref count if the same instance is being added again
219+
));
229220
}
230221
}
231222

Assets/Colyseus/Runtime/Colyseus/Serializer/Schema/ReferenceTracker.cs

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System;
2-
using System.Collections;
32
using System.Collections.Generic;
3+
using UnityEngine;
44

55
namespace Colyseus.Schema
66
{
@@ -80,18 +80,20 @@ public bool Has(int refId)
8080
/// Remove a reference by ID
8181
/// </summary>
8282
/// <param name="refId">The ID of the reference to remove</param>
83-
/// <returns>True if successful, false otherwise</returns>
84-
public bool Remove(int refId)
83+
public void Remove(int refId)
8584
{
85+
if (!refCounts.ContainsKey(refId))
86+
{
87+
Debug.Log("trying to remove refId that doesn't exist: " + refId);
88+
return;
89+
}
90+
8691
refCounts[refId] = refCounts[refId] - 1;
8792

88-
if (!deletedRefs.Contains(refId))
93+
if (refCounts[refId] <= 0)
8994
{
9095
deletedRefs.Add(refId);
91-
return true;
9296
}
93-
94-
return false;
9597
}
9698

9799
/// <summary>
@@ -110,31 +112,36 @@ public void GarbageCollection()
110112
IRef _ref = refs[refId];
111113
if (_ref is Schema)
112114
{
113-
foreach (KeyValuePair<string, System.Type> field in ((Schema) _ref).GetFieldChildTypes())
115+
foreach (KeyValuePair<string, System.Type> field in ((Schema)_ref).GetFieldChildTypes())
114116
{
115-
object fieldValue = ((Schema) _ref)[field.Key];
116-
if (
117-
fieldValue is IRef &&
118-
Remove(((IRef) fieldValue).__refId))
117+
object fieldValue = ((Schema)_ref)[field.Key];
118+
if (fieldValue is IRef)
119119
{
120-
totalDeletedRefs++;
120+
int childRefId = ((IRef)fieldValue).__refId;
121+
if (!deletedRefs.Contains(childRefId))
122+
{
123+
Remove(childRefId);
124+
totalDeletedRefs++;
125+
}
121126
}
122127
}
123128
}
124-
else if (_ref is ISchemaCollection && ((ISchemaCollection) _ref).HasSchemaChild)
129+
else if (_ref is ISchemaCollection && ((ISchemaCollection)_ref).HasSchemaChild)
125130
{
126-
((ISchemaCollection)_ref).ForEach((key, value) =>
127-
{
128-
if (Remove(((IRef)value).__refId))
129-
{
130-
totalDeletedRefs++;
131-
}
132-
});
131+
((ISchemaCollection)_ref).ForEach((key, value) =>
132+
{
133+
int childRefId = ((IRef)value).__refId;
134+
if (!deletedRefs.Contains(childRefId))
135+
{
136+
Remove(childRefId);
137+
totalDeletedRefs++;
138+
}
139+
});
133140
}
134141

135142
refs.Remove(refId);
136143
refCounts.Remove(refId);
137-
callbacks.Remove(refId);
144+
callbacks.Remove(refId);
138145
}
139146
}
140147

Assets/Colyseus/Tests/Editor/ColyseusTests/SchemaDeserializerTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ public void InstanceSharingTypesTest()
417417
var previousArraySchemaRefId = state.arrayOfPlayers.__refId;
418418

419419
// Replacing ArraySchema
420-
decoder.Decode(new byte[] { 130, 9, 255, 9, 128, 0, 10, 255, 10, 128, 11, 255, 11, 128, 10, 129, 20 });
420+
decoder.Decode(new byte[] { 194, 9, 255, 9, 128, 0, 10, 255, 10, 128, 11, 255, 11, 128, 10, 129, 20 });
421421
Assert.AreEqual(false, refs.refs.ContainsKey(previousArraySchemaRefId));
422422
Assert.AreEqual(1, state.arrayOfPlayers.Count);
423423
Assert.AreEqual(5, refs.refs.Count);

Assets/Colyseus/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "io.colyseus.sdk",
3-
"version": "0.16.4",
3+
"version": "0.16.5",
44
"displayName": "Colyseus SDK",
55
"description": "Colyseus Multiplayer SDK for Unity",
66
"unity": "2019.1",

Server/src/rooms/MyRoom.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Room, Client } from "colyseus";
1+
import { Room, Client, AuthContext } from "colyseus";
22
import { MyRoomState, Player } from "./schema/MyRoomState";
33

44
export type PositionMessage = {
@@ -12,6 +12,10 @@ export class MyRoom extends Room<MyRoomState> {
1212
this.setState(new MyRoomState());
1313
}
1414

15+
onAuth(client: Client, options: any, context: AuthContext) {
16+
return false;
17+
}
18+
1519
onJoin (client: Client, options: any) {
1620
console.log(client.sessionId, "joined!");
1721

0 commit comments

Comments
 (0)