diff --git a/README.md b/README.md index 56c607e..f52424f 100644 --- a/README.md +++ b/README.md @@ -95,10 +95,10 @@ zoffline can be installed on the same machine as Zwift or another local machine.
Windows Instructions * Install Zwift - * If your Zwift version is 1.0.85684, you're all set. + * If your Zwift version is 1.0.100133, you're all set. * If Zwift is not installed, install it before installing zoffline. - * If your Zwift version is newer than 1.0.85684 and zoffline is running from source: copy ``C:\Program Files (x86)\Zwift\Zwift_ver_cur.xml`` to zoffline's ``cdn/gameassets/Zwift_Updates_Root/`` overwriting the existing file. - * If your Zwift version is newer than 1.0.85684 and zoffline is not running from source: wait for zoffline to be updated. + * If your Zwift version is newer than 1.0.100133 and zoffline is running from source: copy ``C:\Program Files (x86)\Zwift\Zwift_ver_cur.xml`` to zoffline's ``cdn/gameassets/Zwift_Updates_Root/`` overwriting the existing file. + * If your Zwift version is newer than 1.0.100133 and zoffline is not running from source: wait for zoffline to be updated. * __NOTE:__ instead of performing the steps below you can instead just run the __configure_client__ script from https://github.com/zoffline/zwift-offline/releases/tag/zoffline_helper * On your Windows machine running Zwift, copy the following files in this repo to a known location: * ``ssl/cert-zwift-com.p12`` @@ -124,9 +124,9 @@ to generate your own certificates and do the same.
Mac OS X Instructions * Install Zwift - * If your Zwift version is 1.0.85684, you're all set. + * If your Zwift version is 1.0.100118, you're all set. * If Zwift is not installed, install it before installing zoffline. - * If your Zwift version is newer than 1.0.85684: copy ``~/Library/Application Support/Zwift/ZwiftMac_ver_cur.xml`` to zoffline's ``cdn/gameassets/Zwift_Updates_Root/`` overwriting the existing file. + * If your Zwift version is newer than 1.0.100118: copy ``~/Library/Application Support/Zwift/ZwiftMac_ver_cur.xml`` to zoffline's ``cdn/gameassets/Zwift_Updates_Root/`` overwriting the existing file. * On your Mac machine running Zwift, copy the following files in this repo to a known location: * ``ssl/cert-zwift-com.p12`` * ``ssl/cert-zwift-com.pem`` diff --git a/cdn/gameassets/Zwift_Updates_Root/ZwiftMac_ver_cur.xml b/cdn/gameassets/Zwift_Updates_Root/ZwiftMac_ver_cur.xml index 5071394..dfb51c8 100644 --- a/cdn/gameassets/Zwift_Updates_Root/ZwiftMac_ver_cur.xml +++ b/cdn/gameassets/Zwift_Updates_Root/ZwiftMac_ver_cur.xml @@ -1,7 +1,10 @@ +manifest="ZwiftMac_1.0.100118_b796cad3_manifest.xml" +manifest_checksum="-2080585074" +ver_cur_checksum="400842798"/> diff --git a/cdn/gameassets/Zwift_Updates_Root/Zwift_ver_cur.xml b/cdn/gameassets/Zwift_Updates_Root/Zwift_ver_cur.xml index 21f57f3..1337e8f 100644 --- a/cdn/gameassets/Zwift_Updates_Root/Zwift_ver_cur.xml +++ b/cdn/gameassets/Zwift_Updates_Root/Zwift_ver_cur.xml @@ -1,7 +1,10 @@ +manifest="Zwift_1.0.100133_127271d9_manifest.xml" +manifest_checksum="-860072674" +ver_cur_checksum="430382773"/> diff --git a/protobuf/variants.proto b/protobuf/variants.proto index 013792d..45508af 100644 --- a/protobuf/variants.proto +++ b/protobuf/variants.proto @@ -2,8 +2,22 @@ syntax = "proto2"; message Variant { required string name = 1; optional uint32 value = 2; + repeated M3 f3 = 3; } message Variants { repeated Variant variants = 1; } + +message M3 { + repeated M1 f1 = 1; +} + +message M1 { + required string name = 1; + repeated M2 f2 = 2; +} + +message M2 { + required uint32 f4 = 4; +} diff --git a/protobuf/variants_pb2.py b/protobuf/variants_pb2.py index 769d269..8a4884f 100644 --- a/protobuf/variants_pb2.py +++ b/protobuf/variants_pb2.py @@ -19,7 +19,7 @@ DESCRIPTOR = _descriptor.FileDescriptor( syntax='proto2', serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x0evariants.proto\"&\n\x07Variant\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\r\n\x05value\x18\x02 \x01(\r\"&\n\x08Variants\x12\x1a\n\x08variants\x18\x01 \x03(\x0b\x32\x08.Variant' + serialized_pb=b'\n\x0evariants.proto\"7\n\x07Variant\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\r\n\x05value\x18\x02 \x01(\r\x12\x0f\n\x02\x66\x33\x18\x03 \x03(\x0b\x32\x03.M3\"&\n\x08Variants\x12\x1a\n\x08variants\x18\x01 \x03(\x0b\x32\x08.Variant\"\x15\n\x02M3\x12\x0f\n\x02\x66\x31\x18\x01 \x03(\x0b\x32\x03.M1\"#\n\x02M1\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x0f\n\x02\x66\x32\x18\x02 \x03(\x0b\x32\x03.M2\"\x10\n\x02M2\x12\n\n\x02\x66\x34\x18\x04 \x02(\r' ) @@ -47,6 +47,13 @@ _VARIANT = _descriptor.Descriptor( message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='f3', full_name='Variant.f3', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], @@ -60,7 +67,7 @@ _VARIANT = _descriptor.Descriptor( oneofs=[ ], serialized_start=18, - serialized_end=56, + serialized_end=73, ) @@ -91,13 +98,122 @@ _VARIANTS = _descriptor.Descriptor( extension_ranges=[], oneofs=[ ], - serialized_start=58, - serialized_end=96, + serialized_start=75, + serialized_end=113, ) + +_M3 = _descriptor.Descriptor( + name='M3', + full_name='M3', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='f1', full_name='M3.f1', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=115, + serialized_end=136, +) + + +_M1 = _descriptor.Descriptor( + name='M1', + full_name='M1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='M1.name', index=0, + number=1, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='f2', full_name='M1.f2', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=138, + serialized_end=173, +) + + +_M2 = _descriptor.Descriptor( + name='M2', + full_name='M2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='f4', full_name='M2.f4', index=0, + number=4, type=13, cpp_type=3, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=175, + serialized_end=191, +) + +_VARIANT.fields_by_name['f3'].message_type = _M3 _VARIANTS.fields_by_name['variants'].message_type = _VARIANT +_M3.fields_by_name['f1'].message_type = _M1 +_M1.fields_by_name['f2'].message_type = _M2 DESCRIPTOR.message_types_by_name['Variant'] = _VARIANT DESCRIPTOR.message_types_by_name['Variants'] = _VARIANTS +DESCRIPTOR.message_types_by_name['M3'] = _M3 +DESCRIPTOR.message_types_by_name['M1'] = _M1 +DESCRIPTOR.message_types_by_name['M2'] = _M2 _sym_db.RegisterFileDescriptor(DESCRIPTOR) Variant = _reflection.GeneratedProtocolMessageType('Variant', (_message.Message,), { @@ -114,5 +230,26 @@ Variants = _reflection.GeneratedProtocolMessageType('Variants', (_message.Messag }) _sym_db.RegisterMessage(Variants) +M3 = _reflection.GeneratedProtocolMessageType('M3', (_message.Message,), { + 'DESCRIPTOR' : _M3, + '__module__' : 'variants_pb2' + # @@protoc_insertion_point(class_scope:M3) + }) +_sym_db.RegisterMessage(M3) + +M1 = _reflection.GeneratedProtocolMessageType('M1', (_message.Message,), { + 'DESCRIPTOR' : _M1, + '__module__' : 'variants_pb2' + # @@protoc_insertion_point(class_scope:M1) + }) +_sym_db.RegisterMessage(M1) + +M2 = _reflection.GeneratedProtocolMessageType('M2', (_message.Message,), { + 'DESCRIPTOR' : _M2, + '__module__' : 'variants_pb2' + # @@protoc_insertion_point(class_scope:M2) + }) +_sym_db.RegisterMessage(M2) + # @@protoc_insertion_point(module_scope) diff --git a/standalone.py b/standalone.py index 50c846b..bf49953 100755 --- a/standalone.py +++ b/standalone.py @@ -259,7 +259,7 @@ class TCPHandler(socketserver.BaseRequestHandler): self.data = self.request.recv(1024) hello = tcp_node_msgs_pb2.TCPHello() try: - hello.ParseFromString(self.data[3:-4]) + hello.ParseFromString(self.data[8:-9]) except: return # send packet containing UDP server (127.0.0.1) diff --git a/zwift_offline.py b/zwift_offline.py index 7bcde60..d75d154 100644 --- a/zwift_offline.py +++ b/zwift_offline.py @@ -1559,6 +1559,7 @@ def api_profiles_goals_id(player_id, goal_id): @app.route('/api/tcp-config', methods=['GET']) +@app.route('/relay/tcp-config', methods=['GET']) def api_tcp_config(): infos = periodic_info_pb2.PeriodicInfos() info = infos.infos.add() @@ -2101,30 +2102,47 @@ def auth_realms_zwift_tokens_access_codes(): @app.route('/experimentation/v1/variant', methods=['POST']) def experimentation_v1_variant(): - variant_list = [('game_1_12_pc_skip_activity_save_retry', None), - ('return_to_home', 1), - ('game_1_12_nhd_v1', 1), - ('game_1_13_japanese_medium_font', 1), - ('game_1_12_1_retire_client_chat_culling', 1), - ('game_1_14_draftlock_fix', None), - ('xplatform_partner_connection_vitality', None), - ('game_1_16_new_route_ui', 1), - ('pack_dynamics_30_global', None), - ('pack_dynamics_30_makuri', None), - ('pack_dynamics_30_london', None), - ('pack_dynamics_30_watopia', None), - ('pack_dynamics_30_exclude_events', None), - ('game_1_18_server_connection_notifications', None), - ('zc_ios_aug_2021_release_sync', None), - ('game_1_16_2_ble_alternate_unpair_all_paired_devices', 1), - ('game_1_17_game_client_activity_event', None), - ('game_1_17_1_tdf_femmes_yellow_jersey', None), - ('game_1_17_ble_disable_component_sport_filter', 1), - ('game_1_18_new_welcome_ride', None), - ('game_1_18_0_pack_dynamics_2_5_collision_push_back_removal', 1), - ('game_1_15_assert_disable_abort', 1), - ('game_1_18_holiday_mode', None), - ('game_1_14_settings_refactor', None)] + variant_list = [('game_1_12_pc_skip_activity_save_retry', None, None), + ('return_to_home', 1, None), + ('game_1_12_nhd_v1', 1, None), + ('game_1_13_japanese_medium_font', 1, None), + ('game_1_12_1_retire_client_chat_culling', 1, None), + ('game_1_14_draftlock_fix', None, None), + ('xplatform_partner_connection_vitality', None, None), + ('game_1_16_new_route_ui', 1, None), + ('pack_dynamics_30_global', 1, None), + ('pack_dynamics_30_makuri', 1, None), + ('pack_dynamics_30_london', 1, None), + ('pack_dynamics_30_watopia', 1, None), + ('pack_dynamics_30_exclude_events', None, None), + ('game_1_19_system_alerts', 1, None), + ('zc_ios_aug_2021_release_sync', None, None), + ('game_1_16_2_ble_alternate_unpair_all_paired_devices', 1, None), + ('game_1_17_game_client_activity_event', None, None), + ('game_1_17_1_tdf_femmes_yellow_jersey', None, None), + ('game_1_17_ble_disable_component_sport_filter', 1, None), + ('game_1_18_new_welcome_ride', None, None), + ('game_1_19_achievement_service_persist', None, None), + ('game_1_19_achievement_service_src_of_truth', None, None), + ('game_1_18_0_pack_dynamics_2_5_collision_push_back_removal', 1, None), + ('game_1_18_alternate_control_point_pairing', None, None), + ('game_1_18_swap_legacy_controllable_for_ftms', None, None), + ('game_1_19_gender_dob_change', None, None), + ('game_1_18_0_osx_monterey_bluetooth_uart_fix', None, 0), + ('game_1_19_0_default_rubberbanding', None, None), + ('game_1_19_use_tabbed_settings', None, 0), + ('pedal_assist_20', None, None), + ('game_1_19_segment_results_sub_active', None, 0), + ('game_1_19_hw_experiment_1', None, None), + ('game_1_19_paired_devices_alerts', 1, None), + ('game_1_19_real_time_unlocks', None, None), + ('game_1_15_assert_disable_abort', 1, None), + ('game_1_19_local_activity_persistence', None, None), + ('game_1_18_holiday_mode', None, None), + ('game_1_17_noesis_enabled', None, None), + ('game_1_17_home_screen', None, None), + ('game_1_19_noesis_dummy', None, None), + ('game_1_14_settings_refactor', None, None)] variants = variants_pb2.Variants() for variant in variant_list: @@ -2132,6 +2150,12 @@ def experimentation_v1_variant(): item.name = variant[0] if variant[1] is not None: item.value = variant[1] + f3 = item.f3.add() + if variant[2] is not None: + f1 = f3.f1.add() + f1.name = variant[0] + f2 = f1.f2.add() + f2.f4 = variant[2] return variants.SerializeToString(), 200