Merge branch 'master' of https://github.com/ursoft/zwift-offline into ursoft-master

This commit is contained in:
oldnapalm
2022-03-11 18:10:49 -03:00
34 changed files with 2650 additions and 1089 deletions

View File

@@ -301,7 +301,32 @@ To enable support for multiple users perform the steps below. zoffline's previou
</details>
### Step 7 [OPTIONAL]: Install Zwift Companion App
Create a ``server-ip.txt`` file in the ``storage`` directory containing the IP address of the PC running zoffline.
<details><summary>Android (non-rooted device)</summary>
* Install apk-mitm (https://github.com/shroudedcode/apk-mitm)
* Copy the file ``ssl/cert-zwift-com.pem`` in this repo and the Zwift Companion apk (e.g. ``zca.apk``) to a known location
* Open Command Prompt, cd to that location and run
* ``apk-mitm --certificate cert-zwift-com.pem zca.apk``
* Copy ``zca-patched.apk`` to your phone and install it
* Download "#1 HOST CHANGER - BEST FOR GAMING" from Google Play ([link](https://play.google.com/store/apps/details?id=best.see.world.company))
* Create a ``hosts.txt`` file to use with the app (you could use a text editor app or create it online with an online tool such as [this](https://passwordsgenerator.net/text-editor/)). The file must look like this (replace ``<zoffline ip>`` with the IP address of the machine running zoffline):
```
<zoffline ip> us-or-rly101.zwift.com
<zoffline ip> secure.zwift.com
```
* Run "Host Changer", select created ``hosts.txt`` file and press the button
* Optionally, instead of using the "Host Changer" app, you can create a ``fake-dns.txt`` file in the ``storage`` directory and set the "DNS 1" of your phone Wi-Fi connection to the IP address of the PC running zoffline
* If running from source, install the required module with ``pip3 install dnspython``
* Note: If you know what you're doing and have a capable enough router you can adjust your router to alter these DNS records instead of using the "Host Changer" app or changing your phone DNS.
</details>
### Extra optional steps
<details><summary>Expand</summary>
* To obtain the official map schedule and update files from Zwift server: create a ``cdn-proxy.txt`` file in the ``storage`` directory. This can only work if you are running zoffline on a different machine than the Zwift client.

1
game_info.txt Normal file

File diff suppressed because one or more lines are too long

View File

@@ -156,7 +156,7 @@ def get_player_id(session, access_token):
},
)
profile = profile_pb2.Profile()
profile = profile_pb2.PlayerProfile()
profile.ParseFromString(response.content)
return profile.id

View File

@@ -1,34 +1,199 @@
syntax = "proto2";
message Activity {
import "profile.proto"; //enum ActivityPrivacyType, Sport
//All decompiled. TODO: uncomment all new fields and use in algo
enum NotableMomentTypeZCA {
NMTC_ACHIEVEMENT_UNLOCKED = 1;
NMTC_UNLOCKED_ITEM = 2;
NMTC_MISSION_COMPLETED = 3;
NMTC_FINISHED_CHALLENGE = 4;
NMTC_TOOK_ARCH_JERSEY = 5;
NMTC_NEW_PR = 6;
NMTC_MET_DAILY_TARGET = 7;
NMTC_GAINED_LEVEL = 8;
NMTC_COMPLETED_GOAL = 9;
NMTC_FINISHED_EVENT = 10;
NMTC_FINISHED_WORKOUT = 11;
NMTC_RIDE_ON = 12;
NMTC_TRAINING_PLAN_COMPLETED = 13;
}
enum NotableMomentTypeZG_idx {
NMTI_UNKNOWN = 0;
NMTI_NEW_PR = 1;
NMTI_GAINED_LEVEL = 2;
NMTI_TRAINING_PLAN_COMPLETE = 3;
NMTI_UNLOCKED_ITEM = 4;
NMTI_ACHIEVEMENT_UNLOCKED = 5;
NMTI_MISSION_COMPLETED = 6;
NMTI_COMPLETED_GOAL = 7;
NMTI_MET_DAILY_TARGET = 8;
NMTI_TOOK_ARCH_JERSEY = 9;
NMTI_FINISHED_CHALLENGE = 10;
NMTI_FINISHED_EVENT = 11;
NMTI_FINISHED_WORKOUT = 12;
NMTI_ACTIVITY_BESTS = 13;
NMTI_RIDEON = 14;
NMTI_RIDEON_INT = 15; //international
NMTI_QUIT_EVENT = 16;
NMTI_USED_POWERUP = 17;
NMTI_PASSED_TIMING_ARCH = 18;
NMTI_CREATED_GOAL = 19;
NMTI_JOINED_EVENT = 20;
NMTI_STARTED_WORKOUT = 21;
NMTI_STARTED_MISSION = 22;
NMTI_HOLIDAY_EVENT_COMPLETE = 23;
}
enum NotableMomentTypeZG {
NMT_NEW_PR = 0;
NMT_GAINED_LEVEL = 5;
NMT_TRAINING_PLAN_COMPLETE = 19;
NMT_UNLOCKED_ITEM = 4;
NMT_ACHIEVEMENT_UNLOCKED = 2;
NMT_MISSION_COMPLETED = 3;
NMT_COMPLETED_GOAL = 10;
NMT_MET_DAILY_TARGET = 1;
NMT_TOOK_ARCH_JERSEY = 8;
NMT_FINISHED_CHALLENGE = 17;
NMT_FINISHED_EVENT = 13;
NMT_FINISHED_WORKOUT = 15;
NMT_ACTIVITY_BESTS = 20;
NMT_RIDEON = 18;
NMT_RIDEON_INT = 22; //international
NMT_QUIT_EVENT = 12;
NMT_USED_POWERUP = 6;
NMT_PASSED_TIMING_ARCH = 7;
NMT_CREATED_GOAL = 9;
NMT_JOINED_EVENT = 11;
NMT_STARTED_WORKOUT = 14;
NMT_STARTED_MISSION = 16;
NMT_HOLIDAY_EVENT_COMPLETE = 21;
}
message NotableMoment {
optional uint64 activity_id = 1;
optional NotableMomentTypeZG type = 2;
optional uint32 priority = 3;
optional uint64 incidentTime = 4;
optional string aux1 = 5; // example: {\"achievementId\":35,\"name\":\"PAIRED\",\"description\":\"Paired a phone through Zwift Companion\"}
optional string aux2 = 6; // empty string
optional string largeImageUrl = 7;
}
message SocialInteraction {
optional uint64 player_id = 1;
optional uint32 timeDuration = 2;
optional float proximityTimeScore = 3;
optional string si_f4 = 4;
}
message ClubAttribution {
optional string name = 1;
optional float value = 2;
}
enum ProfileFollowStatus {
PFS_UNKNOWN = 1;
PFS_REQUESTS_TO_FOLLOW = 2;
PFS_IS_FOLLOWING = 3;
PFS_IS_BLOCKED = 4;
PFS_NO_RELATIONSHIP = 5;
PFS_SELF = 6;
PFS_HAS_BEEN_DECLINED = 7;
}
enum FitnessPrivacy {
UNSET = 0;
HIDE_SENSITIVE_DATA = 1;
SAME_AS_ACTIVITY = 2;
}
message ActivityFull { //where is primaryImageUrl, feedImageThumbnailUrl, activityRideOnCount, activityCommentCount, eventId, rideOnGiven
optional uint64 id = 1;
required uint64 player_id = 2;
required uint32 f3 = 3; /* world_id or player_type_id */
required uint64 course_id = 3;
required string name = 4;
optional uint32 f5 = 5;
optional uint32 f6 = 6;
optional string f5 = 5;
optional bool privateActivity = 6;
required string start_date = 7;
optional string end_date = 8;
optional float distance = 9; /* in meters */
optional float distanceInMeters = 9;
optional float avg_heart_rate = 10;
optional float max_heart_rate = 11;
optional float avg_watts = 12;
optional float max_watts = 13;
optional float avg_cadence = 14;
optional float max_cadence = 15;
optional float avg_speed = 16; /* in m/s */
optional float max_speed = 17; /* in m/s */
optional float avg_speed = 16; // in m/s
optional float max_speed = 17; // in m/s
optional float calories = 18;
optional float total_elevation = 19;
optional uint64 strava_upload_id = 20;
optional uint64 strava_activity_id = 21;
optional uint32 f23 = 23;
optional uint32 strava_upload_id = 20; //uint64 stored as int32
optional uint32 strava_activity_id = 21; //uint64 stored as int32
optional string f22 = 22;
optional uint32 f23 = 23; //empty; stored as int32; enum up to 5 - ProfileFollowStatus?
optional bytes fit = 24;
optional string fit_filename = 25;
optional uint32 f29 = 29;
optional uint64 subgroupId = 26;
optional uint64 workoutHash = 27;
optional float progressPercentage = 28;
optional Sport sport = 29;
repeated string act_f30 = 30;
optional string date = 31;
optional float act_f32 = 32;
optional string act_f33 = 33;
optional string act_f34 = 34;
repeated NotableMoment notables = 35;
repeated SocialInteraction socials = 36;
optional ActivityPrivacyType privacy = 37;
optional FitnessPrivacy fitness_privacy = 38;
optional string club_name = 39;
optional int64 movingTimeInMs = 40;
repeated ClubAttribution cas = 41;
}
message Activity { //field names pinned to db
optional uint64 id = 1;
required uint64 player_id = 2;
required uint64 f3 = 3; //-> rename to course_id
required string name = 4;
optional string f5 = 5;
optional bool f6 = 6;
required string start_date = 7;
optional string end_date = 8;
optional float distance = 9; // in meters
optional float avg_heart_rate = 10;
optional float max_heart_rate = 11;
optional float avg_watts = 12;
optional float max_watts = 13;
optional float avg_cadence = 14;
optional float max_cadence = 15;
optional float avg_speed = 16; // in m/s
optional float max_speed = 17; // in m/s
optional float calories = 18;
optional float total_elevation = 19;
optional uint32 strava_upload_id = 20; //uint64 stored as int32
optional uint32 strava_activity_id = 21; //uint64 stored as int32
//optional string f22 = 22;
optional uint32 f23 = 23; //empty; stored as int32; enum up to 5 - ProfileFollowStatus?
optional bytes fit = 24;
optional string fit_filename = 25;
//optional uint64 subgroupId = 26;
//optional uint64 workoutHash = 27;
//optional float progressPercentage = 28;
optional int64 f29 = 29; //-> Sport sport
//repeated string act_f30 = 30;
optional string date = 31;
/*optional float act_f32 = 32;
optional string act_f33 = 33;
optional string act_f34 = 34;
repeated NotableMoment notables = 35;
repeated SocialInteraction socials = 36;
optional ActivityPrivacyType privacy = 37;
optional FitnessPrivacy fitness_privacy = 38;
optional string club_name = 39;
optional int64 moving_time_ms = 40;
repeated ClubAttribution cas = 41;*/
}
message Activities {
message ActivityList {
repeated Activity activities = 1;
}
message ActivityListFull {
repeated ActivityFull activities = 1;
}

File diff suppressed because one or more lines are too long

View File

@@ -1,13 +1,17 @@
syntax = "proto2";
import "profile.proto"; //enums PlayerType and Sport
message Category {
message EventSubgroupProtobuf { //where is fieldLimit, signedUp, signupStatus, registered, registrationStatus, followeeEntrantCount
//totalEntrantCount, followeeSignedUpCount, totalSignedUpCount, followeeJoinedCount, totalJoinedCount, rulesSet, workoutHash, overrideMapPreferences
//qualificationRuleIds, accessValidationResult
required uint64 id = 1; // 2395269
optional string description = 2; // "3R True2 Steady Ride [2.0w/kg avg] (C)"
optional string f3 = 3; // ""
optional uint32 f5 = 5; // 154
optional uint32 f6 = 6; // 0
optional string f7 = 7; // "PT3600S"
optional uint32 rules_id = 8; // 320
optional string name = 2; // ex: "3R True2 Steady Ride [2.0w/kg avg] (C)"
optional string description = 3; // ex: "Welcome to our sociable early morning/evening social group ride."
optional uint32 evs_f4 = 4; // ""
optional uint32 evs_f5 = 5; // 154 and others
optional uint32 evs_f6 = 6; // 0
optional string scode = 7; // ex: "PT3600S"
optional uint64 rules_id = 8; // 320 and others
optional uint64 registrationStart = 9;
optional uint64 registrationStartWT = 10;
optional uint64 registrationEnd = 11;
@@ -18,58 +22,134 @@ message Category {
optional uint64 lineUpEndWT = 16;
optional uint64 eventSubgroupStart = 17;
optional uint64 eventSubgroupStartWT = 18;
optional uint32 f21 = 21; // 0
optional uint64 evs_f19 = 19;
optional uint64 evs_f20 = 20; //tag416
optional bool evs_f21 = 21; // false, tag424
required uint64 route_id = 22; // 3366225080
repeated uint32 leaders = 23; // or sweepers?
optional fixed32 f24 = 24;
optional uint32 laps = 25; // 0
optional uint32 startLocation = 29; // 13
optional uint32 label = 30; // 3
optional uint32 f31 = 31; // 1
optional fixed32 f32 = 32; // 1076258406
optional fixed32 f33 = 33; // 1078774989
optional uint32 duration = 34; // Duration of event in seconds
optional uint64 f36 = 36; // 493134166
optional uint32 f37 = 37; // 0
optional string audio = 39; // "https://cdn.zwift.com/AudioBroadcasts/wbrgrouprideaudiov4"
repeated uint32 sweepers = 41; // or leaders?
optional string f43 = 43;
optional uint32 f44 = 44; // 0
optional string tags = 45; // semi-colon delimited tags eg: "fenced;3r;created_ryan;communityevent;no_kick_mode;timestamp=1603911177622"
optional uint32 lateJoinInMinutes = 46;
optional uint32 map_id = 47; // 1
repeated uint64 invitedLeaders = 23; // tag440
optional float distanceInMeters = 24; // tag453
optional uint32 laps = 25; // tag456
// no 26-28
optional uint64 startLocation = 29; // 13, tag488 [>=6 -> 'bad start location'] valid values: 1..5 (0->1)
optional uint32 label = 30; // A:1, B:2, C:3, D:4, E:5 etc, tag496
optional uint32 paceType = 31; // 1 everywhere, tag504
optional float fromPaceValue = 32; // tag645
optional float toPaceValue = 33; // tag653
optional uint32 durationInSeconds = 34; // Duration of event in seconds, tag656
optional uint32 evs_f35 = 35; // tag664
optional uint64 jerseyHash = 36; // 493134166, tag672
optional bool evs_f37 = 37; // 0, tag680
optional uint32 evs_f38 = 38; // tag688
optional string auxiliaryUrl = 39; // "https://cdn.zwift.com/AudioBroadcasts/wbrgrouprideaudiov4", tag698
optional uint64 bikeHash = 40; // 4208139356, tag704
repeated uint64 invitedSweepers = 41; // tag712
optional uint64 evs_f42 = 42; // tag720
optional string customUrl = 43; // https://cdn.zwift.com/events/upload/workouts/CafeRide1.zwo, tag730
optional bool evs_f44 = 44; // false, tag736
optional string tags = 45; // tag746, semi-colon delimited tags eg: "fenced;3r;created_ryan;communityevent;no_kick_mode;timestamp=1603911177622"
optional uint32 lateJoinInMinutes = 46; //tag752
optional uint64 course_id = 47; // 1 and others: course?, tag760
optional uint64 evs_f48 = 48; //tag898
optional string routeUrl = 49; //tag906
repeated int32 evs_f50 = 50; //tag912
optional bool evs_f51 = 51; //tag920
}
message Event {
enum EventVisibility {
EV_NULL = 0;
EV_PUB_SHARE = 1; // event public shareable
EV_BY_RESOURCE = 2; // event defined by resource
EV_SHAREABLE = 3;
}
message MicroserviceEventData {
optional string name = 1; // "clubs" everywhere (json: microserviceName)
optional bytes externalResourceId = 2; // different 16-byte bb4538bfd13346c99a4df2b3cc3b5d95 (json: microserviceExternalResourceId)
optional EventVisibility visibility = 3; // enum 1 (json: microserviceEventVisibility)
}
message EventSeriesProtobuf { //{"id":4531,"name":"Zwift Academy Triathlon - Baseline TT","description":null,"imported":false}
optional uint64 id = 1; //5445 or 1485
optional string name = 2; //INEOSVTC or "Fast Friday"
optional string description = 3; //"" or "Congratulations, you crushed another week of workouts! ..."
}
message EventTimeTrialOptions { //{"timeGapBetweenRowsMs":15000,"maxRows":50,"maxRidersPerRow":10}
optional uint32 timeGapBetweenRowsMs = 1; //15000 everywhere
optional uint32 maxRows = 2; //50 or 25
optional uint32 maxRidersPerRow = 3; //10 everywhere
optional uint32 evt_f4 = 4;
optional uint64 evt_f5 = 5;
}
enum EventTypeV2 {
EVENT_TYPE_UNKNOWN = 0;
EVENT_TYPE_EFONDO = 1;
EVENT_TYPE_RACE = 2;
EVENT_TYPE_GROUP_RIDE = 3;
EVENT_TYPE_GROUP_WORKOUT = 4;
EVENT_TYPE_TIME_TRIAL = 5;
}
enum EventType {
ET_UNKNOWN = 0;
EFONDO = 1;
RACE = 2;
GROUP_RIDE = 3;
GROUP_WORKOUT = 4;
TIME_TRIAL = 5;
}
enum EventCulling {
CULLING_UNDEFINED = 0;
CULLING_EVERYBODY = 1;
CULLING_EVENT_ONLY = 2;
CULLING_SUBGROUP_ONLY = 3;
}
message Event { //real name: EventProtobuf; where is shortName, shortDescription, rulesSet, routeUrl, bikeHash,
//privateEvent, followeeEntrantCount, totalEntrantCount, followeeSignedUpCount, totalSignedUpCount, followeeJoinedCount,
//totalJoinedCount, auxiliaryUrl, imageS3Name, imageS3Bucket, cullingType, recurring, recurringOffset, publishRecurring, parentId, type, workoutHash,
//customUrl, restricted, unlisted, eventSecret, accessExpression, qualificationRuleIds, minGameVersion, recordable, imported, eventTemplateId
required uint64 id = 1;
optional uint32 world_id = 2;
required string title = 3;
optional uint64 server_realm = 2;
required string name = 3;
optional string description = 4;
optional uint64 eventStart = 5; // Start time (epoch time in ms)
optional fixed32 f7 = 7;
optional uint64 laps = 8;
optional uint64 f9 = 9;
repeated Category category = 10;
optional string f11 = 11;
optional string pic_url = 12;
optional uint32 duration = 13; // Duration in seconds?
optional string e_f6 = 6;
optional float distanceInMeters = 7;
optional uint32 laps = 8;
optional uint32 e_f9 = 9;
repeated EventSubgroupProtobuf category = 10; //event_subgroup_size() <= MAX_SUBGROUPS(6)
optional string e_f11 = 11;
optional string imageUrl = 12;
optional uint32 durationInSeconds = 13;
optional uint64 route_id = 14;
optional uint64 rules_id = 15;
optional uint64 f16 = 16;
optional uint64 f17 = 17;
optional uint64 f18 = 18;
optional string f19 = 19;
optional uint32 f22 = 22;
optional uint32 f24 = 24;
optional string f26 = 26;
optional uint32 f27 = 27;
optional uint32 f28 = 28;
optional uint32 f29 = 29;
optional uint32 e_f16 = 16;
optional bool visible = 17;
optional uint64 jerseyHash = 18;
optional string e_f19 = 19;
optional string e_f20 = 20;
optional string e_f21 = 21;
optional Sport sport = 22;
optional uint64 e_f23 = 23;
optional EventType eventType = 24;
optional uint64 e_f25 = 25;
optional string e_f26 = 26;
optional uint64 e_f27 = 27; //<=4, ENUM?
optional bool overrideMapPreferences = 28;
optional bool invisibleToNonParticipants = 29;
optional EventSeriesProtobuf evSeries = 30;
optional string tags = 31; // semi-colon delimited tags
optional uint64 e_f32 = 32;
optional bool e_wtrl = 33; //WTRL (World Tactical Racing Leagues)
optional uint32 lateJoinInMinutes = 34;
optional uint32 map_id = 35;
optional uint64 course_id = 35;
optional EventTimeTrialOptions tto = 36;
optional string e_f37 = 37;
optional string e_f38 = 38;
optional uint32 e_f39 = 39;
optional MicroserviceEventData msed = 40;
repeated uint32 e_f41 = 41;
}
message Events {
message Events { //real name: EventsProtobuf
repeated Event events = 1;
}

File diff suppressed because one or more lines are too long

View File

@@ -1,18 +1,20 @@
syntax = "proto2";
//TODO: uncomment and use f14, rename fields in db
message Goal {
optional uint64 id = 1;
optional uint64 player_id = 2;
optional uint32 f3 = 3; /* status or sport? */
optional string name = 4;
optional uint32 type = 5; /* 0=distance, 1=time */
optional uint32 periodicity = 6; /* 0=weekly, 1=monthly */
optional float target_distance = 7; /* in meters. set to dur for dur goals */
optional float target_duration = 8; /* in minutes. set to dist for dist goals */
optional float actual_distance = 9; /* in minutes. is also set for dur goals? */
optional float actual_duration = 10; /* in meters. is also set for dist goals? */
optional uint64 created_on = 11; /* in ms since epoch */
optional uint64 period_end_date = 12; /* "" */
optional uint64 f13 = 13; /* status or sport? */
optional int64 f3 = 3; //-> enum Sport sport
optional string name = 4; // i.e. "Monthly time goal"
optional int64 type = 5; //-> enum GoalType 0=distance, 1=time
optional int64 periodicity = 6; //-> enum GoalPeriod 0=weekly, 1=monthly
optional float target_distance = 7; //in meters. set to dur for dur goals
optional float target_duration = 8; //in minutes. set to dist for dist goals
optional float actual_distance = 9; //in meters. is also set for dur goals?
optional float actual_duration = 10; //in minutes. is also set for dist goals?
optional uint64 created_on = 11; //in ms since epoch
optional uint64 period_end_date = 12;
optional uint64 f13 = 13; //-> enum GoalStatus 0=active, 1=retired
//optional string f14 = 14; // timezone? (empty)
}
message Goals {

View File

@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\ngoal.proto\"\x80\x02\n\x04Goal\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x11\n\tplayer_id\x18\x02 \x01(\x04\x12\n\n\x02\x66\x33\x18\x03 \x01(\r\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x0c\n\x04type\x18\x05 \x01(\r\x12\x13\n\x0bperiodicity\x18\x06 \x01(\r\x12\x17\n\x0ftarget_distance\x18\x07 \x01(\x02\x12\x17\n\x0ftarget_duration\x18\x08 \x01(\x02\x12\x17\n\x0f\x61\x63tual_distance\x18\t \x01(\x02\x12\x17\n\x0f\x61\x63tual_duration\x18\n \x01(\x02\x12\x12\n\ncreated_on\x18\x0b \x01(\x04\x12\x17\n\x0fperiod_end_date\x18\x0c \x01(\x04\x12\x0b\n\x03\x66\x31\x33\x18\r \x01(\x04\"\x1d\n\x05Goals\x12\x14\n\x05goals\x18\x01 \x03(\x0b\x32\x05.Goal')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\ngoal.proto\"\x80\x02\n\x04Goal\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x11\n\tplayer_id\x18\x02 \x01(\x04\x12\n\n\x02\x66\x33\x18\x03 \x01(\x03\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x0c\n\x04type\x18\x05 \x01(\x03\x12\x13\n\x0bperiodicity\x18\x06 \x01(\x03\x12\x17\n\x0ftarget_distance\x18\x07 \x01(\x02\x12\x17\n\x0ftarget_duration\x18\x08 \x01(\x02\x12\x17\n\x0f\x61\x63tual_distance\x18\t \x01(\x02\x12\x17\n\x0f\x61\x63tual_duration\x18\n \x01(\x02\x12\x12\n\ncreated_on\x18\x0b \x01(\x04\x12\x17\n\x0fperiod_end_date\x18\x0c \x01(\x04\x12\x0b\n\x03\x66\x31\x33\x18\r \x01(\x04\"\x1d\n\x05Goals\x12\x14\n\x05goals\x18\x01 \x03(\x0b\x32\x05.Goal')

View File

@@ -1,7 +1,7 @@
syntax = "proto2";
message HashSeed {
required uint64 seed1 = 1;
required uint64 seed2 = 2;
required uint32 seed1 = 1;
required uint32 seed2 = 2;
required uint64 expiryDate = 3;
}

View File

@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10hash-seeds.proto\"<\n\x08HashSeed\x12\r\n\x05seed1\x18\x01 \x02(\x04\x12\r\n\x05seed2\x18\x02 \x02(\x04\x12\x12\n\nexpiryDate\x18\x03 \x02(\x04\"%\n\tHashSeeds\x12\x18\n\x05seeds\x18\x01 \x03(\x0b\x32\t.HashSeed')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10hash-seeds.proto\"<\n\x08HashSeed\x12\r\n\x05seed1\x18\x01 \x02(\r\x12\r\n\x05seed2\x18\x02 \x02(\r\x12\x12\n\nexpiryDate\x18\x03 \x02(\x04\"%\n\tHashSeeds\x12\x18\n\x05seeds\x18\x01 \x03(\x0b\x32\t.HashSeed')

View File

@@ -1,29 +1,8 @@
syntax = "proto2";
/* XXX: This is a first approximation of login response. Not looked into or verified. */
message UDPNode {
required string ip = 1;
required uint32 port = 2;
}
message UDPNodes {
/* First server here is not a UDP node, it's the TCP telemetry server (34.218.60.145) */
repeated UDPNode node = 1;
}
message APIs {
optional string todaysplan_url = 1;
optional string trainingpeaks_url = 2;
}
message ServerInfo {
required string relay_url = 1;
required APIs apis = 2;
required uint64 time = 3;
optional UDPNodes nodes = 4;
}
import "per-session-info.proto";
message LoginResponse {
required string session_state = 1;
required ServerInfo info = 2;
required PerSessionInfo info = 2;
}

View File

@@ -12,45 +12,14 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default()
import per_session_info_pb2 as per__session__info__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14login-response.proto\"#\n\x07UDPNode\x12\n\n\x02ip\x18\x01 \x02(\t\x12\x0c\n\x04port\x18\x02 \x02(\r\"\"\n\x08UDPNodes\x12\x16\n\x04node\x18\x01 \x03(\x0b\x32\x08.UDPNode\"9\n\x04\x41PIs\x12\x16\n\x0etodaysplan_url\x18\x01 \x01(\t\x12\x19\n\x11trainingpeaks_url\x18\x02 \x01(\t\"\\\n\nServerInfo\x12\x11\n\trelay_url\x18\x01 \x02(\t\x12\x13\n\x04\x61pis\x18\x02 \x02(\x0b\x32\x05.APIs\x12\x0c\n\x04time\x18\x03 \x02(\x04\x12\x18\n\x05nodes\x18\x04 \x01(\x0b\x32\t.UDPNodes\"A\n\rLoginResponse\x12\x15\n\rsession_state\x18\x01 \x02(\t\x12\x19\n\x04info\x18\x02 \x02(\x0b\x32\x0b.ServerInfo')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14login-response.proto\x1a\x16per-session-info.proto\"E\n\rLoginResponse\x12\x15\n\rsession_state\x18\x01 \x02(\t\x12\x1d\n\x04info\x18\x02 \x02(\x0b\x32\x0f.PerSessionInfo')
_UDPNODE = DESCRIPTOR.message_types_by_name['UDPNode']
_UDPNODES = DESCRIPTOR.message_types_by_name['UDPNodes']
_APIS = DESCRIPTOR.message_types_by_name['APIs']
_SERVERINFO = DESCRIPTOR.message_types_by_name['ServerInfo']
_LOGINRESPONSE = DESCRIPTOR.message_types_by_name['LoginResponse']
UDPNode = _reflection.GeneratedProtocolMessageType('UDPNode', (_message.Message,), {
'DESCRIPTOR' : _UDPNODE,
'__module__' : 'login_response_pb2'
# @@protoc_insertion_point(class_scope:UDPNode)
})
_sym_db.RegisterMessage(UDPNode)
UDPNodes = _reflection.GeneratedProtocolMessageType('UDPNodes', (_message.Message,), {
'DESCRIPTOR' : _UDPNODES,
'__module__' : 'login_response_pb2'
# @@protoc_insertion_point(class_scope:UDPNodes)
})
_sym_db.RegisterMessage(UDPNodes)
APIs = _reflection.GeneratedProtocolMessageType('APIs', (_message.Message,), {
'DESCRIPTOR' : _APIS,
'__module__' : 'login_response_pb2'
# @@protoc_insertion_point(class_scope:APIs)
})
_sym_db.RegisterMessage(APIs)
ServerInfo = _reflection.GeneratedProtocolMessageType('ServerInfo', (_message.Message,), {
'DESCRIPTOR' : _SERVERINFO,
'__module__' : 'login_response_pb2'
# @@protoc_insertion_point(class_scope:ServerInfo)
})
_sym_db.RegisterMessage(ServerInfo)
LoginResponse = _reflection.GeneratedProtocolMessageType('LoginResponse', (_message.Message,), {
'DESCRIPTOR' : _LOGINRESPONSE,
'__module__' : 'login_response_pb2'
@@ -61,14 +30,6 @@ _sym_db.RegisterMessage(LoginResponse)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
_UDPNODE._serialized_start=24
_UDPNODE._serialized_end=59
_UDPNODES._serialized_start=61
_UDPNODES._serialized_end=95
_APIS._serialized_start=97
_APIS._serialized_end=154
_SERVERINFO._serialized_start=156
_SERVERINFO._serialized_end=248
_LOGINRESPONSE._serialized_start=250
_LOGINRESPONSE._serialized_end=315
_LOGINRESPONSE._serialized_start=48
_LOGINRESPONSE._serialized_end=117
# @@protoc_insertion_point(module_scope)

17
protobuf/make.bat Normal file
View File

@@ -0,0 +1,17 @@
del *_pb2.py *_pb2.pyc
protoc --python_out=. activity.proto
protoc --python_out=. segment-result.proto
protoc --python_out=. profile.proto
protoc --python_out=. per-session-info.proto
protoc --python_out=. login-response.proto
protoc --python_out=. periodic-info.proto
protoc --python_out=. world.proto
protoc --python_out=. goal.proto
protoc --python_out=. zfiles.proto
protoc --python_out=. udp-node-msgs.proto
protoc --python_out=. tcp-node-msgs.proto
protoc --python_out=. hash-seeds.proto
protoc --python_out=. events.proto
protoc --python_out=. variants.proto
pause

View File

@@ -1,4 +1,25 @@
syntax = "proto2";
message TcpAddress {
optional string ip = 1;
optional int32 port = 2;
optional int32 lb_realm = 3; //load balancing cluster: server realm or 0 (generic)
optional int32 lb_course = 4; //load balancing cluster: course id (see also TcpAddressService::updateAddresses)
}
message TcpConfig {
//First server: the TCP telemetry server (34.218.60.145)
repeated TcpAddress nodes = 1;
}
message PartnersUrls {
optional string todaysplan_url = 1;
optional string trainingpeaks_url = 2;
}
message PerSessionInfo {
required string relay_url = 1;
optional PartnersUrls apis = 2;
optional uint64 time = 3;
optional TcpConfig nodes = 4;
optional int32 maxSegmSubscrs = 5; //if received, sub_718DE99570 puts log message "Received max allowed segment subscriptions from session: %d", m_maxSegmSubscrs and stores it into GlobalState...
}

View File

@@ -14,11 +14,35 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16per-session-info.proto\"#\n\x0ePerSessionInfo\x12\x11\n\trelay_url\x18\x01 \x02(\t')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16per-session-info.proto\"K\n\nTcpAddress\x12\n\n\x02ip\x18\x01 \x01(\t\x12\x0c\n\x04port\x18\x02 \x01(\x05\x12\x10\n\x08lb_realm\x18\x03 \x01(\x05\x12\x11\n\tlb_course\x18\x04 \x01(\x05\"\'\n\tTcpConfig\x12\x1a\n\x05nodes\x18\x01 \x03(\x0b\x32\x0b.TcpAddress\"A\n\x0cPartnersUrls\x12\x16\n\x0etodaysplan_url\x18\x01 \x01(\t\x12\x19\n\x11trainingpeaks_url\x18\x02 \x01(\t\"\x81\x01\n\x0ePerSessionInfo\x12\x11\n\trelay_url\x18\x01 \x02(\t\x12\x1b\n\x04\x61pis\x18\x02 \x01(\x0b\x32\r.PartnersUrls\x12\x0c\n\x04time\x18\x03 \x01(\x04\x12\x19\n\x05nodes\x18\x04 \x01(\x0b\x32\n.TcpConfig\x12\x16\n\x0emaxSegmSubscrs\x18\x05 \x01(\x05')
_TCPADDRESS = DESCRIPTOR.message_types_by_name['TcpAddress']
_TCPCONFIG = DESCRIPTOR.message_types_by_name['TcpConfig']
_PARTNERSURLS = DESCRIPTOR.message_types_by_name['PartnersUrls']
_PERSESSIONINFO = DESCRIPTOR.message_types_by_name['PerSessionInfo']
TcpAddress = _reflection.GeneratedProtocolMessageType('TcpAddress', (_message.Message,), {
'DESCRIPTOR' : _TCPADDRESS,
'__module__' : 'per_session_info_pb2'
# @@protoc_insertion_point(class_scope:TcpAddress)
})
_sym_db.RegisterMessage(TcpAddress)
TcpConfig = _reflection.GeneratedProtocolMessageType('TcpConfig', (_message.Message,), {
'DESCRIPTOR' : _TCPCONFIG,
'__module__' : 'per_session_info_pb2'
# @@protoc_insertion_point(class_scope:TcpConfig)
})
_sym_db.RegisterMessage(TcpConfig)
PartnersUrls = _reflection.GeneratedProtocolMessageType('PartnersUrls', (_message.Message,), {
'DESCRIPTOR' : _PARTNERSURLS,
'__module__' : 'per_session_info_pb2'
# @@protoc_insertion_point(class_scope:PartnersUrls)
})
_sym_db.RegisterMessage(PartnersUrls)
PerSessionInfo = _reflection.GeneratedProtocolMessageType('PerSessionInfo', (_message.Message,), {
'DESCRIPTOR' : _PERSESSIONINFO,
'__module__' : 'per_session_info_pb2'
@@ -29,6 +53,12 @@ _sym_db.RegisterMessage(PerSessionInfo)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
_PERSESSIONINFO._serialized_start=26
_PERSESSIONINFO._serialized_end=61
_TCPADDRESS._serialized_start=26
_TCPADDRESS._serialized_end=101
_TCPCONFIG._serialized_start=103
_TCPCONFIG._serialized_end=142
_PARTNERSURLS._serialized_start=144
_PARTNERSURLS._serialized_end=209
_PERSESSIONINFO._serialized_start=212
_PERSESSIONINFO._serialized_end=341
# @@protoc_insertion_point(module_scope)

View File

@@ -1,5 +1,6 @@
syntax = "proto2";
message PeriodicInfo {
//TODO: check if used
message PeriodicInfo { // very similar to TcpAddress, did not found in ZwiftApp.exe yet
required string game_server_ip = 1;
optional uint32 f2 = 2;
optional uint32 f3 = 3;
@@ -8,7 +9,6 @@ message PeriodicInfo {
optional uint32 f6 = 6;
}
message PeriodicInfos {
message PeriodicInfos { // very similar to TcpConfig
repeated PeriodicInfo infos = 1;
}

View File

@@ -1,240 +1,328 @@
syntax = "proto2";
message Profile {
optional int64 id = 1;
optional int32 is_connected_to_strava = 2;
optional string email = 3;
optional string first_name = 4;
optional string last_name = 5;
optional bool is_male = 6;
optional bytes f7 = 7;
optional uint32 weight_in_grams = 9;
optional uint32 ftp = 10;
optional uint32 f11 = 11;
optional uint32 f12 = 12;
optional uint32 f13 = 13;
optional uint32 f14 = 14;
optional uint32 f15 = 15;
optional uint32 f16 = 16;
optional uint32 f17 = 17;
optional uint32 f18 = 18;
optional uint32 f19 = 19;
optional fixed32 f20 = 20;
optional fixed32 f21 = 21;
optional fixed32 f22 = 22;
optional fixed32 f23 = 23;
optional fixed32 f24 = 24;
optional fixed32 f25 = 25;
optional fixed32 f26 = 26;
optional fixed64 f27 = 27;
optional fixed64 f28 = 28;
optional fixed64 f29 = 29;
optional fixed64 f30 = 30;
optional fixed64 f31 = 31;
optional fixed64 f32 = 32;
optional bytes f33 = 33;
optional uint32 country_code = 34;
optional uint32 total_distance_in_meters = 35;
optional uint32 elevation_gain_in_meters = 36;
optional uint32 time_ridden_in_minutes = 37;
optional uint32 f38 = 38; /* time in jersey X */
optional uint32 f39 = 39; /* time in jersey Y */
optional uint32 f40 = 40; /* time in jersey Z */
optional uint32 total_watt_hours = 41;
optional uint32 height_in_millimeters = 42;
optional string dob = 43;
optional uint32 f44 = 44;
optional bool f45 = 45;
optional uint32 total_xp = 46;
optional uint32 f47 = 47;
optional PlayerType player_type = 48;
enum PlayerType {
PLAYERTYPE0 = 0;
NORMAL = 1;
PLAYERTYPE2 = 2;
PLAYERTYPE3 = 3;
PLAYERTYPE4 = 4;
}
optional uint32 achievement_level = 49;
optional bool f50 = 50;
optional bool f51 = 51;
optional uint32 f52 = 52;
optional uint32 f53 = 53;
optional uint32 f54 = 54;
optional uint32 age = 55;
optional fixed32 f56 = 56;
optional uint32 f57 = 57;
optional bytes f58 = 58;
optional fixed64 f59 = 59;
repeated bytes f60 = 60; /* related to subscription/billing */
optional ProfileSocialFacts social_facts = 61;
message ProfileSocialFacts {
optional int64 profile_id = 1;
optional int64 f2 = 2;
optional int64 f3 = 3;
optional int64 f4 = 4;
optional ProfileFollowStatus f5 = 5;
optional ProfileFollowStatus f6 = 6;
optional bool f7 = 7;
}
optional ProfileFollowStatus f62 = 62;
optional bool f63 = 63;
optional bool f64 = 64;
optional ProfileEnrolledProgram f65 = 65;
enum ProfileEnrolledProgram {
ENROLLEDPROGRAM0 = 0;
ENROLLEDPROGRAM1 = 1;
ENROLLEDPROGRAM2 = 2;
ENROLLEDPROGRAM3 = 3;
ENROLLEDPROGRAM4 = 4;
}
optional bytes f66 = 66;
optional uint32 f67 = 67;
optional fixed32 f68 = 68;
optional fixed32 f69 = 69;
optional fixed32 f70 = 70;
optional fixed32 f71 = 71;
optional fixed32 f72 = 72;
optional fixed32 f73 = 73;
optional uint32 f74 = 74;
optional uint32 f75 = 75;
optional fixed32 f76 = 76;
optional fixed32 f77 = 77;
optional fixed32 f78 = 78;
optional fixed32 f79 = 79;
optional uint32 f80 = 80;
optional uint32 f81 = 81;
optional Subscription f82 = 82;
enum Sport {
SPORT0 = 0;
SPORT1 = 1;
SPORT2 = 2;
SPORT3 = 3;
SPORT4 = 4;
}
optional string mix_panel_distinct_id = 83;
optional uint32 f84 = 84;
optional uint32 f85 = 85;
optional Sport sport = 86;
optional uint32 f87 = 87;
optional bool f88 = 88;
optional string preferred_language = 89;
optional uint32 f90 = 90;
optional uint32 f91 = 91;
optional uint32 f92 = 92;
optional uint32 f93 = 93;
optional uint32 f94 = 94;
optional uint32 f95 = 95;
optional uint32 f96 = 96;
optional uint32 f97 = 97;
optional uint32 f98 = 98;
optional uint32 f99 = 99;
optional uint32 f100 = 100;
optional uint32 f101 = 101;
optional uint32 f102 = 102;
optional uint32 f103 = 103;
optional uint32 f104 = 104;
optional bool f105 = 105;
optional bool f106 = 106;
repeated bytes f107 = 107;
optional string launched_game_client = 108;
optional int64 f109 = 109;
optional bool f110 = 110;
repeated PacerSetting f114 = 114;
optional int32 f117 = 117;
optional int32 f118 = 118;
optional int32 f119 = 119;
optional int32 f120 = 120;
optional int32 f121 = 121;
optional int32 f125 = 125;
//TODO: answer ??? questions and saved_game format (zwift_profile.ksy)
enum ActivityPrivacyType {
PUBLIC = 0;
PRIVATE = 1;
FRIENDS = 2;
}
enum Sport {
CYCLING = 0;
RUNNING = 1;
ROWING = 2;
SPORT3 = 3;
SPORT4 = 4;
}
enum PlayerType {
PLAYERTYPE0 = 0;
NORMAL = 1;
PRO_CYCLIST = 2;
ZWIFT_STAFF = 3;
AMBASSADOR = 4;
VERIFIED = 5;
ZED = 6;
ZAC = 7;
PRO_TRIATHLETE = 8;
PRO_RUNNER = 9;
}
enum PowerType {
PT_VIRTUAL = 0;
PT_METER = 1;
}
message AchievementEntry {
required int32 id = 1;
}
message Achievements {
repeated AchievementEntry achievements = 1;
}
message Profiles {
repeated Profile profiles = 1;
message PlayerProfile {
optional int64 id = 1;
optional int64 server_realm = 2;
optional string email = 3;
optional string first_name = 4;
optional string last_name = 5;
optional bool is_male = 6;
optional string f7 = 7; //??? empty
// no f8 exists
optional uint32 weight_in_grams = 9;
optional uint32 ftp = 10;
optional uint32 f11 = 11; //??? empty
optional uint32 body_type = 12;
optional uint32 hair_type = 13;
optional uint32 facial_hair_type = 14;
optional uint32 ride_helmet_type = 15;
optional uint32 glasses_type = 16;
optional uint32 ride_shoes_type = 17;
optional uint32 ride_socks_type = 18;
optional uint32 ride_gloves = 19;
optional fixed32 ride_jersey = 20;
optional fixed32 f21 = 21; //??? empty
optional fixed32 bike_wheel_front = 22;
optional fixed32 bike_wheel_rear = 23;
optional fixed32 bike_frame = 24;
optional fixed32 f25 = 25; //??? empty
optional fixed32 f26 = 26; //??? empty
optional fixed64 bike_frame_colour = 27;
optional fixed64 f28 = 28; //??? empty
optional fixed64 f29 = 29; //??? empty
optional fixed64 f30 = 30; //??? empty
optional fixed64 f31 = 31; //??? empty
optional fixed64 f32 = 32; //??? empty
optional bytes saved_game = 33; //for format look at zwift_profile.ksy
optional uint32 country_code = 34;
optional uint32 total_distance_in_meters = 35;
optional uint32 elevation_gain_in_meters = 36;
optional uint32 time_ridden_in_minutes = 37;
optional uint32 total_in_kom_jersey = 38;
optional uint32 total_in_sprinters_jersey = 39;
optional uint32 total_in_orange_jersey = 40;
optional uint32 total_watt_hours = 41; // = calories * 0.3256381927080305
optional uint32 height_in_millimeters = 42;
optional string dob = 43;
optional uint32 max_heart_rate = 44;
optional bool connected_to_strava = 45;
optional uint32 total_xp = 46;
optional uint32 total_gold_drops = 47;
optional PlayerType player_type = 48;
optional uint32 achievement_level = 49;
optional bool use_metric = 50;
optional bool strava_premium = 51;
optional PowerType power_source_model = 52;
optional uint32 f53 = 53; //??? empty
optional uint32 f54 = 54; //??? empty
optional uint32 age = 55;
optional fixed32 f56 = 56; //??? empty
optional uint32 f57 = 57; //??? empty
optional string large_avatar_url = 58;
optional fixed64 privacy_bits = 59;
repeated ProfileEntitlement entitlements = 60;
optional SocialFacts social_facts = 61;
message SocialFacts {
optional int64 profile_id = 1;
optional int32 followers_count = 2;
optional int32 followees_count = 3;
optional int32 followees_in_common_with_logged_in_player = 4;
optional FollowStatus follower_status_of_logged_in_player = 5;
optional FollowStatus followee_status_of_logged_in_player = 6;
optional bool is_favorite_of_logged_in_player = 7;
}
optional FollowStatus follow_status = 62;
optional bool connected_to_training_peaks = 63;
optional bool connected_to_todays_plan = 64;
optional EnrolledProgram enrolled_program = 65;
enum EnrolledProgram {
ENROLLEDPROGRAM0 = 0;
ZWIFT_ACADEMY = 1;
ENROLLEDPROGRAM2 = 2;
ENROLLEDPROGRAM3 = 3;
ENROLLEDPROGRAM4 = 4;
}
optional string todayplan_url = 66;
optional uint32 f67 = 67; //??? empty
optional fixed32 run_shirt_type = 68;
optional fixed32 run_shorts_type = 69;
optional fixed32 run_shoes_type = 70;
optional fixed32 run_socks_type = 71;
optional fixed32 run_helmet_type = 72;
optional fixed32 run_arm_accessory = 73;
optional uint32 total_run_distance = 74;
optional uint32 total_run_experience_points = 75;
optional fixed32 f76 = 76; //??? empty
optional fixed32 f77 = 77; //??? empty
optional fixed32 f78 = 78; //??? empty
optional fixed32 f79 = 79; //??? empty
optional uint32 f80 = 80; //??? empty
optional uint32 f81 = 81; //??? empty
optional Subscription subscription = 82;
optional string mix_panel_distinct_id = 83;
optional uint32 run_achievement_level = 84;
optional uint32 total_run_time_in_minutes = 85;
optional Sport sport = 86;
optional uint32 utc_offset_in_minutes = 87;
optional bool connected_to_under_armour = 88;
optional string preferred_language = 89;
optional uint32 hair_colour = 90;
optional uint32 facial_hair_colour = 91;
optional uint32 f92 = 92; //??? empty
optional uint32 f93 = 93; //??? empty
optional uint32 run_shorts_length = 94;
optional uint32 f95 = 95; //??? empty
optional uint32 run_socks_length = 96;
optional uint32 f97 = 97; //??? empty
optional uint32 ride_socks_length = 98;
optional uint32 f99 = 99; //??? empty
optional uint32 f100 = 100; //??? empty
optional uint32 f101 = 101; //??? empty
optional uint32 f102 = 102; //??? empty
optional uint32 f103 = 103; //??? empty
optional uint32 f104 = 104; //??? empty
optional bool connected_to_withings = 105;
optional bool connected_to_fitbit = 106;
// no 107 repeated bytes
optional string launched_game_client = 108;
optional int64 current_activity_id = 109;
optional bool connected_to_garmin = 110;
message Reminder {
optional int64 f1 = 1;
optional string f2 = 2;
optional int64 f3 = 3;
message ReminderProperty {
optional int64 f1 = 1;
optional string f2 = 2;
optional string f3 = 3;
}
repeated ReminderProperty f4 = 4;
}
repeated Reminder reminders = 111;
optional bool f112 = 112; //??? empty
repeated Attribute private_attributes = 113;
repeated Attribute public_attributes = 114;
optional int32 total_run_calories = 115;
optional int64 f116 = 116; //??? empty
optional int32 run_time_1mi_in_seconds = 117;
optional int32 run_time_5km_in_seconds = 118;
optional int32 run_time_10km_in_seconds = 119;
optional int32 run_time_half_marathon_in_seconds = 120;
optional int32 run_time_full_marathon_in_seconds = 121;
optional int32 f122 = 122; //??? empty
enum CyclingOrganization {
NO_CYCLING_LICENSE = 0;
CYCLING_SOUTH_AFRICA = 1;
CYCLING_AUSTRALIA = 2;
CYCLING_NEW_ZEALAND = 3;
}
optional CyclingOrganization cycling_organization = 123;
optional string f124 = 124; // LICENSE_NUMBER/E_NUMBER
optional ActivityPrivacyType default_activity_privacy = 125;
optional bool connected_to_runtastic = 126;
repeated PropertyChange property_changes = 127;
}
message PlayerProfiles {
repeated PlayerProfile profiles = 1;
}
message ProfileEntitlement {
optional EntitlementType f1 = 1;
enum EntitlementType {
ENTITLEMENTTYPE0 = 0;
ENTITLEMENTTYPE1 = 1;
ENTITLEMENTTYPE2 = 2;
ENTITLEMENTTYPE3 = 3;
ENTITLEMENTTYPE4 = 4;
}
optional int64 f2 = 2;
optional ProfileEntitlementStatus c = 3;
enum ProfileEntitlementStatus {
ENTITLEMENTSTATUS0 = 0;
ENTITLEMENTSTATUS1 = 1;
ENTITLEMENTSTATUS2 = 2;
ENTITLEMENTSTATUS3 = 3;
ENTITLEMENTSTATUS4 = 4;
}
optional bytes f4 = 4;
optional uint32 f5 = 5;
optional uint32 f6 = 6;
optional uint32 f7 = 7;
optional uint32 f8 = 8;
optional uint32 f9 = 9;
optional bytes f10 = 10;
optional Platform f11 = 11;
enum Platform {
PLATFORM0 = 0;
PLATFORM1 = 1;
PLATFORM2 = 2;
PLATFORM3 = 3;
PLATFORM4 = 4;
PLATFORM5 = 5;
PLATFORM6 = 6;
}
optional uint32 f12 = 12;
optional bool f13 = 13;
optional EntitlementType type = 1;
enum EntitlementType {
ENTITLEMENTTYPE0 = 0;
RIDE = 1;
RUN = 2;
ROW = 3;
USE = 4;
}
optional int64 f2 = 2; // always -1: legacy?
optional ProfileEntitlementStatus status = 3;
enum ProfileEntitlementStatus {
ENTITLEMENTSTATUS0 = 0;
EXPIRED = 1;
ACTIVE = 2;
CANCELED = 3;
INACTIVE = 4;
APPLIED_AS_SUBSCRIPTION_TRIAL_PERIOD = 5;
}
optional string period = 4; // 'P7D' = period of 7 days (Y, M also supported for year and month)
optional uint32 begin_time_unix = 5; //when period started
optional uint32 end_time_unix = 6; //when period ended
optional uint32 kilometers = 7; //25 every month
optional uint32 begin_total_distance = 8; //where every-month gift started
optional uint32 end_total_distance = 9; //where every-month gift should end
optional string source = 10; // for example, "strava.premium" ?
optional Platform platform = 11; // legacy?
enum Platform {
PLATFORM_OSX = 0;
PLATFORM_PC = 1;
PLATFORM_IOS = 2;
PLATFORM_ANDROID = 3;
PLATFORM_TVOS = 4;
PLATFORM5 = 5;
PLATFORM6 = 6;
}
optional uint32 renewal_date_unix = 12; //when next 25km gift renewed
optional bool new_trial_system = 13; //do not interrupt current track if trial ended
repeated Platform platforms = 14;
}
enum ProfileFollowStatus {
FOLLOWSTATUS0 = 0;
SELF = 1;
FOLLOWSTATUS2 = 2;
FOLLOWSTATUS3 = 3;
FOLLOWSTATUS4 = 4;
enum FollowStatus {
FOLLOWSTATUS0 = 0;
UNKNOWN = 1;
REQUESTS_TO_FOLLOW = 2;
IS_FOLLOWING = 3;
HAS_BEEN_DECLINED = 7;
IS_BLOCKED = 4;
NO_RELATIONSHIP = 5;
SELF = 6;
}
message Subscription {
optional Gateway f1 = 1;
enum Gateway {
GATEWAY0 = 0;
GATEWAY1 = 1;
GATEWAY2 = 2;
GATEWAY3 = 3;
GATEWAY4 = 4;
}
optional SubscriptionStatus f2 = 2;
enum SubscriptionStatus {
STATUS0 = 0;
STATUS1 = 1;
ACTIVE = 2;
ACTIVE_CANCELLED = 3;
STATUS4 = 4;
STATUS5 = 5;
STATUS6 = 6;
}
optional Gateway gateway = 1;
enum Gateway {
BRAINTREE = 0;
APPLE = 1;
}
optional SubscriptionStatus status = 2;
enum SubscriptionStatus {
NEW = 0;
EXPIRED = 1;
ACTIVE = 2;
CANCELED = 3;
PAST_DUE = 4;
PENDING = 5;
SUBERROR = 6;
UNRECOGNIZED = 7;
UNKNOWN = 8;
ACTIVE_WITH_PAYMENT_FAILURE = 9;
ABANDONED = 10;
}
}
message PacerSetting {
required int64 id = 1;
optional uint64 number_value = 2;
optional fixed32 hex_value = 3;
optional string string_value = 5;
message PropertyChange {
enum Id {
TYPE0 = 0;
DATE_OF_BIRTH = 1;
GENDER = 2;
}
required Id property_name = 1;
optional int32 change_count = 2;
optional int32 max_changes = 3;
}
/*
Attribute ID is crc32 of it's name. Examples:
public
324889996=0x135D6D8C <MAGIC> (0)
private
-1575272099="TODAYS_SPORT_SELECT_TYPE" (CYCLIST)
1169650385="PLAYER_CACHE_BLOB" (000000)
1025311738="ONBOARD_CUSTOMIZATION_USER_TYPE_ZWIFT_GOAL" (GET IN SHAPE/TRAINING)
-1482469514="LEVEL50" (1)
839250175="TRAINING_PLAN_DETAILS" ("")
1190707182="LAST_RATING_TIME" (1641574907)
-702503934="XPTODROPSCONVERSIONDONE" (1)
2076353160="USERRIDECOUNT" (4)
-2012319163="LAST_WORKOUT_HASH" (1007947233)
-1001004453="SPORT_SELECT_TYPE" (CYCLIST)
1857228933="USAGE_HISTOGRAM_1" (0,...)
2004261226="DROPS_CURRENTSESSION" (0.0)
1318665884="USERPROFILE_STEERINGTUTORIALSHOWN" (1)
568968402="MOUNTAIN_TRAIL_STARTED" (7)
-642877525="MOUNTAIN_TRAIL_COMPLETED" (5)
-1414690690="USERPROFILE_STEERINGPAIRED" (1)
-34579778="ONROAD_SURVEY_COMPLETED" (5)
-1316403440="PACERBOTTUTORIAL" (1)
*/
message Attribute {
required int32 id = 1;
optional int64 number_value = 2;
optional float float_value = 3;
optional string string_value = 5;
}

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +1,11 @@
syntax = "proto2";
//import "profile.proto"; //enums PlayerType and Sport
//TODO: incorporate new fields, rename db fields
message SegmentResult {
optional uint64 id = 1;
required uint64 player_id = 2;
optional uint32 f3 = 3;
optional uint32 f4 = 4;
optional uint64 f3 = 3; //=g_CurrentServerRealmID
optional uint64 f4 = 4; //=CourseID
optional uint64 segment_id = 5;
optional uint64 event_subgroup_id = 6;
required string first_name = 7;
@@ -11,19 +13,22 @@ message SegmentResult {
optional uint64 world_time = 9;
optional string finish_time_str = 10;
required uint64 elapsed_ms = 11;
optional bool f12 = 12;
optional int64 f12 = 12; //-> enum PowerType + '-1'? (in ZNETWORK_RegisterPlayerSegmentResult from m_bikeEntity->m_hasPowerMeter)
optional uint32 f13 = 13; //weight_in_grams
optional uint32 f14 = 14;
optional uint32 f14 = 14; //:=0 in Leaderboards::SetPlayerSegmentResult
optional uint32 f15 = 15; //avg_power
optional bool f16 = 16;
optional string f17 = 17;
optional uint64 f18 = 18;
optional uint32 f19 = 19;
optional uint32 f20 = 20;
optional bool f16 = 16; //:= isMale
optional string f17 = 17; //ISO8601 time (magicLeaderboardBirthday := const @ ZNETWORK_Initialize)
optional uint64 f18 = 18; //-> enum PlayerType player_type
optional uint32 f19 = 19; //avg_hr(ZNETWORK_RaceResultEntrySaveRequest):=m_computer.m_accumHeartRate/m_computer.m_accumTime @ZNETWORK_RegisterLocalPlayersSegmentResult (or 0.0)
optional int64 f20 = 20; //-> enum Sport sport
//optional uint64 f21 = 21; //:=activityId (may be -1)
//optional bool f22 = 22;
//optional string f23 = 23;
}
message SegmentResults {
required uint32 world_id = 1;
required uint64 server_realm = 1;
required uint64 segment_id = 2;
optional uint64 event_subgroup_id = 3;
repeated SegmentResult segment_results = 4;

View File

@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14segment-result.proto\"\xd2\x02\n\rSegmentResult\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x11\n\tplayer_id\x18\x02 \x02(\x04\x12\n\n\x02\x66\x33\x18\x03 \x01(\r\x12\n\n\x02\x66\x34\x18\x04 \x01(\r\x12\x12\n\nsegment_id\x18\x05 \x01(\x04\x12\x19\n\x11\x65vent_subgroup_id\x18\x06 \x01(\x04\x12\x12\n\nfirst_name\x18\x07 \x02(\t\x12\x11\n\tlast_name\x18\x08 \x02(\t\x12\x12\n\nworld_time\x18\t \x01(\x04\x12\x17\n\x0f\x66inish_time_str\x18\n \x01(\t\x12\x12\n\nelapsed_ms\x18\x0b \x02(\x04\x12\x0b\n\x03\x66\x31\x32\x18\x0c \x01(\x08\x12\x0b\n\x03\x66\x31\x33\x18\r \x01(\r\x12\x0b\n\x03\x66\x31\x34\x18\x0e \x01(\r\x12\x0b\n\x03\x66\x31\x35\x18\x0f \x01(\r\x12\x0b\n\x03\x66\x31\x36\x18\x10 \x01(\x08\x12\x0b\n\x03\x66\x31\x37\x18\x11 \x01(\t\x12\x0b\n\x03\x66\x31\x38\x18\x12 \x01(\x04\x12\x0b\n\x03\x66\x31\x39\x18\x13 \x01(\r\x12\x0b\n\x03\x66\x32\x30\x18\x14 \x01(\r\"z\n\x0eSegmentResults\x12\x10\n\x08world_id\x18\x01 \x02(\r\x12\x12\n\nsegment_id\x18\x02 \x02(\x04\x12\x19\n\x11\x65vent_subgroup_id\x18\x03 \x01(\x04\x12\'\n\x0fsegment_results\x18\x04 \x03(\x0b\x32\x0e.SegmentResult')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14segment-result.proto\"\xd2\x02\n\rSegmentResult\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x11\n\tplayer_id\x18\x02 \x02(\x04\x12\n\n\x02\x66\x33\x18\x03 \x01(\x04\x12\n\n\x02\x66\x34\x18\x04 \x01(\x04\x12\x12\n\nsegment_id\x18\x05 \x01(\x04\x12\x19\n\x11\x65vent_subgroup_id\x18\x06 \x01(\x04\x12\x12\n\nfirst_name\x18\x07 \x02(\t\x12\x11\n\tlast_name\x18\x08 \x02(\t\x12\x12\n\nworld_time\x18\t \x01(\x04\x12\x17\n\x0f\x66inish_time_str\x18\n \x01(\t\x12\x12\n\nelapsed_ms\x18\x0b \x02(\x04\x12\x0b\n\x03\x66\x31\x32\x18\x0c \x01(\x03\x12\x0b\n\x03\x66\x31\x33\x18\r \x01(\r\x12\x0b\n\x03\x66\x31\x34\x18\x0e \x01(\r\x12\x0b\n\x03\x66\x31\x35\x18\x0f \x01(\r\x12\x0b\n\x03\x66\x31\x36\x18\x10 \x01(\x08\x12\x0b\n\x03\x66\x31\x37\x18\x11 \x01(\t\x12\x0b\n\x03\x66\x31\x38\x18\x12 \x01(\x04\x12\x0b\n\x03\x66\x31\x39\x18\x13 \x01(\r\x12\x0b\n\x03\x66\x32\x30\x18\x14 \x01(\x03\"~\n\x0eSegmentResults\x12\x14\n\x0cserver_realm\x18\x01 \x02(\x04\x12\x12\n\nsegment_id\x18\x02 \x02(\x04\x12\x19\n\x11\x65vent_subgroup_id\x18\x03 \x01(\x04\x12\'\n\x0fsegment_results\x18\x04 \x03(\x0b\x32\x0e.SegmentResult')
@@ -40,5 +40,5 @@ if _descriptor._USE_C_DESCRIPTORS == False:
_SEGMENTRESULT._serialized_start=25
_SEGMENTRESULT._serialized_end=363
_SEGMENTRESULTS._serialized_start=365
_SEGMENTRESULTS._serialized_end=487
_SEGMENTRESULTS._serialized_end=491
# @@protoc_insertion_point(module_scope)

View File

@@ -1,53 +1,116 @@
syntax = "proto2";
////////////////////////////////////////
// Initial TCP response below
////////////////////////////////////////
message ServerDetails {
required int32 f1 = 1;
required int32 f2 = 2;
required string ip = 3;
required int32 port = 4;
enum SocialPlayerActionType {
SOCIAL_ACTION_UNKNOWN_TYPE = 0;
SOCIAL_TEXT_MESSAGE = 1;
SOCIAL_RIDE_ON = 2;
SOCIAL_FLAG = 3;
}
enum FlagType {
FLAG_TYPE_UNKNOWN = 0;
FLAG_TYPE_HARASSMENT = 1;
FLAG_TYPE_FLIER = 2;
FLAG_TYPE_BAD_LANGUAGE = 3;
}
enum MessageGroupType {
MGT_UNKNOWN = 0;
MGT_GLOBAL = 1;
MGT_DIRECT = 2;
MGT_EVENT = 3;
MGT_CLUB = 4;
}
message SocialPlayerAction {
optional int64 player_id = 1;
optional int64 to_player_id = 2; // 0 if public message
optional SocialPlayerActionType spa_type = 3;
optional string firstName = 4;
optional string lastName = 5;
optional string message = 6;
optional string avatar = 7;
optional int32 countryCode = 8;
optional FlagType flagType = 9;
optional MessageGroupType mgType = 10;
optional int64 eventSubgroup = 11;
}
/*message MobileAlertResponse {
optional int64 f1 = 1;
optional int64 f2 = 2;
}
message ServersType1 {
repeated ServerDetails details = 1;
optional int32 f2 = 2;
optional int32 f3 = 3;
optional int32 f4 = 4;
}
message BLEPeripheralCharacteristic {
optional string f1 = 1;
optional bytes f2 = 2;
}*/
message ServerConnectionDetailsWrapper {
required int32 f1 = 1; // Value seems to be the same as ConnDetails' f1
required int32 f2 = 2; // Value seems to be the same as ConnDetails' f2
repeated ServerDetails details = 3;
}
//TODO: PeripheralResponseType UNKNOWN_RESPONSE_TYPE(0), PERIPHERAL_ERROR(1), CHARACTERISTIC_VALUE(2), PERIPHERAL_CONNECTED(3), PERIPHERAL_DISCONNECTED(4), PERIPHERAL_DISCOVERED(5);
// PeripheralErrorType UNKNOWN_ERROR(0), PERMISSION_DENIED(1), BLE_UNSUPPORTED(2), BLE_POWERED_OFF(3);
/*message BLEPeripheralResponse {
optional uint32 f1 = 1;
optional uint32 f2 = 2;
optional string f3 = 3;
optional BLEPeripheral f4 = 4;
optional BLEPeripheralCharacteristic f5 = 5;
}*/
message ServersType2 {
repeated ServerConnectionDetailsWrapper details_wrapper = 1;
required int32 port = 2;
}
// login-response.proto already defines ServerInfo and Python 3 doesn't like reusing it
message TCPServerInfo {
/*TODO: UNKNOWN(0), FLAGS(1), INCOMPLETE_UUIDS_16_BIT(2), COMPLETE_UUIDS_16_BIT(3), INCOMPLETE_UUIDS_32_BIT(4),
COMPLETE_UUIDS_32_BIT(5), INCOMPLETE_UUIDS_128_BIT(6), COMPLETE_UUIDS_128_BIT(7), SHORTENED_LOCAL_NAME(8),
COMPLETE_LOCAL_NAME(9), TX_POWER_LEVEL(10), CLASS_OF_DEVICE(13), SIMPLE_PAIRING_HASH(14), SIMPLE_PAIRING_RANDOMIZER(15),
DEVICE_ID(16), SECURITY_MANAGER_OOB_FLAGS(17), SLAVE_CONNECTION_INTERVAL(18), SOLICITATION_UUIDS_16_BIT(20),
SOLICITATION_UUIDS_128_BIT(21), SERVICE_DATA_16_BIT(22), PUBLIC_TARGET_ADDRESS(23), RANDOM_TARGET_ADDRESS(24),
APPEARANCE(25), ADVERTISING_INTERVAL(26), LE_BLUETOOTH_DEVICE_ADDRESS(27), LE_ROLE(28), SIMPLE_PAIRING_HASH_C256(29),
SIMPLE_PAIRING_RANDOMIZER_R256(30), SOLICITATION_UUIDS_32_BIT(31), SERVICE_DATA_32_BIT(32), SERVICE_DATA_128_BIT(33),
LE_SECURE_CONFIRMATION_VALUE(34), LE_SECURE_RANDOM_VALUE(35), URI(36), INDOOR_POSITIONING(37), TRANSPORT_DISCOVERY_DATA(38),
LE_SUPPORTED_FEATURES(39), CHANNEL_MAP_UPDATE_INDICATION(40), PB_ADV(41), MESH_MESSAGE(42), MESH_BEACON(43), BIG_INFO(44),
BROADCAST_CODE(45), INFORMATION_DATA_3D(61), MANUFACTURER_DATA(255); */
/*message BLEAdvertisementDataSection {
optional int32 f1 = 1;
required int32 player_id = 2;
required int32 f3 = 3;
repeated ServersType1 servers = 24;
repeated ServersType2 other_servers = 25;
optional bytes f2 = 2;
}
message TCPHello {
required int32 player_id = 2;
}
////////////////////////////////////////
// Recurring TCP response below
////////////////////////////////////////
message RecurringTCPResponse {
optional int32 f1 = 1;
optional int32 player_id = 2;
message BLEPeripheral {
optional string f1 = 1;
optional string f2 = 2;
optional int32 f3 = 3;
}*/
/*TODO: CONNECTABLE_UNDIRECTED(0), CONNECTABLE_DIRECTED(1), SCANNABLE_UNDIRECTED(2), NON_CONNECTABLE_UNDIRECTED(3),
SCAN_RESPONSE(4), EXTENDED(5); */
/*message BLEAdvertisement {
optional BLEPeripheral f1 = 1;
repeated BLEAdvertisementDataSection f2 = 2;
optional int32 f3 = 3;
optional int32 f11 = 11;
}
message PhoneToGameCommand {
required int32 seqno = 1;
required uint32 command = 2;
optional int64 f3 = 3;
optional string f4 = 4;
optional int64 f5 = 5;
optional string f6 = 6;
optional int64 f7 = 7;
optional int32 f8 = 8;
optional uint32 f9 = 9;
required uint32 command_copy = 10;
optional SocialPlayerAction f11 = 11;
// no 12
optional MobileAlertResponse f13 = 13;
// no 14-17
optional BLEPeripheralResponse f18 = 18;
optional int64 f19 = 19;
optional string f20 = 20;
optional bytes f21 = 21;
optional BLEAdvertisement f22 = 22;
}
message PhoneToGame {
required int64 player_id = 1;
repeated PhoneToGameCommand command = 2;
optional float f3 = 3;
optional float f4 = 4;
optional float f5 = 5;
optional float f6 = 6;
optional float f7 = 7;
optional float f8 = 8;
optional double f9 = 9;
optional int32 f10 = 10;
}*/

View File

@@ -2,6 +2,7 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: tcp-node-msgs.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import enum_type_wrapper
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import message as _message
@@ -14,81 +15,46 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13tcp-node-msgs.proto\"A\n\rServerDetails\x12\n\n\x02\x66\x31\x18\x01 \x02(\x05\x12\n\n\x02\x66\x32\x18\x02 \x02(\x05\x12\n\n\x02ip\x18\x03 \x02(\t\x12\x0c\n\x04port\x18\x04 \x02(\x05\"S\n\x0cServersType1\x12\x1f\n\x07\x64\x65tails\x18\x01 \x03(\x0b\x32\x0e.ServerDetails\x12\n\n\x02\x66\x32\x18\x02 \x01(\x05\x12\n\n\x02\x66\x33\x18\x03 \x01(\x05\x12\n\n\x02\x66\x34\x18\x04 \x01(\x05\"Y\n\x1eServerConnectionDetailsWrapper\x12\n\n\x02\x66\x31\x18\x01 \x02(\x05\x12\n\n\x02\x66\x32\x18\x02 \x02(\x05\x12\x1f\n\x07\x64\x65tails\x18\x03 \x03(\x0b\x32\x0e.ServerDetails\"V\n\x0cServersType2\x12\x38\n\x0f\x64\x65tails_wrapper\x18\x01 \x03(\x0b\x32\x1f.ServerConnectionDetailsWrapper\x12\x0c\n\x04port\x18\x02 \x02(\x05\"\x80\x01\n\rTCPServerInfo\x12\n\n\x02\x66\x31\x18\x01 \x01(\x05\x12\x11\n\tplayer_id\x18\x02 \x02(\x05\x12\n\n\x02\x66\x33\x18\x03 \x02(\x05\x12\x1e\n\x07servers\x18\x18 \x03(\x0b\x32\r.ServersType1\x12$\n\rother_servers\x18\x19 \x03(\x0b\x32\r.ServersType2\"\x1d\n\x08TCPHello\x12\x11\n\tplayer_id\x18\x02 \x02(\x05\"N\n\x14RecurringTCPResponse\x12\n\n\x02\x66\x31\x18\x01 \x01(\x05\x12\x11\n\tplayer_id\x18\x02 \x01(\x05\x12\n\n\x02\x66\x33\x18\x03 \x01(\x05\x12\x0b\n\x03\x66\x31\x31\x18\x0b \x01(\x05')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13tcp-node-msgs.proto\"\x9a\x02\n\x12SocialPlayerAction\x12\x11\n\tplayer_id\x18\x01 \x01(\x03\x12\x14\n\x0cto_player_id\x18\x02 \x01(\x03\x12)\n\x08spa_type\x18\x03 \x01(\x0e\x32\x17.SocialPlayerActionType\x12\x11\n\tfirstName\x18\x04 \x01(\t\x12\x10\n\x08lastName\x18\x05 \x01(\t\x12\x0f\n\x07message\x18\x06 \x01(\t\x12\x0e\n\x06\x61vatar\x18\x07 \x01(\t\x12\x13\n\x0b\x63ountryCode\x18\x08 \x01(\x05\x12\x1b\n\x08\x66lagType\x18\t \x01(\x0e\x32\t.FlagType\x12!\n\x06mgType\x18\n \x01(\x0e\x32\x11.MessageGroupType\x12\x15\n\reventSubgroup\x18\x0b \x01(\x03*v\n\x16SocialPlayerActionType\x12\x1e\n\x1aSOCIAL_ACTION_UNKNOWN_TYPE\x10\x00\x12\x17\n\x13SOCIAL_TEXT_MESSAGE\x10\x01\x12\x12\n\x0eSOCIAL_RIDE_ON\x10\x02\x12\x0f\n\x0bSOCIAL_FLAG\x10\x03*l\n\x08\x46lagType\x12\x15\n\x11\x46LAG_TYPE_UNKNOWN\x10\x00\x12\x18\n\x14\x46LAG_TYPE_HARASSMENT\x10\x01\x12\x13\n\x0f\x46LAG_TYPE_FLIER\x10\x02\x12\x1a\n\x16\x46LAG_TYPE_BAD_LANGUAGE\x10\x03*`\n\x10MessageGroupType\x12\x0f\n\x0bMGT_UNKNOWN\x10\x00\x12\x0e\n\nMGT_GLOBAL\x10\x01\x12\x0e\n\nMGT_DIRECT\x10\x02\x12\r\n\tMGT_EVENT\x10\x03\x12\x0c\n\x08MGT_CLUB\x10\x04')
_SOCIALPLAYERACTIONTYPE = DESCRIPTOR.enum_types_by_name['SocialPlayerActionType']
SocialPlayerActionType = enum_type_wrapper.EnumTypeWrapper(_SOCIALPLAYERACTIONTYPE)
_FLAGTYPE = DESCRIPTOR.enum_types_by_name['FlagType']
FlagType = enum_type_wrapper.EnumTypeWrapper(_FLAGTYPE)
_MESSAGEGROUPTYPE = DESCRIPTOR.enum_types_by_name['MessageGroupType']
MessageGroupType = enum_type_wrapper.EnumTypeWrapper(_MESSAGEGROUPTYPE)
SOCIAL_ACTION_UNKNOWN_TYPE = 0
SOCIAL_TEXT_MESSAGE = 1
SOCIAL_RIDE_ON = 2
SOCIAL_FLAG = 3
FLAG_TYPE_UNKNOWN = 0
FLAG_TYPE_HARASSMENT = 1
FLAG_TYPE_FLIER = 2
FLAG_TYPE_BAD_LANGUAGE = 3
MGT_UNKNOWN = 0
MGT_GLOBAL = 1
MGT_DIRECT = 2
MGT_EVENT = 3
MGT_CLUB = 4
_SERVERDETAILS = DESCRIPTOR.message_types_by_name['ServerDetails']
_SERVERSTYPE1 = DESCRIPTOR.message_types_by_name['ServersType1']
_SERVERCONNECTIONDETAILSWRAPPER = DESCRIPTOR.message_types_by_name['ServerConnectionDetailsWrapper']
_SERVERSTYPE2 = DESCRIPTOR.message_types_by_name['ServersType2']
_TCPSERVERINFO = DESCRIPTOR.message_types_by_name['TCPServerInfo']
_TCPHELLO = DESCRIPTOR.message_types_by_name['TCPHello']
_RECURRINGTCPRESPONSE = DESCRIPTOR.message_types_by_name['RecurringTCPResponse']
ServerDetails = _reflection.GeneratedProtocolMessageType('ServerDetails', (_message.Message,), {
'DESCRIPTOR' : _SERVERDETAILS,
_SOCIALPLAYERACTION = DESCRIPTOR.message_types_by_name['SocialPlayerAction']
SocialPlayerAction = _reflection.GeneratedProtocolMessageType('SocialPlayerAction', (_message.Message,), {
'DESCRIPTOR' : _SOCIALPLAYERACTION,
'__module__' : 'tcp_node_msgs_pb2'
# @@protoc_insertion_point(class_scope:ServerDetails)
# @@protoc_insertion_point(class_scope:SocialPlayerAction)
})
_sym_db.RegisterMessage(ServerDetails)
ServersType1 = _reflection.GeneratedProtocolMessageType('ServersType1', (_message.Message,), {
'DESCRIPTOR' : _SERVERSTYPE1,
'__module__' : 'tcp_node_msgs_pb2'
# @@protoc_insertion_point(class_scope:ServersType1)
})
_sym_db.RegisterMessage(ServersType1)
ServerConnectionDetailsWrapper = _reflection.GeneratedProtocolMessageType('ServerConnectionDetailsWrapper', (_message.Message,), {
'DESCRIPTOR' : _SERVERCONNECTIONDETAILSWRAPPER,
'__module__' : 'tcp_node_msgs_pb2'
# @@protoc_insertion_point(class_scope:ServerConnectionDetailsWrapper)
})
_sym_db.RegisterMessage(ServerConnectionDetailsWrapper)
ServersType2 = _reflection.GeneratedProtocolMessageType('ServersType2', (_message.Message,), {
'DESCRIPTOR' : _SERVERSTYPE2,
'__module__' : 'tcp_node_msgs_pb2'
# @@protoc_insertion_point(class_scope:ServersType2)
})
_sym_db.RegisterMessage(ServersType2)
TCPServerInfo = _reflection.GeneratedProtocolMessageType('TCPServerInfo', (_message.Message,), {
'DESCRIPTOR' : _TCPSERVERINFO,
'__module__' : 'tcp_node_msgs_pb2'
# @@protoc_insertion_point(class_scope:TCPServerInfo)
})
_sym_db.RegisterMessage(TCPServerInfo)
TCPHello = _reflection.GeneratedProtocolMessageType('TCPHello', (_message.Message,), {
'DESCRIPTOR' : _TCPHELLO,
'__module__' : 'tcp_node_msgs_pb2'
# @@protoc_insertion_point(class_scope:TCPHello)
})
_sym_db.RegisterMessage(TCPHello)
RecurringTCPResponse = _reflection.GeneratedProtocolMessageType('RecurringTCPResponse', (_message.Message,), {
'DESCRIPTOR' : _RECURRINGTCPRESPONSE,
'__module__' : 'tcp_node_msgs_pb2'
# @@protoc_insertion_point(class_scope:RecurringTCPResponse)
})
_sym_db.RegisterMessage(RecurringTCPResponse)
_sym_db.RegisterMessage(SocialPlayerAction)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
_SERVERDETAILS._serialized_start=23
_SERVERDETAILS._serialized_end=88
_SERVERSTYPE1._serialized_start=90
_SERVERSTYPE1._serialized_end=173
_SERVERCONNECTIONDETAILSWRAPPER._serialized_start=175
_SERVERCONNECTIONDETAILSWRAPPER._serialized_end=264
_SERVERSTYPE2._serialized_start=266
_SERVERSTYPE2._serialized_end=352
_TCPSERVERINFO._serialized_start=355
_TCPSERVERINFO._serialized_end=483
_TCPHELLO._serialized_start=485
_TCPHELLO._serialized_end=514
_RECURRINGTCPRESPONSE._serialized_start=516
_RECURRINGTCPRESPONSE._serialized_end=594
_SOCIALPLAYERACTIONTYPE._serialized_start=308
_SOCIALPLAYERACTIONTYPE._serialized_end=426
_FLAGTYPE._serialized_start=428
_FLAGTYPE._serialized_end=536
_MESSAGEGROUPTYPE._serialized_start=538
_MESSAGEGROUPTYPE._serialized_end=634
_SOCIALPLAYERACTION._serialized_start=24
_SOCIALPLAYERACTION._serialized_end=306
# @@protoc_insertion_point(module_scope)

View File

@@ -1,124 +1,265 @@
syntax = "proto2";
import "profile.proto"; //enums PlayerType and Sport
import "per-session-info.proto"; //TcpConfig
enum ZofflineConstants {
RealmID = 1; // hardcoded in ZwiftApp=1 (g_CurrentServerRealmID, 0: never connected; -1: disconnected)
}
enum WA_TYPE {
WAT_LEAVE = 2; //proto::PlayerLeftWorld
WAT_RELOGIN = 3; //proto::PlayerLeftWorld
WAT_RIDE_ON = 4; //proto::RideOn
WAT_SPA = 5; //proto::SocialPlayerAction (chat message)
WAT_EVENT = 6; //proto::Event
WAT_JOIN_E = 7; //proto::PlayerJoinedEvent
WAT_LEFT_E = 8; //proto::PlayerLeftEvent
WAT_RQ_PROF = 9; //proto::RequestProfileFromServer
WAT_INV_W = 10; //proto::ReceiveInvitationWorldAttribute
WAT_KICKED = 11; //no payload
WAT_WTIME = 100; //g_WorldTime := payload (GOD message, may be ignored if ZWIFT\CONFIG\IGNOREGODMESSAGES=1)
WAT_RTIME = 101; //BlimpEntity::SetRoadTime(payload), also GOD message
WAT_B_ACT = 102; //BikeEntity::PerformAction(payload)
WAT_GRP_M = 103; //GroupMessage (may be ignored if ZWIFT\CONFIG\SHOWGROUPMSGS=1)
WAT_PRI_M = 104; //PrivateMessage
WAT_SR = 105; //proto::SegmentResult
WAT_FLAG = 106; //Leaderboards::FlagSandbagger / Leaderboards::FlagCheater
WAT_NONE = 107; //does nothing
WAT_RLA = 108; //ZNETWORK_BroadcastRideLeaderAction
WAT_GE = 109; //GroupEvents::UserSignedup / GroupEvents::UserRegistered
WAT_NM = 110; //notable moment + Play_Magic_Whoosh_Deep_Sparkle
WAT_LATE = 111; //ZNETWORK_INTERNAL_HandleLateJoinRequest
WAT_RH = 112; //ZNETWORK_INTERNAL_HandleRouteHashRequest
WAT_STATS = 113; //GLOBAL_MESSAGE_TYPE_RIDER_FENCE_STATS
WAT_FENCE = 114; //GLOBAL_MESSAGE_TYPE_GRFENCE_CONFIG
WAT_BN_GE = 115; //ZNETWORK_BroadcastBibNumberForGroupEvent
WAT_PPI = 116; //ZNETWORK_INTERNAL_HandlePacePartnerInfo
}
message WorldAttribute {
optional int64 wa_f1 = 1; //not r/w by game? 587645624533328784, later 5876456 85771834256
optional int64 server_realm = 2;
optional WA_TYPE wa_type = 3;
optional bytes payload = 4; //not only protobuf
optional int64 world_time_born = 5;
optional int64 x = 6; //stored as int32
optional int64 y_altitude = 7; //stored as int32
optional int64 z = 8; //stored as int32
optional int64 world_time_expire = 9;
optional int64 rel_id = 10; //WAT_PPI: pace partner smth; WAT_SPA: to_player_id; WAT_RH: route_id? ...
optional int32 importance = 11; //not read by game??? WAT_B_ACT:1000; WAT_NM:50000; WAT_RH:5000000; ... 75000 ?
optional int64 wa_f12 = 12; //not r/w by game? Not in package when testing
optional int32 wa_f13 = 13; //not r/w by game?
optional int64 timestamp = 14; //not written by game? (from server) looks like "The Current Epoch Unix Timestamp" in Microseconds
optional int32 wa_f15 = 15; //not r/w by game? 6, might be course
optional int64 wa_f16 = 16; //not r/w by game? stored as bool
}
/*message WorldAttributes {
repeated WorldAttribute world_attributes = 1;
required int64 world_time = 2;
}
message World { //zwift.protobuf.World
required uint64 id = 1;
required string name = 2;
required uint64 w_f3 = 3;
optional bool w_f4 = 4;
required uint64 w_f5 = 5;
required uint64 world_time = 6;
required uint64 real_time = 7;
repeated Player w_f8 = 8;
}
message Player {
optional PlayerProfile player_profile = 1;
optional PlayerState player_state = 2;
}*/
message PlayerState {
optional int32 id = 1;
optional int64 worldTime = 2;
optional int32 distance = 3;
required int32 roadTime = 4;
optional int64 id = 1;
optional int64 worldTime = 2; // milliseconds
optional int32 distance = 3; // meters
optional int32 roadTime = 4; // 1/100 sec
optional int32 laps = 5;
optional int32 speed = 6;
optional uint32 speed = 6; // millimeters per hour
optional uint32 ps_f7 = 7;
optional int32 roadPosition = 8;
optional int32 cadenceUHz = 9;
optional int32 cadenceUHz = 9; // =(cad / 60) * 1000000
optional int32 ps_f10 = 10; // BikeEntity.field_B58; 0
optional int32 heartrate = 11;
optional int32 power = 12;
optional int64 heading = 13;
optional int32 lean = 14;
optional int32 climbing = 15;
optional int32 time = 16;
optional int32 f19 = 19;
optional int32 f20 = 20;
optional int32 progress = 21;
optional int64 customisationId = 22;
optional int32 justWatching = 23;
optional int64 lean = 14;
optional int32 climbing = 15; // meters
optional int32 time = 16; // seconds
optional int32 ps_f17 = 17;
optional uint32 frameHue = 18; // BikeEntity::DrawBike m_frameHue * 255.0
//field 19:
//byte[0].bits[0,1]: HasPowerMeter, HasPhoneConnected
//byte[0].bits[2,3]: RoadDirectionForward, ??? !BikeEntity.field_DCC || BikeEntity.disSteer
//byte[0].bits[4]: read in BikeEntity::ProcessNewPacket, steering-related
//byte[1]: =0 ???
//byte[2]: fallback course/getMapRevisionId
//byte[3]: realRideons (not counted yet in BikeEntity::m_rideons) @ BikeEntity::UpdateRideOns, see also BikeEntity::Update
optional uint32 f19 = 19;
optional uint32 f20 = 20; //road_id: (f20 & 0xff00) >> 8 (=16777231 -> road_id = 0)
optional uint32 progress = 21; // WorkoutMode = progress & 0xF
optional int64 customizationId = 22;
optional bool justWatching = 23;
optional int32 calories = 24;
optional float x = 25;
optional float altitude = 26;
optional float y = 27;
optional int32 watchingRiderId = 28;
optional int32 groupId = 29;
optional int64 sport = 31;
optional float f34 = 34;
optional float y_altitude = 26;
optional float z = 27;
optional int64 watchingRiderId = 28;
optional int64 groupId = 29;
// 30 absent at least in Android Game
optional Sport sport = 31;
optional float ps_f32 = 32;
optional uint32 ps_f33 = 33;
optional float ps_f34 = 34; //= BikeEntity.field_F00 (=219.56387 and incr if moving)
optional int32 world = 35;
optional int32 f38 = 38;
optional uint64 route = 39;
optional uint32 ps_f36 = 36; // = f(BikeEntity.field_2a28) BikeEntity::CreateNewPacket
optional uint32 ps_f37 = 37; // = f(BikeEntity.field_2a28) BikeEntity::CreateNewPacket
optional bool canSteer = 38; // = BikeEntity.m_canSteer
optional int32 route = 39;
}
message ClientToServer {
required int32 connected = 1;
required int32 player_id = 2;
required int64 world_time = 3;
required int32 seqno = 4;
required int64 server_realm = 1; //UdpClient::sendDisconnectedClientToServer: -1. Otherwise g_CurrentServerRealmID (RealmID or 0 if not connected yet)
required int64 player_id = 2;
optional int64 world_time = 3;
optional uint32 seqno = 4;
optional uint32 cts_f5 = 5;
optional int64 cts_f6 = 6;
required PlayerState state = 7;
required int64 f8 = 8;
required int64 f9 = 9;
optional bool cts_f8 = 8;
optional bool cts_f9 = 9;
required int64 last_update = 10;
required int64 f11 = 11;
optional bool cts_f11 = 11;
required int64 last_player_update = 12;
optional int64 larg_wa_time = 13; //TcpClient::sayHello: LargestWorldAttributeTimestamp
optional bool cts_f14 = 14;
repeated int64 subsSegments = 15; //subscribed segment ids? TcpClient::sayHello, TcpClient::sendSubscribeToSegment
repeated int64 unsSegments = 16; //unsubscribed segment ids? TcpClient::processSegmentUnsubscription
}
message PlayerSummary {
optional int32 plsu_f1 = 1;
optional int32 plsu_f2 = 2;
optional int32 plsu_f3 = 3;
optional int32 plsu_f4 = 4;
}
message PlayerSummaries {
optional sint64 plsus_f1 = 1; //stored as int32
optional sint64 plsus_f2 = 2; //stored as int32
optional sint32 plsus_f3 = 3;
optional sint32 plsus_f4 = 4;
optional int32 plsus_f5 = 5;
optional int32 plsus_f6 = 6;
optional int32 plsus_f7 = 7;
repeated PlayerSummary player_summaries = 8;
}
message RelayAddress {
optional int32 lb_realm = 1; // load balancing cluster: server realm or 0 (generic)
optional int32 lb_course = 2; // load balancing cluster: course id
optional string ip = 3;
optional int32 port = 4;
optional float ra_f5 = 5; //or fixed
optional float ra_f6 = 6; //or fixed
}
message UdpConfig {
repeated RelayAddress relay_addresses = 1;
optional int32 uc_f2 = 2; //=10?
optional int32 uc_f3 = 3; //=30?
optional int32 uc_f4 = 4; //=3?
}
message RelayAddressesVOD {
optional int32 lb_realm = 1; // load balancing cluster: server realm or 0 (generic)
optional int32 lb_course = 2; // load balancing cluster: course id
repeated RelayAddress relay_addresses = 3;
optional bool rav_f4 = 4;
}
message UdpConfigVOD {
repeated RelayAddressesVOD relay_addresses_vod = 1;
optional int32 port = 2;
optional int64 ucv_f3 = 3;
optional int64 ucv_f4 = 4;
optional float ucv_f5 = 5; //or fixed
optional float ucv_f6 = 6; //or fixed
}
message PlayerRouteDistance {
optional int32 bikeId = 1; //BikeManager::FindBikeWithNetworkID
optional float prd_f2 = 2; //or fixed
optional int32 prd_f3 = 3; //-> m_bikeEntity->field_9C8
}
message EventSubgroupPlacements {
optional int32 esp_f1 = 1; //-> m_bikeEntity->field_9C0; UdpStatistics::registerFanViewLatestPlayerStateInfo
repeated PlayerRouteDistance player_rd1 = 2;
repeated PlayerRouteDistance player_rd2 = 3;
repeated PlayerRouteDistance player_rd3 = 4;
repeated PlayerRouteDistance player_rd4 = 5;
optional int32 eventTotalRiders = 6;
optional int32 bikeNetworkId = 7;
optional int32 esp_f8 = 8; //-> BikeWithNetworkID->field_9C8
optional float esp_f9 = 9; //or fixed
}
enum IPProtocol {
UDP = 1;
TCP = 2;
}
message ServerToClient {
required int32 f1 = 1;
required int32 player_id = 2;
required int64 world_time = 3;
optional int64 server_realm = 1;
optional int64 player_id = 2;
optional int64 world_time = 3;
optional int32 seqno = 4;
optional int32 f5 = 5;
optional int32 stc_f5 = 5; //read in WorldClockService::calculateOneLegLatency
// 6,7: absent
repeated PlayerState states = 8;
repeated PlayerUpdate updates = 9;
optional int64 f11 = 11;
repeated WorldAttribute updates = 9;
repeated int64 stc_f10 = 10;
optional bool stc_f11 = 11; //=true???
optional string zc_local_ip = 12;
optional int64 stc_f13 = 13;
optional int32 zwifters = 14;
optional int32 zc_local_port = 15;
optional IPProtocol zc_protocol = 16; //TODO: enum; 2: TCP
optional int64 stc_f17 = 17; //read in WorldClockService::calculateOneLegLatency
optional int32 num_msgs = 18;
optional int32 msgnum = 19;
optional bool hasSimultLogin = 20; //UdpClient::disconnectionRequested due to simultaneous login (1); OR simultaneous login ceased (0)
optional PlayerSummaries player_summaries = 21; //tag426
// 22 absent
optional EventSubgroupPlacements ev_subgroup_ps = 23; //tag442
optional UdpConfig udp_config = 24; //tag450
optional UdpConfigVOD udp_config_vod_1 = 25; //tag458
optional int32 stc_f26 = 26; //tag464 UdpClient::receivedExpungeReason
optional UdpConfigVOD udp_config_vod_2 = 27; //tag474
repeated PlayerState player_states = 28; //tag482
optional TcpConfig tcp_config = 29; //tag490
repeated int64 ackSubsSegm = 30; //tag496 TcpClient::processSubscribedSegment
}
message Ghost {
message Ghost { //not from the Zwift game, zoffline-specific!
required int32 player_id = 1;
repeated PlayerState states = 2;
}
message Ghosts {
message Ghosts { //not from the Zwift game, zoffline-specific!
repeated Ghost ghosts = 1;
}
message PlayerUpdate {
optional int64 f1 = 1; // 587645624533328784, later 5876456 85771834256
optional int32 f2 = 2; // 1
required int32 type = 3; // 105 entered world, 5 chat message, 4 ride on
required bytes payload = 4; // protobuf
optional int64 world_time1 = 5;
optional int64 x = 6;
optional int64 altitude = 7;
optional int64 y = 8;
optional int64 world_time2 = 9;
optional int64 f11 = 11; // 75000 ?
optional int64 f12 = 12; //Not in package when testing
optional int64 f14 = 14; // '1604516817408239', later '1604516824709874'
optional int64 f15 = 15; //6, might be course
}
message ChatMessage {
required int32 rider_id = 1;
required int32 to_rider_id = 2; // 0 if public message
required int32 f3 = 3; // always value 1 ?
required string firstName = 4;
required string lastName = 5;
required string message = 6;
optional string avatar = 7;
required int32 countryCode = 8;
optional int32 eventSubgroup = 11;
}
message RideOn {
required int32 rider_id = 1;
required int32 to_rider_id = 2;
required int64 player_id = 1;
required int64 to_player_id = 2;
required string firstName = 3;
required string lastName = 4;
required int32 countryCode = 5;
}
message SegmentComplete {
optional int64 f1 = 1;
required int32 rider_id = 2;
optional int32 f3 = 3;
optional int64 f4 = 4;
optional int64 segment_id = 5;
optional int64 f6 = 6;
optional string first_name = 7;
optional string last_name = 8;
optional int64 world_time = 9;
optional int64 milliseconds = 11;
optional int32 f12 = 12;
optional int32 weight_in_grams = 13;
optional int32 f14 = 14;
optional int32 avg_power = 15;
optional int32 f16 = 16;
optional string f7date = 17;
optional int32 f19 = 19;
}

File diff suppressed because one or more lines are too long

View File

@@ -1,43 +1,43 @@
syntax = "proto2";
message World {
required uint32 id = 1;
required string name = 2;
required uint32 f3 = 3;
/* missing 4 */
required uint64 f5 = 5;
required uint64 world_time = 6;
required uint64 real_time = 7;
repeated Player player_states = 8;
repeated Player pace_partner_states = 12;
import "profile.proto"; //enums PlayerType and Sport
message DropInWorld {
required uint64 id = 1;
optional string name = 2;
optional uint64 course_id = 3;
optional bool f4 = 4;
optional uint64 zwifters = 5;
optional uint64 world_time = 6;
optional uint64 real_time = 7;
repeated DropInPlayer pro_players = 8;
repeated DropInPlayer followees = 9;
repeated DropInPlayer others = 10;
optional uint64 max_zwifters = 11; //stored as int32
repeated DropInPlayer pacer_bots = 12;
}
message Worlds {
repeated World worlds = 1;
message DropInWorldList {
repeated DropInWorld worlds = 1;
}
message WorldAttributes {
/* repeated RiderAttributes riders = 1; */
required int64 world_time = 2;
}
message Player {
required uint32 id = 1;
message DropInPlayer {
required uint64 id = 1;
required string firstName = 2;
required string lastName = 3;
optional uint32 distance = 4;
optional uint32 time = 5;
optional uint32 f6 = 6;
optional uint32 f7 = 7;
optional uint32 f8 = 8;
optional uint32 f9 = 9;
optional uint32 f10 = 10;
optional uint32 f11 = 11;
optional uint32 power = 12;
optional uint32 f13 = 13;
optional uint64 distance = 4;
optional uint64 time = 5;
optional uint64 country_code = 6;
optional PlayerType player_type = 7;
optional Sport sport = 8;
optional bool f9 = 9;
optional bool f10 = 10;
optional uint64 f11 = 11;
optional uint64 power = 12;
optional uint64 f13 = 13;
optional float x = 14;
optional float altitude = 15;
optional float y = 16;
optional uint64 route = 17;
optional uint32 f18 = 18;
optional uint32 f19 = 19;
optional float y_altitude = 15;
optional float z = 16;
optional int32 route = 17;
optional uint32 ride_power = 18;
optional uint32 speed = 19;
}

View File

@@ -12,53 +12,44 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default()
import profile_pb2 as profile__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0bworld.proto\"\xa6\x01\n\x05World\x12\n\n\x02id\x18\x01 \x02(\r\x12\x0c\n\x04name\x18\x02 \x02(\t\x12\n\n\x02\x66\x33\x18\x03 \x02(\r\x12\n\n\x02\x66\x35\x18\x05 \x02(\x04\x12\x12\n\nworld_time\x18\x06 \x02(\x04\x12\x11\n\treal_time\x18\x07 \x02(\x04\x12\x1e\n\rplayer_states\x18\x08 \x03(\x0b\x32\x07.Player\x12$\n\x13pace_partner_states\x18\x0c \x03(\x0b\x32\x07.Player\" \n\x06Worlds\x12\x16\n\x06worlds\x18\x01 \x03(\x0b\x32\x06.World\"%\n\x0fWorldAttributes\x12\x12\n\nworld_time\x18\x02 \x02(\x03\"\x90\x02\n\x06Player\x12\n\n\x02id\x18\x01 \x02(\r\x12\x11\n\tfirstName\x18\x02 \x02(\t\x12\x10\n\x08lastName\x18\x03 \x02(\t\x12\x10\n\x08\x64istance\x18\x04 \x01(\r\x12\x0c\n\x04time\x18\x05 \x01(\r\x12\n\n\x02\x66\x36\x18\x06 \x01(\r\x12\n\n\x02\x66\x37\x18\x07 \x01(\r\x12\n\n\x02\x66\x38\x18\x08 \x01(\r\x12\n\n\x02\x66\x39\x18\t \x01(\r\x12\x0b\n\x03\x66\x31\x30\x18\n \x01(\r\x12\x0b\n\x03\x66\x31\x31\x18\x0b \x01(\r\x12\r\n\x05power\x18\x0c \x01(\r\x12\x0b\n\x03\x66\x31\x33\x18\r \x01(\r\x12\t\n\x01x\x18\x0e \x01(\x02\x12\x10\n\x08\x61ltitude\x18\x0f \x01(\x02\x12\t\n\x01y\x18\x10 \x01(\x02\x12\r\n\x05route\x18\x11 \x01(\x04\x12\x0b\n\x03\x66\x31\x38\x18\x12 \x01(\r\x12\x0b\n\x03\x66\x31\x39\x18\x13 \x01(\r')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0bworld.proto\x1a\rprofile.proto\"\x9d\x02\n\x0b\x44ropInWorld\x12\n\n\x02id\x18\x01 \x02(\x04\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\tcourse_id\x18\x03 \x01(\x04\x12\n\n\x02\x66\x34\x18\x04 \x01(\x08\x12\x10\n\x08zwifters\x18\x05 \x01(\x04\x12\x12\n\nworld_time\x18\x06 \x01(\x04\x12\x11\n\treal_time\x18\x07 \x01(\x04\x12\"\n\x0bpro_players\x18\x08 \x03(\x0b\x32\r.DropInPlayer\x12 \n\tfollowees\x18\t \x03(\x0b\x32\r.DropInPlayer\x12\x1d\n\x06others\x18\n \x03(\x0b\x32\r.DropInPlayer\x12\x14\n\x0cmax_zwifters\x18\x0b \x01(\x04\x12!\n\npacer_bots\x18\x0c \x03(\x0b\x32\r.DropInPlayer\"/\n\x0f\x44ropInWorldList\x12\x1c\n\x06worlds\x18\x01 \x03(\x0b\x32\x0c.DropInWorld\"\xcc\x02\n\x0c\x44ropInPlayer\x12\n\n\x02id\x18\x01 \x02(\x04\x12\x11\n\tfirstName\x18\x02 \x02(\t\x12\x10\n\x08lastName\x18\x03 \x02(\t\x12\x10\n\x08\x64istance\x18\x04 \x01(\x04\x12\x0c\n\x04time\x18\x05 \x01(\x04\x12\x14\n\x0c\x63ountry_code\x18\x06 \x01(\x04\x12 \n\x0bplayer_type\x18\x07 \x01(\x0e\x32\x0b.PlayerType\x12\x15\n\x05sport\x18\x08 \x01(\x0e\x32\x06.Sport\x12\n\n\x02\x66\x39\x18\t \x01(\x08\x12\x0b\n\x03\x66\x31\x30\x18\n \x01(\x08\x12\x0b\n\x03\x66\x31\x31\x18\x0b \x01(\x04\x12\r\n\x05power\x18\x0c \x01(\x04\x12\x0b\n\x03\x66\x31\x33\x18\r \x01(\x04\x12\t\n\x01x\x18\x0e \x01(\x02\x12\x12\n\ny_altitude\x18\x0f \x01(\x02\x12\t\n\x01z\x18\x10 \x01(\x02\x12\r\n\x05route\x18\x11 \x01(\x05\x12\x12\n\nride_power\x18\x12 \x01(\r\x12\r\n\x05speed\x18\x13 \x01(\r')
_WORLD = DESCRIPTOR.message_types_by_name['World']
_WORLDS = DESCRIPTOR.message_types_by_name['Worlds']
_WORLDATTRIBUTES = DESCRIPTOR.message_types_by_name['WorldAttributes']
_PLAYER = DESCRIPTOR.message_types_by_name['Player']
World = _reflection.GeneratedProtocolMessageType('World', (_message.Message,), {
'DESCRIPTOR' : _WORLD,
_DROPINWORLD = DESCRIPTOR.message_types_by_name['DropInWorld']
_DROPINWORLDLIST = DESCRIPTOR.message_types_by_name['DropInWorldList']
_DROPINPLAYER = DESCRIPTOR.message_types_by_name['DropInPlayer']
DropInWorld = _reflection.GeneratedProtocolMessageType('DropInWorld', (_message.Message,), {
'DESCRIPTOR' : _DROPINWORLD,
'__module__' : 'world_pb2'
# @@protoc_insertion_point(class_scope:World)
# @@protoc_insertion_point(class_scope:DropInWorld)
})
_sym_db.RegisterMessage(World)
_sym_db.RegisterMessage(DropInWorld)
Worlds = _reflection.GeneratedProtocolMessageType('Worlds', (_message.Message,), {
'DESCRIPTOR' : _WORLDS,
DropInWorldList = _reflection.GeneratedProtocolMessageType('DropInWorldList', (_message.Message,), {
'DESCRIPTOR' : _DROPINWORLDLIST,
'__module__' : 'world_pb2'
# @@protoc_insertion_point(class_scope:Worlds)
# @@protoc_insertion_point(class_scope:DropInWorldList)
})
_sym_db.RegisterMessage(Worlds)
_sym_db.RegisterMessage(DropInWorldList)
WorldAttributes = _reflection.GeneratedProtocolMessageType('WorldAttributes', (_message.Message,), {
'DESCRIPTOR' : _WORLDATTRIBUTES,
DropInPlayer = _reflection.GeneratedProtocolMessageType('DropInPlayer', (_message.Message,), {
'DESCRIPTOR' : _DROPINPLAYER,
'__module__' : 'world_pb2'
# @@protoc_insertion_point(class_scope:WorldAttributes)
# @@protoc_insertion_point(class_scope:DropInPlayer)
})
_sym_db.RegisterMessage(WorldAttributes)
Player = _reflection.GeneratedProtocolMessageType('Player', (_message.Message,), {
'DESCRIPTOR' : _PLAYER,
'__module__' : 'world_pb2'
# @@protoc_insertion_point(class_scope:Player)
})
_sym_db.RegisterMessage(Player)
_sym_db.RegisterMessage(DropInPlayer)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
_WORLD._serialized_start=16
_WORLD._serialized_end=182
_WORLDS._serialized_start=184
_WORLDS._serialized_end=216
_WORLDATTRIBUTES._serialized_start=218
_WORLDATTRIBUTES._serialized_end=255
_PLAYER._serialized_start=258
_PLAYER._serialized_end=530
_DROPINWORLD._serialized_start=31
_DROPINWORLD._serialized_end=316
_DROPINWORLDLIST._serialized_start=318
_DROPINWORLDLIST._serialized_end=365
_DROPINPLAYER._serialized_start=368
_DROPINPLAYER._serialized_end=700
# @@protoc_insertion_point(module_scope)

View File

@@ -1,7 +1,12 @@
syntax = "proto2";
message ZFile {
message ZFileProto {
required uint64 id = 1;
required string folder = 2;
required string filename = 3;
required uint64 timestamp = 4;
optional string f4 = 4; //NetworkClientImpl::generateZFileGzip: empty
required uint64 timestamp = 5;
}
message ZFilesProto {
repeated ZFileProto zfiles = 1;
}

View File

@@ -14,21 +14,31 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0czfiles.proto\"H\n\x05ZFile\x12\n\n\x02id\x18\x01 \x02(\x04\x12\x0e\n\x06\x66older\x18\x02 \x02(\t\x12\x10\n\x08\x66ilename\x18\x03 \x02(\t\x12\x11\n\ttimestamp\x18\x04 \x02(\x04')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0czfiles.proto\"Y\n\nZFileProto\x12\n\n\x02id\x18\x01 \x02(\x04\x12\x0e\n\x06\x66older\x18\x02 \x02(\t\x12\x10\n\x08\x66ilename\x18\x03 \x02(\t\x12\n\n\x02\x66\x34\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x02(\x04\"*\n\x0bZFilesProto\x12\x1b\n\x06zfiles\x18\x01 \x03(\x0b\x32\x0b.ZFileProto')
_ZFILE = DESCRIPTOR.message_types_by_name['ZFile']
ZFile = _reflection.GeneratedProtocolMessageType('ZFile', (_message.Message,), {
'DESCRIPTOR' : _ZFILE,
_ZFILEPROTO = DESCRIPTOR.message_types_by_name['ZFileProto']
_ZFILESPROTO = DESCRIPTOR.message_types_by_name['ZFilesProto']
ZFileProto = _reflection.GeneratedProtocolMessageType('ZFileProto', (_message.Message,), {
'DESCRIPTOR' : _ZFILEPROTO,
'__module__' : 'zfiles_pb2'
# @@protoc_insertion_point(class_scope:ZFile)
# @@protoc_insertion_point(class_scope:ZFileProto)
})
_sym_db.RegisterMessage(ZFile)
_sym_db.RegisterMessage(ZFileProto)
ZFilesProto = _reflection.GeneratedProtocolMessageType('ZFilesProto', (_message.Message,), {
'DESCRIPTOR' : _ZFILESPROTO,
'__module__' : 'zfiles_pb2'
# @@protoc_insertion_point(class_scope:ZFilesProto)
})
_sym_db.RegisterMessage(ZFilesProto)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
_ZFILE._serialized_start=16
_ZFILE._serialized_end=88
_ZFILEPROTO._serialized_start=16
_ZFILEPROTO._serialized_end=105
_ZFILESPROTO._serialized_start=107
_ZFILESPROTO._serialized_end=149
# @@protoc_insertion_point(module_scope)

View File

@@ -48,7 +48,7 @@ def file_exists(file):
PROFILE_FILE = 'profile.bin'
if file_exists(PROFILE_FILE):
p = profile_pb2.Profile()
p = profile_pb2.PlayerProfile()
with open(PROFILE_FILE, 'rb') as f:
p.ParseFromString(f.read())
p.first_name = input("First name: ")

View File

@@ -134,7 +134,7 @@ def get_player_id(session, access_token):
print('Response HTTP Status Code: {status_code}'.format(
status_code=response.status_code))
profile = profile_pb2.Profile()
profile = profile_pb2.PlayerProfile()
profile.ParseFromString(response.content)
return profile.id

View File

@@ -94,8 +94,8 @@ def save_ghost(name, player_id):
try:
if not os.path.isdir(folder):
os.makedirs(folder)
except:
return
except Exception as exc:
print('save_ghost: %s' % repr(exc))
f = '%s/%s-%s.bin' % (folder, zwift_offline.get_utc_date_time().strftime("%Y-%m-%d-%H-%M-%S"), name)
with open(f, 'wb') as fd:
fd.write(ghosts.rec.SerializeToString())
@@ -117,8 +117,8 @@ def organize_ghosts(player_id):
try:
if not os.path.isdir(dest):
os.makedirs(dest)
except:
return
except Exception as exc:
print('organize_ghosts: %s' % repr(exc))
os.rename(file, os.path.join(dest, f))
def load_ghosts(player_id, state, ghosts):
@@ -228,9 +228,10 @@ class CDNHandler(SimpleHTTPRequestHandler):
url = 'http://{}{}'.format(hostname, self.path)
req_header = self.parse_headers()
resp = requests.get(url, headers=merge_two_dicts(req_header, set_header()), verify=False)
except:
self.send_error(404, 'error trying to proxy')
return
except Exception as exc:
print('Error trying to proxy: %s' % repr(exc))
self.send_error(404, 'error trying to proxy')
return
self.send_response(resp.status_code)
self.send_resp_headers(resp)
self.wfile.write(resp.content)
@@ -257,18 +258,20 @@ class CDNHandler(SimpleHTTPRequestHandler):
class TCPHandler(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024)
hello = tcp_node_msgs_pb2.TCPHello()
#print("TCPHandler hello: %s" % self.data.hex())
hello = udp_node_msgs_pb2.ClientToServer()
try:
hello.ParseFromString(self.data[4:-4])
except:
hello.ParseFromString(self.data[4:-4]) #2 bytes: payload length, 1 byte: =0x1 (TcpClient::sendClientToServer) 1 byte: type; payload; 4 bytes: hash
#type: TcpClient::sayHello(=0x0), TcpClient::sendSubscribeToSegment(=0x1), TcpClient::processSegmentUnsubscription(=0x1)
except Exception as exc:
print('TCPHandler ParseFromString exception: %s' % repr(exc))
return
# send packet containing UDP server (127.0.0.1)
# (very little investigation done into this packet while creating
# protobuf structures hence the excessive "details" usage)
msg = tcp_node_msgs_pb2.TCPServerInfo()
msg = udp_node_msgs_pb2.ServerToClient()
msg.player_id = hello.player_id
msg.f3 = 0
servers = msg.servers.add()
msg.world_time = 0
if self.request.getpeername()[0] == '127.0.0.1': # to avoid needing hairpinning
udp_node_ip = "127.0.0.1"
elif os.path.exists(SERVER_IP_FILE):
@@ -276,41 +279,41 @@ class TCPHandler(socketserver.BaseRequestHandler):
udp_node_ip = f.read().rstrip('\r\n')
else:
udp_node_ip = "127.0.0.1"
details1 = servers.details.add()
details1.f1 = 1
details1.f2 = 6
details1 = msg.udp_config.relay_addresses.add()
details1.lb_realm = udp_node_msgs_pb2.ZofflineConstants.RealmID
details1.lb_course = 6 # watopia crowd
details1.ip = udp_node_ip
details1.port = 3022
details2 = servers.details.add()
details2.f1 = 0
details2.f2 = 0
details2 = msg.udp_config.relay_addresses.add()
details2.lb_realm = 0 #generic load balancing realm
details2.lb_course = 0 #generic load balancing course
details2.ip = udp_node_ip
details2.port = 3022
servers.f2 = 10
servers.f3 = 30
servers.f4 = 3
other_servers = msg.other_servers.add()
wdetails1 = other_servers.details_wrapper.add()
wdetails1.f1 = 1
wdetails1.f2 = 6
details3 = wdetails1.details.add()
msg.udp_config.uc_f2 = 10
msg.udp_config.uc_f3 = 30
msg.udp_config.uc_f4 = 3
wdetails1 = msg.udp_config_vod_1.relay_addresses_vod.add()
wdetails1.lb_realm = udp_node_msgs_pb2.ZofflineConstants.RealmID
wdetails1.lb_course = 6 # watopia crowd
details3 = wdetails1.relay_addresses.add()
details3.CopyFrom(details1)
wdetails2 = other_servers.details_wrapper.add()
wdetails2.f1 = 0
wdetails2.f2 = 0
details4 = wdetails2.details.add()
wdetails2 = msg.udp_config_vod_1.relay_addresses_vod.add()
wdetails2.lb_realm = 0 #generic load balancing realm
wdetails2.lb_course = 0 #generic load balancing course
details4 = wdetails2.relay_addresses.add()
details4.CopyFrom(details2)
other_servers.port = 3022
msg.udp_config_vod_1.port = 3022
payload = msg.SerializeToString()
# Send size of payload as 2 bytes
self.request.sendall(struct.pack('!h', len(payload)))
self.request.sendall(payload)
player_id = hello.player_id
msg = tcp_node_msgs_pb2.RecurringTCPResponse()
#print("TCPHandler for %d" % player_id)
msg = udp_node_msgs_pb2.ServerToClient()
msg.player_id = player_id
msg.f3 = 0
msg.f11 = 1
msg.world_time = 0
msg.stc_f11 = True
payload = msg.SerializeToString()
last_alive_check = int(zwift_offline.get_utc_time())
@@ -318,8 +321,25 @@ class TCPHandler(socketserver.BaseRequestHandler):
#Check every 5 seconds for new updates
tcpthreadevent.wait(timeout=5)
try:
t = int(zwift_offline.get_utc_time())
#if ZC need to be registered
if player_id in zwift_offline.zc_connect_queue: # and player_id in online:
zc_params = udp_node_msgs_pb2.ServerToClient()
zc_params.player_id = player_id
zc_params.world_time = 0
zc_params.zc_local_ip = zwift_offline.zc_connect_queue[player_id][0]
zc_params.zc_local_port = zwift_offline.zc_connect_queue[player_id][1] #21587
zc_params.zc_protocol = udp_node_msgs_pb2.IPProtocol.TCP #=2
zc_params_payload = zc_params.SerializeToString()
last_alive_check = t
self.request.sendall(struct.pack('!h', len(zc_params_payload)))
self.request.sendall(zc_params_payload)
#print("TCPHandler register_zc %d %s" % (player_id, zc_params_payload.hex()))
zwift_offline.zc_connect_queue.pop(player_id)
message = udp_node_msgs_pb2.ServerToClient()
message.f1 = 1
message.server_realm = udp_node_msgs_pb2.ZofflineConstants.RealmID
message.player_id = player_id
message.world_time = zwift_offline.world_time()
@@ -337,7 +357,7 @@ class TCPHandler(socketserver.BaseRequestHandler):
self.request.sendall(message_payload)
message = udp_node_msgs_pb2.ServerToClient()
message.f1 = 1
message.server_realm = udp_node_msgs_pb2.ZofflineConstants.RealmID
message.player_id = player_id
message.world_time = zwift_offline.world_time()
@@ -345,8 +365,6 @@ class TCPHandler(socketserver.BaseRequestHandler):
for player_update_proto in added_player_updates:
player_update_queue[player_id].remove(player_update_proto)
t = int(zwift_offline.get_utc_time())
#Check if any updates are added and should be sent to client, otherwise just keep alive every 25 seconds
if len(message.updates) > 0:
last_alive_check = t
@@ -357,7 +375,8 @@ class TCPHandler(socketserver.BaseRequestHandler):
last_alive_check = t
self.request.sendall(struct.pack('!h', len(payload)))
self.request.sendall(payload)
except:
except Exception as exc:
print('TCPHandler loop exception: %s' % repr(exc))
break
class GhostsVariables:
@@ -458,11 +477,11 @@ def remove_inactive():
def get_empty_message(player_id):
message = udp_node_msgs_pb2.ServerToClient()
message.f1 = 1
message.server_realm = udp_node_msgs_pb2.ZofflineConstants.RealmID
message.player_id = player_id
message.seqno = 1
message.f5 = 1
message.f11 = 1
message.stc_f5 = 1
message.stc_f11 = 1
message.msgnum = 1
return message
@@ -488,7 +507,8 @@ class UDPHandler(socketserver.BaseRequestHandler):
try:
#If no sensors connected, first byte must be skipped
recv.ParseFromString(data[1:-4])
except:
except Exception as exc:
print('UDPHandler ParseFromString exception: %s' % repr(exc))
return
client_address = self.client_address

View File

@@ -6,9 +6,9 @@ import sys
sys.modules['FixTk'] = None
a = Analysis(['standalone.py'],
pathex=['/home/alexvh/Code/zoffline'],
pathex=['protobuf'],
binaries=[],
datas=[('ssl/*', 'ssl'), ('initialize_db.sql', '.'), ('start_lines.csv', '.'), ('variants.txt', '.')],
datas=[('ssl/*', 'ssl'), ('initialize_db.sql', '.'), ('start_lines.csv', '.'), ('game_info.txt', '.'), ('variants.txt', '.')],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],

File diff suppressed because it is too large Load Diff