From 94e675a29546276f402106dfe33bf24da8c217c2 Mon Sep 17 00:00:00 2001 From: Ash Logan Date: Fri, 3 May 2024 15:22:35 +1000 Subject: [PATCH 1/3] fix(datastore): Account for StructureVersion in DataStoreSearchParam https://nintendo-wiki.pretendo.network/docs/nex/protocols/datastore/#datastoresearchparam-structure Fixes games using revision 0 like PUYOPUYOTETRIS (NEX v3.5). Might need extra work to support NEX v4. May cause regressions in existing games if StructureVersion isn't properly set. --- datastore/types/datastore_search_param.go | 52 ++++++++++++++++------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/datastore/types/datastore_search_param.go b/datastore/types/datastore_search_param.go index 1f58451b..528c2141 100644 --- a/datastore/types/datastore_search_param.go +++ b/datastore/types/datastore_search_param.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" + "github.com/PretendoNetwork/nex-go/v2" "github.com/PretendoNetwork/nex-go/v2/types" ) @@ -27,13 +28,16 @@ type DataStoreSearchParam struct { ResultRange *types.ResultRange ResultOption *types.PrimitiveU8 MinimalRatingFrequency *types.PrimitiveU32 - UseCache *types.PrimitiveBool - TotalCountEnabled *types.PrimitiveBool - DataTypes *types.List[*types.PrimitiveU16] + UseCache *types.PrimitiveBool // * Revision 1 or NEX 4.0 + TotalCountEnabled *types.PrimitiveBool // * Revision 3 or NEX 4.0 + DataTypes *types.List[*types.PrimitiveU16] // * Revision 2 or NEX 4.0 } // WriteTo writes the DataStoreSearchParam to the given writable func (dssp *DataStoreSearchParam) WriteTo(writable types.Writable) { + stream := writable.(*nex.ByteStreamOut) + libraryVersion := stream.LibraryVersions.DataStore + contentWritable := writable.CopyNew() dssp.SearchTarget.WriteTo(contentWritable) @@ -52,9 +56,18 @@ func (dssp *DataStoreSearchParam) WriteTo(writable types.Writable) { dssp.ResultRange.WriteTo(contentWritable) dssp.ResultOption.WriteTo(contentWritable) dssp.MinimalRatingFrequency.WriteTo(contentWritable) - dssp.UseCache.WriteTo(contentWritable) - dssp.TotalCountEnabled.WriteTo(contentWritable) - dssp.DataTypes.WriteTo(contentWritable) + + if dssp.StructureVersion >= 1 || libraryVersion.GreaterOrEqual("4.0.0") { + dssp.UseCache.WriteTo(contentWritable) + } + + if dssp.StructureVersion >= 3 || libraryVersion.GreaterOrEqual("4.0.0") { + dssp.TotalCountEnabled.WriteTo(contentWritable) + } + + if dssp.StructureVersion >= 2 || libraryVersion.GreaterOrEqual("4.0.0") { + dssp.DataTypes.WriteTo(contentWritable) + } content := contentWritable.Bytes() @@ -65,6 +78,9 @@ func (dssp *DataStoreSearchParam) WriteTo(writable types.Writable) { // ExtractFrom extracts the DataStoreSearchParam from the given readable func (dssp *DataStoreSearchParam) ExtractFrom(readable types.Readable) error { + stream := readable.(*nex.ByteStreamIn) + libraryVersion := stream.LibraryVersions.DataStore + var err error err = dssp.ExtractHeaderFrom(readable) @@ -152,19 +168,25 @@ func (dssp *DataStoreSearchParam) ExtractFrom(readable types.Readable) error { return fmt.Errorf("Failed to extract DataStoreSearchParam.MinimalRatingFrequency. %s", err.Error()) } - err = dssp.UseCache.ExtractFrom(readable) - if err != nil { - return fmt.Errorf("Failed to extract DataStoreSearchParam.UseCache. %s", err.Error()) + if dssp.StructureVersion >= 1 || libraryVersion.GreaterOrEqual("4.0.0") { + err = dssp.UseCache.ExtractFrom(readable) + if err != nil { + return fmt.Errorf("Failed to extract DataStoreSearchParam.UseCache. %s", err.Error()) + } } - err = dssp.TotalCountEnabled.ExtractFrom(readable) - if err != nil { - return fmt.Errorf("Failed to extract DataStoreSearchParam.TotalCountEnabled. %s", err.Error()) + if dssp.StructureVersion >= 3 || libraryVersion.GreaterOrEqual("4.0.0") { + err = dssp.TotalCountEnabled.ExtractFrom(readable) + if err != nil { + return fmt.Errorf("Failed to extract DataStoreSearchParam.TotalCountEnabled. %s", err.Error()) + } } - err = dssp.DataTypes.ExtractFrom(readable) - if err != nil { - return fmt.Errorf("Failed to extract DataStoreSearchParam.DataTypes. %s", err.Error()) + if dssp.StructureVersion >= 2 || libraryVersion.GreaterOrEqual("4.0.0") { + err = dssp.DataTypes.ExtractFrom(readable) + if err != nil { + return fmt.Errorf("Failed to extract DataStoreSearchParam.DataTypes. %s", err.Error()) + } } return nil From 567a3fc6f40e3752d516758caab7e93fd4f8f9f6 Mon Sep 17 00:00:00 2001 From: Ash Logan Date: Fri, 3 May 2024 22:07:30 +1000 Subject: [PATCH 2/3] fix(datastore): Account for StructureVersion in DataStoreChangeMetaParam https://nintendo-wiki.pretendo.network/docs/nex/protocols/datastore/#datastorechangemetaparam-structure Fixes games using revision 0 like PUYOPUYOTETRIS (NEX v3.5). May cause regressions in existing games if StructureVersion isn't properly set. --- datastore/types/datastore_change_meta_param.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/datastore/types/datastore_change_meta_param.go b/datastore/types/datastore_change_meta_param.go index cac10c07..eacbe34e 100644 --- a/datastore/types/datastore_change_meta_param.go +++ b/datastore/types/datastore_change_meta_param.go @@ -24,7 +24,7 @@ type DataStoreChangeMetaParam struct { DataType *types.PrimitiveU16 Status *types.PrimitiveU8 CompareParam *DataStoreChangeMetaCompareParam - PersistenceTarget *DataStorePersistenceTarget + PersistenceTarget *DataStorePersistenceTarget // * Revision 1 } // WriteTo writes the DataStoreChangeMetaParam to the given writable @@ -44,7 +44,10 @@ func (dscmp *DataStoreChangeMetaParam) WriteTo(writable types.Writable) { dscmp.DataType.WriteTo(contentWritable) dscmp.Status.WriteTo(contentWritable) dscmp.CompareParam.WriteTo(contentWritable) - dscmp.PersistenceTarget.WriteTo(contentWritable) + + if dscmp.StructureVersion >= 1 { + dscmp.PersistenceTarget.WriteTo(contentWritable) + } content := contentWritable.Bytes() @@ -127,9 +130,11 @@ func (dscmp *DataStoreChangeMetaParam) ExtractFrom(readable types.Readable) erro return fmt.Errorf("Failed to extract DataStoreChangeMetaParam.CompareParam. %s", err.Error()) } - err = dscmp.PersistenceTarget.ExtractFrom(readable) - if err != nil { - return fmt.Errorf("Failed to extract DataStoreChangeMetaParam.PersistenceTarget. %s", err.Error()) + if dscmp.StructureVersion >= 1 { + err = dscmp.PersistenceTarget.ExtractFrom(readable) + if err != nil { + return fmt.Errorf("Failed to extract DataStoreChangeMetaParam.PersistenceTarget. %s", err.Error()) + } } return nil From fc7bc303e710a8a12da4a07b6b779f2d301a31b6 Mon Sep 17 00:00:00 2001 From: Ash Logan Date: Fri, 3 May 2024 22:08:55 +1000 Subject: [PATCH 3/3] fix(datastore): Fix struct order in DataStoreMetaInfo https://nintendo-wiki.pretendo.network/docs/nex/protocols/datastore/#datastoremetainfo-structure All the sources I can find put name first, then dataType. Not sure how this happened? --- datastore/types/datastore_meta_info.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/datastore/types/datastore_meta_info.go b/datastore/types/datastore_meta_info.go index 0d608588..3a1f397e 100644 --- a/datastore/types/datastore_meta_info.go +++ b/datastore/types/datastore_meta_info.go @@ -14,8 +14,8 @@ type DataStoreMetaInfo struct { DataID *types.PrimitiveU64 OwnerID *types.PID Size *types.PrimitiveU32 - DataType *types.PrimitiveU16 Name *types.String + DataType *types.PrimitiveU16 MetaBinary *types.QBuffer Permission *DataStorePermission DelPermission *DataStorePermission @@ -39,8 +39,8 @@ func (dsmi *DataStoreMetaInfo) WriteTo(writable types.Writable) { dsmi.DataID.WriteTo(contentWritable) dsmi.OwnerID.WriteTo(contentWritable) dsmi.Size.WriteTo(contentWritable) - dsmi.DataType.WriteTo(contentWritable) dsmi.Name.WriteTo(contentWritable) + dsmi.DataType.WriteTo(contentWritable) dsmi.MetaBinary.WriteTo(contentWritable) dsmi.Permission.WriteTo(contentWritable) dsmi.DelPermission.WriteTo(contentWritable) @@ -87,14 +87,14 @@ func (dsmi *DataStoreMetaInfo) ExtractFrom(readable types.Readable) error { return fmt.Errorf("Failed to extract DataStoreMetaInfo.Size. %s", err.Error()) } - err = dsmi.DataType.ExtractFrom(readable) + err = dsmi.Name.ExtractFrom(readable) if err != nil { - return fmt.Errorf("Failed to extract DataStoreMetaInfo.DataType. %s", err.Error()) + return fmt.Errorf("Failed to extract DataStoreMetaInfo.Name. %s", err.Error()) } - err = dsmi.Name.ExtractFrom(readable) + err = dsmi.DataType.ExtractFrom(readable) if err != nil { - return fmt.Errorf("Failed to extract DataStoreMetaInfo.Name. %s", err.Error()) + return fmt.Errorf("Failed to extract DataStoreMetaInfo.DataType. %s", err.Error()) } err = dsmi.MetaBinary.ExtractFrom(readable) @@ -178,8 +178,8 @@ func (dsmi *DataStoreMetaInfo) Copy() types.RVType { copied.DataID = dsmi.DataID.Copy().(*types.PrimitiveU64) copied.OwnerID = dsmi.OwnerID.Copy().(*types.PID) copied.Size = dsmi.Size.Copy().(*types.PrimitiveU32) - copied.DataType = dsmi.DataType.Copy().(*types.PrimitiveU16) copied.Name = dsmi.Name.Copy().(*types.String) + copied.DataType = dsmi.DataType.Copy().(*types.PrimitiveU16) copied.MetaBinary = dsmi.MetaBinary.Copy().(*types.QBuffer) copied.Permission = dsmi.Permission.Copy().(*DataStorePermission) copied.DelPermission = dsmi.DelPermission.Copy().(*DataStorePermission) @@ -222,11 +222,11 @@ func (dsmi *DataStoreMetaInfo) Equals(o types.RVType) bool { return false } - if !dsmi.DataType.Equals(other.DataType) { + if !dsmi.Name.Equals(other.Name) { return false } - if !dsmi.Name.Equals(other.Name) { + if !dsmi.DataType.Equals(other.DataType) { return false } @@ -301,8 +301,8 @@ func (dsmi *DataStoreMetaInfo) FormatToString(indentationLevel int) string { b.WriteString(fmt.Sprintf("%sDataID: %s,\n", indentationValues, dsmi.DataID)) b.WriteString(fmt.Sprintf("%sOwnerID: %s,\n", indentationValues, dsmi.OwnerID.FormatToString(indentationLevel+1))) b.WriteString(fmt.Sprintf("%sSize: %s,\n", indentationValues, dsmi.Size)) - b.WriteString(fmt.Sprintf("%sDataType: %s,\n", indentationValues, dsmi.DataType)) b.WriteString(fmt.Sprintf("%sName: %s,\n", indentationValues, dsmi.Name)) + b.WriteString(fmt.Sprintf("%sDataType: %s,\n", indentationValues, dsmi.DataType)) b.WriteString(fmt.Sprintf("%sMetaBinary: %s,\n", indentationValues, dsmi.MetaBinary)) b.WriteString(fmt.Sprintf("%sPermission: %s,\n", indentationValues, dsmi.Permission.FormatToString(indentationLevel+1))) b.WriteString(fmt.Sprintf("%sDelPermission: %s,\n", indentationValues, dsmi.DelPermission.FormatToString(indentationLevel+1))) @@ -354,8 +354,8 @@ func NewDataStoreMetaInfo() *DataStoreMetaInfo { DataID: types.NewPrimitiveU64(0), OwnerID: types.NewPID(0), Size: types.NewPrimitiveU32(0), - DataType: types.NewPrimitiveU16(0), Name: types.NewString(""), + DataType: types.NewPrimitiveU16(0), MetaBinary: types.NewQBuffer(nil), Permission: NewDataStorePermission(), DelPermission: NewDataStorePermission(),