Skip to content

Commit 2a36c9c

Browse files
MostCromulentclaude
andcommitted
Restore Android record deserialization fallback in TrackableSerializer
<!-- -->Card-Forge#10343 replaced GameEventProxy with TrackableSerializer but did not carry forward the readClassDescriptor() override added in <!-- -->Card-Forge#10304. Android's D8 desugars records to regular classes with computed serialVersionUIDs, while the JVM hardcodes 0L for records — so every GameEvent now fails to deserialize on Android clients in cross-platform network play (visible as "TrackableSerializer: Failed to unwrap event: ... local class incompatible: stream classdesc serialVersionUID = 0, local class serialVersionUID = ..." warnings). Re-applies the same pattern used in CObjectInputStream and the deleted GameEventProxy: when the stream's UID disagrees with the local class UID, fall through to the local descriptor. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 22b1816 commit 2a36c9c

1 file changed

Lines changed: 17 additions & 0 deletions

File tree

forge-gui/src/main/java/forge/gamemodes/net/TrackableSerializer.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,23 @@ static class ResolvingInputStream extends ObjectInputStream {
226226
enableResolveObject(true);
227227
}
228228

229+
// Android desugars records to classes with computed serialVersionUID; the JVM keeps records at 0L.
230+
// Fall through to the local descriptor when UIDs mismatch.
231+
@Override
232+
protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
233+
ObjectStreamClass streamDesc = super.readClassDescriptor();
234+
try {
235+
Class<?> localClass = Class.forName(streamDesc.getName());
236+
ObjectStreamClass localDesc = ObjectStreamClass.lookup(localClass);
237+
if (localDesc != null && streamDesc.getSerialVersionUID() != localDesc.getSerialVersionUID()) {
238+
return localDesc;
239+
}
240+
} catch (ClassNotFoundException ignored) {
241+
// Class not found locally — fall through to stream descriptor.
242+
}
243+
return streamDesc;
244+
}
245+
229246
@Override
230247
protected Object resolveObject(Object obj) {
231248
return resolve(obj, tracker);

0 commit comments

Comments
 (0)