diff --git a/gdxsv/db.go b/gdxsv/db.go index 448a06d..b02b43e 100644 --- a/gdxsv/db.go +++ b/gdxsv/db.go @@ -121,6 +121,7 @@ type MLobbySetting struct { TeamShuffle bool `db:"team_shuffle" json:"team_shuffle"` PingLimit int `db:"ping_limit" json:"ping_limit"` PingRegion string `db:"ping_region" json:"ping_region"` + PatchNames string `db:"patch_names" json:"patch_names"` } type MRule struct { @@ -150,6 +151,14 @@ type MRule struct { StageNo int `db:"stage_no" json:"stage_no"` } +type MPatch struct { + Platform string `db:"platform" json:"platform"` + Disk string `db:"disk" json:"disk"` + Name string `db:"name" json:"name"` + WriteOnce bool `db:"write_once" json:"write_once"` + Codes string `db:"codes" json:"codes"` +} + // DB is an interface of database operation. type DB interface { // Init initializes the database. @@ -227,4 +236,7 @@ type DB interface { // GetRule returns game rule. GetRule(id string) (*MRule, error) + + // GetPatch returns game patch. + GetPatch(platform, disk, name string) (*MPatch, error) } diff --git a/gdxsv/db_sqlite.go b/gdxsv/db_sqlite.go index 3da6880..9abfcfb 100644 --- a/gdxsv/db_sqlite.go +++ b/gdxsv/db_sqlite.go @@ -128,6 +128,7 @@ CREATE TABLE IF NOT EXISTS m_lobby_setting team_shuffle integer not null, ping_limit integer not null, ping_region text default '', + patch_names text default '', PRIMARY KEY (platform, disk, no) ); CREATE TABLE IF NOT EXISTS m_rule @@ -158,6 +159,15 @@ CREATE TABLE IF NOT EXISTS m_rule stage_no integer not null, PRIMARY KEY (id) ); +CREATE TABLE IF NOT EXISTS m_patch +( + platform text not null, + disk text not null, + name text not null, + write_once integer not null, + codes text not null, + PRIMARY KEY (platform, disk, name) +); ` const indexes = ` @@ -658,3 +668,12 @@ func (db SQLiteDB) GetRule(id string) (*MRule, error) { } return m, nil } + +func (db SQLiteDB) GetPatch(platform, disk, name string) (*MPatch, error) { + m := &MPatch{} + err := db.QueryRowx("SELECT * FROM m_patch WHERE platform = ? AND disk = ? AND name = ?", platform, disk, name).StructScan(m) + if err != nil { + return nil, err + } + return m, nil +} diff --git a/gdxsv/db_test.go b/gdxsv/db_test.go index 87df19b..4d83e6a 100644 --- a/gdxsv/db_test.go +++ b/gdxsv/db_test.go @@ -603,3 +603,24 @@ INSERT INTO m_rule ( panic(err) } } + +func mustInsertMPatch(patch MPatch) { + db := getDB().(SQLiteDB) + _, err := db.NamedExec(` +INSERT INTO m_patch ( + platform , + disk , + name , + write_once , + codes +) VALUES ( + :platform , + :disk , + :name , + :write_once , + :codes +)`, patch) + if err != nil { + panic(err) + } +} diff --git a/gdxsv/lbs_handler.go b/gdxsv/lbs_handler.go index 19c376f..cab62e4 100644 --- a/gdxsv/lbs_handler.go +++ b/gdxsv/lbs_handler.go @@ -159,6 +159,7 @@ const ( // gdxsv extended commands lbsExtSyncSharedData CmdID = 0x9900 lbsPlatformInfo CmdID = 0x9950 + lbsGamePatch CmdID = 0x9960 ) func RequestLineCheck(p *LbsPeer) { @@ -250,12 +251,12 @@ func sendUserList(p *LbsPeer) { p.SendMessage(n) } -func isOldFlycastVersion(userVersion string) bool { +func isOldFlycastVersion(userVersion string, minVersion string) bool { if strings.HasPrefix(userVersion, "gdxsv-") { // New version-string have the prefix. userVersion = "v" + strings.TrimPrefix(userVersion, "gdxsv-") } - if semver.Compare(userVersion, requiredFlycastVersion) < 0 { + if semver.Compare(userVersion, minVersion) < 0 { return true } return false @@ -284,7 +285,7 @@ var _ = register(lbsLoginType, func(p *LbsPeer, m *LbsMessage) { switch loginType { case 0: - if p.PlatformInfo["flycast"] != "" && isOldFlycastVersion(p.PlatformInfo["flycast"]) { + if p.PlatformInfo["flycast"] != "" && isOldFlycastVersion(p.PlatformInfo["flycast"], requiredFlycastVersion) { p.SendMessage(NewServerNotice(lbsShutDown).Writer(). WriteString("
PLEASE UPDATE Flycast").Msg()) return @@ -334,7 +335,7 @@ var _ = register(lbsLoginType, func(p *LbsPeer, m *LbsMessage) { p.SendMessage(NewServerNotice(lbsShutDown).Writer(). WriteString("
UNSUPPORTED LOGIN TYPE").Msg()) case 2: - if p.PlatformInfo["flycast"] != "" && isOldFlycastVersion(p.PlatformInfo["flycast"]) { + if p.PlatformInfo["flycast"] != "" && isOldFlycastVersion(p.PlatformInfo["flycast"], requiredFlycastVersion) { p.SendMessage(NewServerNotice(lbsShutDown).Writer(). WriteString("
PLEASE UPDATE Flycast").Msg()) return @@ -842,6 +843,13 @@ var _ = register(lbsPlazaStatus, func(p *LbsPeer, m *LbsMessage) { } } + // Check GamePatch feature is available + if lobby.LobbySetting.PatchNames != "" { + if p.PlatformInfo["flycast"] != "" && isOldFlycastVersion(p.PlatformInfo["flycast"], novelFlycastVersion) { + status = 1 + } + } + p.SendMessage(NewServerAnswer(m).Writer(). Write16(lobbyID). Write8(uint8(status)).Msg()) diff --git a/gdxsv/lbs_handler_test.go b/gdxsv/lbs_handler_test.go index 253acdf..21c1b1e 100644 --- a/gdxsv/lbs_handler_test.go +++ b/gdxsv/lbs_handler_test.go @@ -42,13 +42,19 @@ func Test_isOldFlycastVersion(t *testing.T) { args: args{userVersion: "gdxsv-0.6.9"}, want: true, }, + { + name: "real semver dev version is old", + requiredVersion: "v1.0.4", + args: args{userVersion: "v1.0.4-dev.3+100e01d4"}, + want: true, + }, } backup := requiredFlycastVersion for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { requiredFlycastVersion = tt.requiredVersion - if got := isOldFlycastVersion(tt.args.userVersion); got != tt.want { + if got := isOldFlycastVersion(tt.args.userVersion, requiredFlycastVersion); got != tt.want { t.Errorf("isOldFlycastVersion() = %v, want %v", got, tt.want) } }) diff --git a/gdxsv/lbs_lobby.go b/gdxsv/lbs_lobby.go index 5bc966d..86088c5 100644 --- a/gdxsv/lbs_lobby.go +++ b/gdxsv/lbs_lobby.go @@ -3,7 +3,9 @@ package main import ( "database/sql" "fmt" + "gdxsv/gdxsv/proto" "go.uber.org/zap" + pb "google.golang.org/protobuf/proto" "math/rand" "sort" "strconv" @@ -349,6 +351,20 @@ func (l *LbsLobby) printLobbyReminder(p *LbsPeer) { func (l *LbsLobby) Enter(p *LbsPeer) { l.Users[p.UserID] = &p.DBUser + + // Send game patch for offline testing + if l.LobbySetting.PatchNames != "" { + patchList := l.makePatchList() + logger.Info("patchList", zap.Any("patchList", patchList)) + patchBin, err := pb.Marshal(patchList) + if err != nil { + logger.Error("pb.Marshal patch", zap.Error(err)) + return + } + patchMsg := NewServerNotice(lbsGamePatch) + patchMsg.Writer().Write(patchBin) + p.SendMessage(patchMsg) + } } func (l *LbsLobby) Exit(userID string) { @@ -593,6 +609,33 @@ func (l *LbsLobby) Update() { l.checkRoomBattleStart() } +func (l *LbsLobby) makePatchList() *proto.GamePatchList { + sp := strings.Split(strings.TrimSpace(l.LobbySetting.PatchNames), ",") + if len(sp) == 0 { + return nil + } + + patchList := new(proto.GamePatchList) + + for _, name := range sp { + mPatch, err := getDB().GetPatch(l.Platform, l.GameDisk, name) + if err != nil { + logger.Warn("failed to load patch", zap.String("name", name), zap.Error(err)) + continue + } + + gamePatch, err := convertGamePatch(mPatch) + if err != nil { + logger.Warn("failed to convert patch", zap.String("name", name), zap.Error(err)) + continue + } + + patchList.Patches = append(patchList.Patches, gamePatch) + } + + return patchList +} + func (l *LbsLobby) checkLobbyBattleStart(force bool) { if !(force || l.canStartBattle()) { return @@ -669,6 +712,16 @@ func (l *LbsLobby) checkLobbyBattleStart(force bool) { } } + patchList := l.makePatchList() + logger.Info("patchList", zap.Any("patchList", patchList)) + patchBin, err := pb.Marshal(patchList) + if err != nil { + logger.Error("pb.Marshal patch", zap.Error(err)) + return + } + patchMsg := NewServerNotice(lbsGamePatch) + patchMsg.Writer().Write(patchBin) + sharedData.ShareMcsGame(&McsGame{ BattleCode: b.BattleCode, Rule: *b.Rule, @@ -676,6 +729,7 @@ func (l *LbsLobby) checkLobbyBattleStart(force bool) { UpdatedAt: time.Now(), State: McsGameStateCreated, McsAddr: mcsAddr, + PatchList: patchList, }) for _, q := range participants { @@ -697,6 +751,7 @@ func (l *LbsLobby) checkLobbyBattleStart(force bool) { State: McsUserStateCreated, }) NotifyReadyBattle(q) + q.SendMessage(patchMsg) } if mcsPeer != nil { @@ -830,6 +885,15 @@ func (l *LbsLobby) checkRoomBattleStart() { } } + patchList := l.makePatchList() + patchBin, err := pb.Marshal(patchList) + if err != nil { + logger.Error("pb.Marshal patch", zap.Error(err)) + return + } + patchMsg := NewServerNotice(lbsGamePatch) + patchMsg.Writer().Write(patchBin) + sharedData.ShareMcsGame(&McsGame{ BattleCode: b.BattleCode, Rule: *b.Rule, @@ -837,6 +901,7 @@ func (l *LbsLobby) checkRoomBattleStart() { UpdatedAt: time.Now(), State: McsGameStateCreated, McsAddr: mcsAddr, + PatchList: patchList, }) for _, q := range participants { diff --git a/gdxsv/lbs_message.string.go b/gdxsv/lbs_message.string.go index 2de6a88..21cdbcd 100644 --- a/gdxsv/lbs_message.string.go +++ b/gdxsv/lbs_message.string.go @@ -101,9 +101,10 @@ func _() { _ = x[lbsMatchingCancel-24581] _ = x[lbsExtSyncSharedData-39168] _ = x[lbsPlatformInfo-39248] + _ = x[lbsGamePatch-39264] } -const _CmdID_name = "lbsLineChecklbsLogoutlbsShutDownlbsVSUserLostlbsMatchingCancellbsConnectionIDlbsAskConnectionIDlbsWarningMessagelbsLoginTypelbsUserHandlelbsUserRegistlbsUserDecidelbsAskPlatformCodelbsAskCountryCodelbsAskGameCodelbsAskGameVersionlbsLoginOklbsAskBattleResultlbsUserInfo1lbsUserInfo2lbsUserInfo3lbsUserInfo4lbsUserInfo5lbsUserInfo6lbsUserInfo7lbsUserInfo8lbsUserInfo9lbsEncodeStartlbsStartLobbylbsAskKDDIChargeslbsPostGameParameterlbsRankRankinglbsWinLoselbsDeviceDatalbsServerMoneylbsPlazaMaxlbsPlazaTitlelbsPlazaJoinlbsPlazaStatuslbsPlazaEntrylbsGoToToplbsPlazaExplainlbsLobbyJoinlbsLobbyEntrylbsPlazaExitlbsRoomMaxlbsRoomTitlelbsRoomStatuslbsRoomEntrylbsRoomCreatelbsLobbyExitlbsLobbyMatchingEntrylbsLobbyMatchingJoinlbsLobbyRemovelbsRoomExitlbsRoomLeaverlbsRoomCommerlbsMatchingEntrylbsRoomRemovelbsWaitJoinlbsRoomUserRejectlbsPutRoomNamelbsEndRoomCreatelbsPostChatMessagelbsChatMessagelbsUserSitelbsSendMaillbsRecvMaillbsManagerMessagelbsAskNewsTaglbsNewsTextlbsInvitationTaglbsRegulationHeaderlbsRegulationTextlbsRegulationFooterlbsTopRankingTaglbsTopRankingSuulbsTopRankinglbsAskPatchDatalbsPatchHeaderlbsPatchData6863lbsCalcDownloadChecksumlbsPatchPinglbsReadyBattlelbsAskMatchingJoinlbsAskPlayerSidelbsAskPlayerInfolbsAskRuleDatalbsAskBattleCodelbsAskMcsAddresslbsAskMcsVersionlbsExtSyncSharedDatalbsPlatformInfo" +const _CmdID_name = "lbsLineChecklbsLogoutlbsShutDownlbsVSUserLostlbsMatchingCancellbsConnectionIDlbsAskConnectionIDlbsWarningMessagelbsLoginTypelbsUserHandlelbsUserRegistlbsUserDecidelbsAskPlatformCodelbsAskCountryCodelbsAskGameCodelbsAskGameVersionlbsLoginOklbsAskBattleResultlbsUserInfo1lbsUserInfo2lbsUserInfo3lbsUserInfo4lbsUserInfo5lbsUserInfo6lbsUserInfo7lbsUserInfo8lbsUserInfo9lbsEncodeStartlbsStartLobbylbsAskKDDIChargeslbsPostGameParameterlbsRankRankinglbsWinLoselbsDeviceDatalbsServerMoneylbsPlazaMaxlbsPlazaTitlelbsPlazaJoinlbsPlazaStatuslbsPlazaEntrylbsGoToToplbsPlazaExplainlbsLobbyJoinlbsLobbyEntrylbsPlazaExitlbsRoomMaxlbsRoomTitlelbsRoomStatuslbsRoomEntrylbsRoomCreatelbsLobbyExitlbsLobbyMatchingEntrylbsLobbyMatchingJoinlbsLobbyRemovelbsRoomExitlbsRoomLeaverlbsRoomCommerlbsMatchingEntrylbsRoomRemovelbsWaitJoinlbsRoomUserRejectlbsPutRoomNamelbsEndRoomCreatelbsPostChatMessagelbsChatMessagelbsUserSitelbsSendMaillbsRecvMaillbsManagerMessagelbsAskNewsTaglbsNewsTextlbsInvitationTaglbsRegulationHeaderlbsRegulationTextlbsRegulationFooterlbsTopRankingTaglbsTopRankingSuulbsTopRankinglbsAskPatchDatalbsPatchHeaderlbsPatchData6863lbsCalcDownloadChecksumlbsPatchPinglbsReadyBattlelbsAskMatchingJoinlbsAskPlayerSidelbsAskPlayerInfolbsAskRuleDatalbsAskBattleCodelbsAskMcsAddresslbsAskMcsVersionlbsExtSyncSharedDatalbsPlatformInfolbsGamePatch" var _CmdID_map = map[CmdID]string{ 24577: _CmdID_name[0:12], @@ -199,6 +200,7 @@ var _CmdID_map = map[CmdID]string{ 26903: _CmdID_name[1268:1284], 39168: _CmdID_name[1284:1304], 39248: _CmdID_name[1304:1319], + 39264: _CmdID_name[1319:1331], } func (i CmdID) String() string { diff --git a/gdxsv/main.go b/gdxsv/main.go index 7b83dbf..67a0396 100644 --- a/gdxsv/main.go +++ b/gdxsv/main.go @@ -11,6 +11,7 @@ import ( "log" "math/rand" "net/http" + _ "net/http/pprof" "os" "os/signal" "runtime" @@ -31,6 +32,9 @@ var ( // Minimum required flycast version. requiredFlycastVersion = "v0.7.0" + + // New feature installed version. + novelFlycastVersion = "v1.0.5" ) var ( diff --git a/gdxsv/main_test.go b/gdxsv/main_test.go index 2ebc0a2..313cc8a 100644 --- a/gdxsv/main_test.go +++ b/gdxsv/main_test.go @@ -55,6 +55,13 @@ func TestMain(m *testing.M) { }) mustInsertMRule(MRule{ID: "dummy"}) mustInsertMString("dummy", "dummy string") + mustInsertMPatch(MPatch{ + Platform: "emu-x86/64", + Disk: "dc2", + Name: "dummy-patch", + WriteOnce: true, + Codes: "1, 8, 0c391d97, 1, 0", + }) os.Exit(m.Run()) } diff --git a/gdxsv/mcs.go b/gdxsv/mcs.go index 07cab79..b677783 100644 --- a/gdxsv/mcs.go +++ b/gdxsv/mcs.go @@ -287,11 +287,18 @@ func (mcs *Mcs) Join(p McsPeer, sessionID string) *McsRoom { mcs.mtx.Lock() mcs.updated = time.Now() room := mcs.rooms[user.BattleCode] + created := false if room == nil { room = newMcsRoom(mcs, game) mcs.rooms[user.BattleCode] = room + created = true } mcs.mtx.Unlock() + + if created { + logger.Info("new McsRoom", zap.String("battle_code", user.BattleCode), zap.Any("game", game)) + } + room.Join(p, user) sharedData.UpdateMcsUserState(sessionID, McsUserStateJoined) diff --git a/gdxsv/mcs_room.go b/gdxsv/mcs_room.go index 457ac72..f4d8652 100644 --- a/gdxsv/mcs_room.go +++ b/gdxsv/mcs_room.go @@ -23,18 +23,20 @@ type McsRoom struct { } func newMcsRoom(mcs *Mcs, gameInfo *McsGame) *McsRoom { - return &McsRoom{ + room := &McsRoom{ mcs: mcs, game: gameInfo, battleLog: &proto.BattleLogFile{ - LogFileVersion: 20201212, + LogFileVersion: 20210702, GameDisk: gameInfo.GameDisk, GdxsvVersion: gdxsvVersion, BattleCode: gameInfo.BattleCode, RuleBin: SerializeRule(&gameInfo.Rule), + Patches: gameInfo.PatchList.GetPatches(), StartAt: time.Now().UnixNano(), }, } + return room } func (r *McsRoom) PeerCount() int { diff --git a/gdxsv/mcs_udp.go b/gdxsv/mcs_udp.go index 02afef6..c9d7c40 100644 --- a/gdxsv/mcs_udp.go +++ b/gdxsv/mcs_udp.go @@ -283,6 +283,7 @@ func (u *McsUDPPeer) Serve(mcs *Mcs) { var err error pbBuf, err = pbm.MarshalAppend(pbBuf[:0], pkt) proto.PutPacket(pkt) + if err != nil { u.logger.Error("Marshal error", zap.Error(err)) u.SetCloseReason("sv_marshal_error") diff --git a/gdxsv/patch.go b/gdxsv/patch.go new file mode 100644 index 0000000..6517938 --- /dev/null +++ b/gdxsv/patch.go @@ -0,0 +1,74 @@ +package main + +import ( + "bufio" + "fmt" + "gdxsv/gdxsv/proto" + "strconv" + "strings" +) + +func convertGamePatch(patch *MPatch) (*proto.GamePatch, error) { + p := &proto.GamePatch{ + WriteOnce: patch.WriteOnce, + Name: patch.Name, + GameDisk: patch.Disk, + } + + sc := bufio.NewScanner(strings.NewReader(patch.Codes)) + for sc.Scan() { + if sc.Err() != nil { + return nil, sc.Err() + } + + line := strings.TrimSpace(sc.Text()) + + if strings.HasPrefix(line, "#") { + // comment line + continue + } + + sp := strings.Split(line, ",") + if len(sp) == 0 { + continue + } + + if 4 <= len(sp) { + // csv: size, addr, original, changed + + code := new(proto.GamePatchCode) + if v, err := strconv.ParseInt(strings.TrimSpace(sp[0]), 10, 32); err != nil { + return nil, err + } else { + if v == 8 || v == 16 || v == 32 { + code.Size = int32(v) + } else { + return nil, fmt.Errorf("invalid size") + } + } + + sp[1] = strings.TrimPrefix(strings.TrimSpace(sp[1]), "0x") + if v, err := strconv.ParseUint(sp[1], 16, 32); err != nil { + return nil, err + } else { + code.Address = uint32(v) + } + + if v, err := strconv.ParseUint(strings.TrimSpace(sp[2]), 0, 32); err != nil { + return nil, err + } else { + code.Original = uint32(v) + } + + if v, err := strconv.ParseUint(strings.TrimSpace(sp[3]), 0, 32); err != nil { + return nil, err + } else { + code.Changed = uint32(v) + } + + p.Codes = append(p.Codes, code) + } + } + + return p, nil +} diff --git a/gdxsv/patch_test.go b/gdxsv/patch_test.go new file mode 100644 index 0000000..51a7ac7 --- /dev/null +++ b/gdxsv/patch_test.go @@ -0,0 +1,66 @@ +package main + +import ( + "gdxsv/gdxsv/proto" + "reflect" + "testing" +) + +func Test_convertGamePatch(t *testing.T) { + type args struct { + patch *MPatch + } + tests := []struct { + name string + args args + want *proto.GamePatch + wantErr bool + }{ + { + name: "simple", + args: args{patch: &MPatch{Disk: GameDiskDC2, Name: "simple", Codes: "8,0,0,0\n32,0xffffffff,1,2"}}, + want: &proto.GamePatch{GameDisk: GameDiskDC2, Name: "simple", + Codes: []*proto.GamePatchCode{ + {Size: 8, Address: 0, Original: 0, Changed: 0}, + {Size: 32, Address: 0xffffffff, Original: 1, Changed: 2}, + }, + }, + }, + { + name: "complex", + args: args{patch: &MPatch{Disk: GameDiskDC2, Name: "complex", WriteOnce: true, + Codes: ` # comment + 32, ffffffff, 123, 0x0c500000, + 16, 0x8c500000, 0x0000, 0x911f + 16, 0x8c500002, 0, 0x314c + + 16, 0x8c500004, 0x0000, 0x8412 + 16, 0x8c500006, 10, 0x630c, + +`, + }}, + // codes:{size:32 address:4294967295 original:123 changed:206569472} codes:{size:16 address:2354053120 changed:37151} codes:{size:16 address:2354053122 changed:12620} codes:{size:16 address:2354053124 changed:33810} codes:{size:16 address:2354053126 changed:25356}, + want: &proto.GamePatch{GameDisk: GameDiskDC2, Name: "complex", WriteOnce: true, + Codes: []*proto.GamePatchCode{ + {Size: 32, Address: 0xffffffff, Original: 123, Changed: 0x0c500000}, + {Size: 16, Address: 0x8c500000, Original: 0, Changed: 0x911f}, + {Size: 16, Address: 0x8c500002, Original: 0, Changed: 0x314c}, + {Size: 16, Address: 0x8c500004, Original: 0, Changed: 0x8412}, + {Size: 16, Address: 0x8c500006, Original: 10, Changed: 0x630c}, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := convertGamePatch(tt.args.patch) + if (err != nil) != tt.wantErr { + t.Errorf("convertGamePatch() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("convertGamePatch() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/gdxsv/proto/battlelog.pb.go b/gdxsv/proto/battlelog.pb.go index 5ea2339..44a9644 100644 --- a/gdxsv/proto/battlelog.pb.go +++ b/gdxsv/proto/battlelog.pb.go @@ -20,6 +20,195 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type GamePatch struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GameDisk string `protobuf:"bytes,1,opt,name=game_disk,json=gameDisk,proto3" json:"game_disk,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + WriteOnce bool `protobuf:"varint,4,opt,name=write_once,json=writeOnce,proto3" json:"write_once,omitempty"` + Codes []*GamePatchCode `protobuf:"bytes,10,rep,name=codes,proto3" json:"codes,omitempty"` +} + +func (x *GamePatch) Reset() { + *x = GamePatch{} + if protoimpl.UnsafeEnabled { + mi := &file_battlelog_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GamePatch) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GamePatch) ProtoMessage() {} + +func (x *GamePatch) ProtoReflect() protoreflect.Message { + mi := &file_battlelog_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GamePatch.ProtoReflect.Descriptor instead. +func (*GamePatch) Descriptor() ([]byte, []int) { + return file_battlelog_proto_rawDescGZIP(), []int{0} +} + +func (x *GamePatch) GetGameDisk() string { + if x != nil { + return x.GameDisk + } + return "" +} + +func (x *GamePatch) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *GamePatch) GetWriteOnce() bool { + if x != nil { + return x.WriteOnce + } + return false +} + +func (x *GamePatch) GetCodes() []*GamePatchCode { + if x != nil { + return x.Codes + } + return nil +} + +type GamePatchCode struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Size int32 `protobuf:"varint,1,opt,name=size,proto3" json:"size,omitempty"` + Address uint32 `protobuf:"varint,2,opt,name=address,proto3" json:"address,omitempty"` + Original uint32 `protobuf:"varint,3,opt,name=original,proto3" json:"original,omitempty"` + Changed uint32 `protobuf:"varint,4,opt,name=changed,proto3" json:"changed,omitempty"` +} + +func (x *GamePatchCode) Reset() { + *x = GamePatchCode{} + if protoimpl.UnsafeEnabled { + mi := &file_battlelog_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GamePatchCode) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GamePatchCode) ProtoMessage() {} + +func (x *GamePatchCode) ProtoReflect() protoreflect.Message { + mi := &file_battlelog_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GamePatchCode.ProtoReflect.Descriptor instead. +func (*GamePatchCode) Descriptor() ([]byte, []int) { + return file_battlelog_proto_rawDescGZIP(), []int{1} +} + +func (x *GamePatchCode) GetSize() int32 { + if x != nil { + return x.Size + } + return 0 +} + +func (x *GamePatchCode) GetAddress() uint32 { + if x != nil { + return x.Address + } + return 0 +} + +func (x *GamePatchCode) GetOriginal() uint32 { + if x != nil { + return x.Original + } + return 0 +} + +func (x *GamePatchCode) GetChanged() uint32 { + if x != nil { + return x.Changed + } + return 0 +} + +type GamePatchList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Patches []*GamePatch `protobuf:"bytes,1,rep,name=patches,proto3" json:"patches,omitempty"` +} + +func (x *GamePatchList) Reset() { + *x = GamePatchList{} + if protoimpl.UnsafeEnabled { + mi := &file_battlelog_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GamePatchList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GamePatchList) ProtoMessage() {} + +func (x *GamePatchList) ProtoReflect() protoreflect.Message { + mi := &file_battlelog_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GamePatchList.ProtoReflect.Descriptor instead. +func (*GamePatchList) Descriptor() ([]byte, []int) { + return file_battlelog_proto_rawDescGZIP(), []int{2} +} + +func (x *GamePatchList) GetPatches() []*GamePatch { + if x != nil { + return x.Patches + } + return nil +} + type BattleLogUser struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -38,7 +227,7 @@ type BattleLogUser struct { func (x *BattleLogUser) Reset() { *x = BattleLogUser{} if protoimpl.UnsafeEnabled { - mi := &file_battlelog_proto_msgTypes[0] + mi := &file_battlelog_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -51,7 +240,7 @@ func (x *BattleLogUser) String() string { func (*BattleLogUser) ProtoMessage() {} func (x *BattleLogUser) ProtoReflect() protoreflect.Message { - mi := &file_battlelog_proto_msgTypes[0] + mi := &file_battlelog_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -64,7 +253,7 @@ func (x *BattleLogUser) ProtoReflect() protoreflect.Message { // Deprecated: Use BattleLogUser.ProtoReflect.Descriptor instead. func (*BattleLogUser) Descriptor() ([]byte, []int) { - return file_battlelog_proto_rawDescGZIP(), []int{0} + return file_battlelog_proto_rawDescGZIP(), []int{3} } func (x *BattleLogUser) GetUserId() string { @@ -137,7 +326,7 @@ type BattleLogMessage struct { func (x *BattleLogMessage) Reset() { *x = BattleLogMessage{} if protoimpl.UnsafeEnabled { - mi := &file_battlelog_proto_msgTypes[1] + mi := &file_battlelog_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -150,7 +339,7 @@ func (x *BattleLogMessage) String() string { func (*BattleLogMessage) ProtoMessage() {} func (x *BattleLogMessage) ProtoReflect() protoreflect.Message { - mi := &file_battlelog_proto_msgTypes[1] + mi := &file_battlelog_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -163,7 +352,7 @@ func (x *BattleLogMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use BattleLogMessage.ProtoReflect.Descriptor instead. func (*BattleLogMessage) Descriptor() ([]byte, []int) { - return file_battlelog_proto_rawDescGZIP(), []int{1} + return file_battlelog_proto_rawDescGZIP(), []int{4} } func (x *BattleLogMessage) GetUserId() string { @@ -203,6 +392,7 @@ type BattleLogFile struct { GdxsvVersion string `protobuf:"bytes,2,opt,name=gdxsv_version,json=gdxsvVersion,proto3" json:"gdxsv_version,omitempty"` BattleCode string `protobuf:"bytes,3,opt,name=battle_code,json=battleCode,proto3" json:"battle_code,omitempty"` LogFileVersion int32 `protobuf:"varint,4,opt,name=log_file_version,json=logFileVersion,proto3" json:"log_file_version,omitempty"` + Patches []*GamePatch `protobuf:"bytes,7,rep,name=patches,proto3" json:"patches,omitempty"` RuleBin []byte `protobuf:"bytes,10,opt,name=rule_bin,json=ruleBin,proto3" json:"rule_bin,omitempty"` Users []*BattleLogUser `protobuf:"bytes,11,rep,name=users,proto3" json:"users,omitempty"` BattleData []*BattleLogMessage `protobuf:"bytes,12,rep,name=battle_data,json=battleData,proto3" json:"battle_data,omitempty"` @@ -213,7 +403,7 @@ type BattleLogFile struct { func (x *BattleLogFile) Reset() { *x = BattleLogFile{} if protoimpl.UnsafeEnabled { - mi := &file_battlelog_proto_msgTypes[2] + mi := &file_battlelog_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -226,7 +416,7 @@ func (x *BattleLogFile) String() string { func (*BattleLogFile) ProtoMessage() {} func (x *BattleLogFile) ProtoReflect() protoreflect.Message { - mi := &file_battlelog_proto_msgTypes[2] + mi := &file_battlelog_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -239,7 +429,7 @@ func (x *BattleLogFile) ProtoReflect() protoreflect.Message { // Deprecated: Use BattleLogFile.ProtoReflect.Descriptor instead. func (*BattleLogFile) Descriptor() ([]byte, []int) { - return file_battlelog_proto_rawDescGZIP(), []int{2} + return file_battlelog_proto_rawDescGZIP(), []int{5} } func (x *BattleLogFile) GetGameDisk() string { @@ -270,6 +460,13 @@ func (x *BattleLogFile) GetLogFileVersion() int32 { return 0 } +func (x *BattleLogFile) GetPatches() []*GamePatch { + if x != nil { + return x.Patches + } + return nil +} + func (x *BattleLogFile) GetRuleBin() []byte { if x != nil { return x.RuleBin @@ -309,54 +506,75 @@ var File_battlelog_proto protoreflect.FileDescriptor var file_battlelog_proto_rawDesc = []byte{ 0x0a, 0x0f, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xfe, 0x01, 0x0a, 0x0d, 0x42, 0x61, 0x74, - 0x74, 0x6c, 0x65, 0x4c, 0x6f, 0x67, 0x55, 0x73, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x69, 0x6c, 0x6f, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x69, 0x6c, 0x6f, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x1d, 0x0a, 0x0a, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x09, 0x67, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x21, - 0x0a, 0x0c, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x77, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x77, 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, - 0x0a, 0x0a, 0x6c, 0x6f, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x09, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, - 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x6f, 0x0a, 0x10, 0x42, 0x61, 0x74, - 0x74, 0x6c, 0x65, 0x4c, 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x17, 0x0a, - 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x65, - 0x71, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x73, 0x65, 0x71, 0x12, 0x1c, 0x0a, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xcf, 0x02, 0x0a, 0x0d, 0x42, - 0x61, 0x74, 0x74, 0x6c, 0x65, 0x4c, 0x6f, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, - 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x67, 0x61, 0x6d, 0x65, 0x44, 0x69, 0x73, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x64, 0x78, - 0x73, 0x76, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x67, 0x64, 0x78, 0x73, 0x76, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, - 0x0a, 0x0b, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, - 0x28, 0x0a, 0x10, 0x6c, 0x6f, 0x67, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6c, 0x6f, 0x67, 0x46, 0x69, - 0x6c, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x75, 0x6c, - 0x65, 0x5f, 0x62, 0x69, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x72, 0x75, 0x6c, - 0x65, 0x42, 0x69, 0x6e, 0x12, 0x2a, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x0b, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x61, 0x74, 0x74, - 0x6c, 0x65, 0x4c, 0x6f, 0x67, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, - 0x12, 0x38, 0x0a, 0x0b, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x61, - 0x74, 0x74, 0x6c, 0x65, 0x4c, 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0a, - 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x5f, 0x61, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x41, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x65, 0x6e, 0x64, 0x5f, 0x61, 0x74, 0x18, - 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x65, 0x6e, 0x64, 0x41, 0x74, 0x42, 0x26, 0x5a, 0x24, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x6e, 0x61, 0x64, 0x61, - 0x2d, 0x73, 0x2f, 0x67, 0x64, 0x78, 0x73, 0x76, 0x2f, 0x67, 0x64, 0x78, 0x73, 0x76, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x87, 0x01, 0x0a, 0x09, 0x47, 0x61, 0x6d, + 0x65, 0x50, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x64, + 0x69, 0x73, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x61, 0x6d, 0x65, 0x44, + 0x69, 0x73, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x77, 0x72, 0x69, 0x74, 0x65, + 0x5f, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x77, 0x72, 0x69, + 0x74, 0x65, 0x4f, 0x6e, 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x18, + 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x61, + 0x6d, 0x65, 0x50, 0x61, 0x74, 0x63, 0x68, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x63, 0x6f, 0x64, + 0x65, 0x73, 0x22, 0x73, 0x0a, 0x0d, 0x47, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x74, 0x63, 0x68, 0x43, + 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x18, 0x0a, + 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x3b, 0x0a, 0x0d, 0x47, 0x61, 0x6d, 0x65, 0x50, + 0x61, 0x74, 0x63, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x63, + 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x47, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x70, 0x61, 0x74, + 0x63, 0x68, 0x65, 0x73, 0x22, 0xfe, 0x01, 0x0a, 0x0d, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x4c, + 0x6f, 0x67, 0x55, 0x73, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, + 0x70, 0x69, 0x6c, 0x6f, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x70, 0x69, 0x6c, 0x6f, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x67, + 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x09, 0x67, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x61, + 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x0b, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, + 0x09, 0x77, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x08, 0x77, 0x69, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, + 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, + 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x6f, 0x0a, 0x10, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x4c, + 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x65, 0x71, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x03, 0x73, 0x65, 0x71, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xfb, 0x02, 0x0a, 0x0d, 0x42, 0x61, 0x74, 0x74, 0x6c, + 0x65, 0x4c, 0x6f, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x6d, 0x65, + 0x5f, 0x64, 0x69, 0x73, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x61, 0x6d, + 0x65, 0x44, 0x69, 0x73, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x64, 0x78, 0x73, 0x76, 0x5f, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x64, + 0x78, 0x73, 0x76, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x61, + 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x6c, + 0x6f, 0x67, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6c, 0x6f, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, + 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, + 0x61, 0x6d, 0x65, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, + 0x73, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x62, 0x69, 0x6e, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x42, 0x69, 0x6e, 0x12, 0x2a, 0x0a, 0x05, + 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x4c, 0x6f, 0x67, 0x55, 0x73, 0x65, + 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x38, 0x0a, 0x0b, 0x62, 0x61, 0x74, 0x74, + 0x6c, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x4c, 0x6f, 0x67, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0a, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x61, + 0x74, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x61, 0x74, 0x18, 0x14, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x41, 0x74, 0x12, 0x15, 0x0a, + 0x06, 0x65, 0x6e, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x65, + 0x6e, 0x64, 0x41, 0x74, 0x42, 0x0d, 0x5a, 0x0b, 0x67, 0x64, 0x78, 0x73, 0x76, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -371,20 +589,26 @@ func file_battlelog_proto_rawDescGZIP() []byte { return file_battlelog_proto_rawDescData } -var file_battlelog_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_battlelog_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_battlelog_proto_goTypes = []interface{}{ - (*BattleLogUser)(nil), // 0: proto.BattleLogUser - (*BattleLogMessage)(nil), // 1: proto.BattleLogMessage - (*BattleLogFile)(nil), // 2: proto.BattleLogFile + (*GamePatch)(nil), // 0: proto.GamePatch + (*GamePatchCode)(nil), // 1: proto.GamePatchCode + (*GamePatchList)(nil), // 2: proto.GamePatchList + (*BattleLogUser)(nil), // 3: proto.BattleLogUser + (*BattleLogMessage)(nil), // 4: proto.BattleLogMessage + (*BattleLogFile)(nil), // 5: proto.BattleLogFile } var file_battlelog_proto_depIdxs = []int32{ - 0, // 0: proto.BattleLogFile.users:type_name -> proto.BattleLogUser - 1, // 1: proto.BattleLogFile.battle_data:type_name -> proto.BattleLogMessage - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 1, // 0: proto.GamePatch.codes:type_name -> proto.GamePatchCode + 0, // 1: proto.GamePatchList.patches:type_name -> proto.GamePatch + 0, // 2: proto.BattleLogFile.patches:type_name -> proto.GamePatch + 3, // 3: proto.BattleLogFile.users:type_name -> proto.BattleLogUser + 4, // 4: proto.BattleLogFile.battle_data:type_name -> proto.BattleLogMessage + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_battlelog_proto_init() } @@ -394,7 +618,7 @@ func file_battlelog_proto_init() { } if !protoimpl.UnsafeEnabled { file_battlelog_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BattleLogUser); i { + switch v := v.(*GamePatch); i { case 0: return &v.state case 1: @@ -406,7 +630,7 @@ func file_battlelog_proto_init() { } } file_battlelog_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BattleLogMessage); i { + switch v := v.(*GamePatchCode); i { case 0: return &v.state case 1: @@ -418,6 +642,42 @@ func file_battlelog_proto_init() { } } file_battlelog_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GamePatchList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_battlelog_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BattleLogUser); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_battlelog_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BattleLogMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_battlelog_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BattleLogFile); i { case 0: return &v.state @@ -436,7 +696,7 @@ func file_battlelog_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_battlelog_proto_rawDesc, NumEnums: 0, - NumMessages: 3, + NumMessages: 6, NumExtensions: 0, NumServices: 0, }, diff --git a/gdxsv/proto/battlelog.proto b/gdxsv/proto/battlelog.proto index 961f369..8a40a3e 100644 --- a/gdxsv/proto/battlelog.proto +++ b/gdxsv/proto/battlelog.proto @@ -3,6 +3,23 @@ syntax = "proto3"; package proto; option go_package = "gdxsv/proto"; +message GamePatch { + string game_disk = 1; + string name = 2; + bool write_once = 4; + repeated GamePatchCode codes = 10; +} + +message GamePatchCode { + int32 size = 1; + uint32 address = 2; + uint32 original = 3; + uint32 changed = 4; +} + +message GamePatchList { + repeated GamePatch patches = 1; +} message BattleLogUser { string user_id = 1; @@ -28,6 +45,7 @@ message BattleLogFile { string gdxsv_version = 2; string battle_code = 3; int32 log_file_version = 4; + repeated GamePatch patches = 7; bytes rule_bin = 10; repeated BattleLogUser users = 11; diff --git a/gdxsv/proto/packet.pb.go b/gdxsv/proto/packet.pb.go index 669daf1..09e5866 100644 --- a/gdxsv/proto/packet.pb.go +++ b/gdxsv/proto/packet.pb.go @@ -539,10 +539,8 @@ var file_packet_proto_rawDesc = []byte{ 0x6f, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x6f, 0x6e, 0x67, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x10, 0x04, 0x12, 0x07, 0x0a, 0x03, 0x46, 0x69, 0x6e, - 0x10, 0x05, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x69, 0x6e, 0x61, 0x64, 0x61, 0x2d, 0x73, 0x2f, 0x67, 0x64, 0x78, 0x73, 0x76, 0x2f, 0x67, - 0x64, 0x78, 0x73, 0x76, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x10, 0x05, 0x42, 0x0d, 0x5a, 0x0b, 0x67, 0x64, 0x78, 0x73, 0x76, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/gdxsv/shareddata.go b/gdxsv/shareddata.go index cf10905..9ea6fbd 100644 --- a/gdxsv/shareddata.go +++ b/gdxsv/shareddata.go @@ -4,6 +4,7 @@ import ( "bytes" "compress/gzip" "encoding/json" + "gdxsv/gdxsv/proto" "go.uber.org/zap" "sync" "time" @@ -52,10 +53,11 @@ type McsUser struct { } type McsGame struct { - BattleCode string `json:"battle_code,omitempty"` - McsAddr string `json:"mcs_addr,omitempty"` - GameDisk string `json:"game_disk"` - Rule Rule `json:"rule,omitempty"` + BattleCode string `json:"battle_code,omitempty"` + McsAddr string `json:"mcs_addr,omitempty"` + GameDisk string `json:"game_disk"` + Rule Rule `json:"rule,omitempty"` + PatchList *proto.GamePatchList `json:"patch_list,omitempty"` State int `json:"state,omitempty"` UpdatedAt time.Time `json:"updated_at,omitempty"` diff --git a/gdxsv/shareddata_test.go b/gdxsv/shareddata_test.go index 0f6c5e4..6a71a7d 100644 --- a/gdxsv/shareddata_test.go +++ b/gdxsv/shareddata_test.go @@ -1,6 +1,7 @@ package main import ( + "gdxsv/gdxsv/proto" "reflect" "testing" "time" @@ -29,6 +30,15 @@ func TestSharedData_Sync(t *testing.T) { Rule: DefaultRule, State: McsGameStateCreated, UpdatedAt: time.Unix(0, 0), + PatchList: &proto.GamePatchList{ + Patches: []*proto.GamePatch{ + { + GameDisk: GameDiskDC2, + Name: "allow-soft-reset", + Codes: []*proto.GamePatchCode{{Size: 8, Address: 0x0c391d97, Original: 1, Changed: 0}}, + }, + }, + }, }) sd1.ShareMcsUser(&McsUser{