Update to Zwift 1.0.105233

This commit is contained in:
oldnapalm
2022-09-14 19:40:59 -03:00
parent 888f085cc7
commit e53eb91786
6 changed files with 189 additions and 117 deletions
+6 -5
View File
@@ -17,6 +17,7 @@ There are three ways with which to install and run zoffline depending on your pl
To install zoffline on Windows:
* Download the latest zoffline release from https://github.com/zoffline/zwift-offline/releases
* If you want the pace partners, download the source code package and extract the ``pace_partners`` directory to the same folder zoffline is in.
* Run the downloaded zoffline.exe
* Once run, zoffline will create a ``storage`` directory in the same folder it's in to store your Zwift progress.
* Start Zwift with zoffline.exe running (__after completing step 2__ or running __configure_client__ script from https://github.com/zoffline/zwift-offline/releases/tag/zoffline_helper)
@@ -93,10 +94,10 @@ zoffline can be installed on the same machine as Zwift or another local machine.
<details><summary>Windows Instructions</summary>
* Install Zwift
* If your Zwift version is 1.0.101500, you're all set.
* If your Zwift version is 1.0.105233, you're all set.
* If Zwift is not installed, install it before installing zoffline.
* If your Zwift version is newer than 1.0.101500 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.101500 and zoffline is not running from source: wait for zoffline to be updated.
* If your Zwift version is newer than 1.0.105233 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.105233 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``
@@ -122,9 +123,9 @@ to generate your own certificates and do the same.
<details><summary>macOS Instructions</summary>
* Install Zwift
* If your Zwift version is 1.0.101500, you're all set.
* If your Zwift version is 1.0.105233, you're all set.
* If Zwift is not installed, install it before installing zoffline.
* If your Zwift version is newer than 1.0.101500: 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.105233: 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``
@@ -1,9 +1,9 @@
<Zwift
version="1.0.101500"
sversion="1.28.1 (101500)"
gbranch="build/101500-rc-1.28.1.16-1.28.1"
gcommit="a08dad09e39cb26d8f279fd66fb9aeae29b7dd5e"
version="1.0.105233"
sversion="1.29.0 (105233)"
gbranch="rc/1.29.0"
gcommit="551bf6896edb8cccfa0298a59d321f81eb4e42a8"
GAME_URL="https://us-or-rly101.zwift.com"
manifest="ZwiftMac_1.0.101500_1fe3bc19_manifest.xml"
manifest_checksum="1178012635"
ver_cur_checksum="529725630"/>
manifest="ZwiftMac_1.0.105233_27ea3fb2_manifest.xml"
manifest_checksum="-852792274"
ver_cur_checksum="-1509200237"/>
@@ -1,9 +1,9 @@
<Zwift
version="1.0.101500"
sversion="1.28.1 (101500)"
gbranch="build/101500-rc-1.28.1.16-1.28.1"
gcommit="a08dad09e39cb26d8f279fd66fb9aeae29b7dd5e"
version="1.0.105233"
sversion="1.29.0 (105233)"
gbranch="rc/1.29.0"
gcommit="551bf6896edb8cccfa0298a59d321f81eb4e42a8"
GAME_URL="https://us-or-rly101.zwift.com"
manifest="Zwift_1.0.101500_1fe3bc19_manifest.xml"
manifest_checksum="1425423777"
ver_cur_checksum="-15275599"/>
manifest="Zwift_1.0.105233_27ea3fb2_manifest.xml"
manifest_checksum="-1173342509"
ver_cur_checksum="-670280471"/>
+1 -1
View File
File diff suppressed because one or more lines are too long
+110 -8
View File
@@ -244,11 +244,30 @@
"value": true,
"values": {}
},
{
"name": "game_1_28_avoid_aborting_current_timing_sector_when_minimizing",
"value": true,
"values": {}
},
{
"name": "game_1_27_add_lineup_to_leave_current_event",
"value": true,
"values": {}
},
{
"name": "game_1_29_integrate_road_and_bike_type_into_braking_performance",
"values": {}
},
{
"name": "game_1_29_use_relay_spline_time_in_meetup_position_late_joiner",
"value": true,
"values": {}
},
{
"name": "game_1_29_ignore_private_meetups_in_group_event_processing_logic",
"value": true,
"values": {}
},
{
"name": "game_upload_route_results_v2",
"value": true,
@@ -260,6 +279,7 @@
},
{
"name": "game_1_25_extended_pedal_asssit",
"value": true,
"values": {
"fields": {
"initialDropInTime": {
@@ -288,7 +308,7 @@
"values": {}
},
{
"name": "game_1_28_ble_middleware",
"name": "game_1_29_ble_middleware",
"values": {}
},
{
@@ -298,6 +318,7 @@
},
{
"name": "game_1_27_atv_remote_gestures",
"value": true,
"values": {
"fields": {
"ATVPopInitDist": {
@@ -354,7 +375,51 @@
"values": {}
},
{
"name": "game_1_28_event_core_feed_service",
"name": "game_1_29_get_started_workouts",
"values": {}
},
{
"name": "game_1_28_ftms_road_grade_lookahead_time_exposed",
"value": true,
"values": {}
},
{
"name": "game_1_29_ble_cycling_speed_pairing_opt",
"values": {}
},
{
"name": "game_1_29_new_local_trainer_profile",
"values": {}
},
{
"name": "game_1_29_fix_stuck_zpower",
"value": true,
"values": {}
},
{
"name": "game_1_29_event_carousel",
"value": true,
"values": {
"fields": {
"NUM_CARDS": {
"varintValue": "6"
}
}
}
},
{
"name": "game_1_29_client_recommendations",
"value": true,
"values": {}
},
{
"name": "game_1_29_level_60_cap_raise",
"value": true,
"values": {}
},
{
"name": "game_1_29_logout_for_windows_and_mac",
"value": true,
"values": {}
},
{
@@ -372,19 +437,51 @@
"values": {}
},
{
"name": "game_1_26_watchdog_timer",
"name": "game_1_28_event_core_feed_service",
"values": {}
},
{
"name": "game_1_29_event_query_interval",
"value": true,
"values": {
"fields": {
"timeoutInterval": {
"numberValue": 60.0
},
"abortEnabled": {
"boolValue": false
"GROUP_EVENT_QUERY_RATE_SECONDS": {
"numberValue": 120.0
}
}
}
},
{
"name": "game_1_29_set_thread_names",
"values": {}
},
{
"name": "game_1_28_watchdog_timer",
"values": {
"fields": {
"abortEnabled": {
"boolValue": false
},
"renderTimeoutInterval": {
"numberValue": 30.0
},
"mainTimeoutInterval": {
"numberValue": 30.0
},
"reportTimeoutsOnLoad": {
"boolValue": false
},
"loadingTimeoutInterval": {
"numberValue": 60.0
}
}
}
},
{
"name": "game_1_29_hand_cycle",
"value": true,
"values": {}
},
{
"name": "game_1_17_noesis_enabled",
"value": true,
@@ -401,6 +498,11 @@
"value": true,
"values": {}
},
{
"name": "workout_training_v2_release",
"value": true,
"values": {}
},
{
"name": "game_1_23_workout_auto_pause",
"values": {
+58 -89
View File
@@ -800,18 +800,15 @@ def upload(username):
@app.route("/download/profile.bin", methods=["GET"])
@login_required
def download_profile():
player_id = current_user.player_id
profile_dir = os.path.join(STORAGE_DIR, str(player_id))
profile_file = os.path.join(profile_dir, 'profile.bin')
profile_file = os.path.join(STORAGE_DIR, str(current_user.player_id), 'profile.bin')
if os.path.isfile(profile_file):
return send_file(profile_file, attachment_filename='profile.bin')
return send_file(profile_file)
@app.route("/download/<int:player_id>/avatarLarge.jpg", methods=["GET"])
def download_avatarLarge(player_id):
profile_dir = os.path.join(STORAGE_DIR, str(player_id))
profile_file = os.path.join(profile_dir, 'avatarLarge.jpg')
profile_file = os.path.join(STORAGE_DIR, str(player_id), 'avatarLarge.jpg')
if os.path.isfile(profile_file):
return send_file(profile_file, mimetype='image/jpeg', attachment_filename='avatarLarge.jpg')
return send_file(profile_file, mimetype='image/jpeg')
else:
return '', 404
@@ -1708,10 +1705,10 @@ def player_playbacks_player_playback():
f.write(stream)
return '', 200
@app.route('/player-playbacks/player/me/playbacks/<segment_id>/pr', methods=['GET'])
@app.route('/player-playbacks/player/me/playbacks/<segment_id>/<option>', methods=['GET'])
@jwt_to_session_cookie
@login_required
def player_playbacks_player_me_playbacks_pr(segment_id):
def player_playbacks_player_me_playbacks(segment_id, option):
segment_id = int(segment_id) & 0xffffffffffffffff
after = request.args.get('after')
before = request.args.get('before')
@@ -1720,7 +1717,10 @@ def player_playbacks_player_me_playbacks_pr(segment_id):
query += " AND world_time > '%s'" % after
if before:
query += " AND world_time < '%s'" % before
query += " ORDER BY time"
if option == 'pr':
query += " ORDER BY time"
elif option == 'latest':
query += " ORDER BY world_time DESC"
row = db.session.execute(sqlalchemy.text(query)).first()
if not row:
return '', 200
@@ -2716,73 +2716,50 @@ def relay_worlds_attributes(server_realm=udp_node_msgs_pb2.ZofflineConstants.Rea
return '', 201
def add_segment_results(segment_id, player_id, only_best, from_date, to_date, results):
where_stmt = ("WHERE segment_id = '%s'" % segment_id)
rows = None
if player_id:
where_stmt += (" AND player_id = '%s'" % player_id)
if from_date:
where_stmt += (" AND strftime('%s', finish_time_str) > strftime('%s', '%s')" % ('%s', '%s', from_date))
if to_date:
where_stmt += (" AND strftime('%s', finish_time_str) < strftime('%s', '%s')" % ('%s', '%s', to_date))
if only_best:
#Only include results from max 1 hour ago
where_stmt += (" AND world_time > '%s'" % (world_time()-(60*60*1000)))
rows = db.session.execute(sqlalchemy.text("""SELECT s1.* FROM segment_result s1
JOIN (SELECT s.player_id, MIN(Cast(s.elapsed_ms AS INTEGER)) AS min_time
FROM segment_result s %s GROUP BY s.player_id) s2 ON s2.player_id = s1.player_id AND s2.min_time = CAST(s1.elapsed_ms AS INTEGER)
GROUP BY s1.player_id, s1.elapsed_ms
ORDER BY CAST(s1.elapsed_ms AS INTEGER)
LIMIT 1000""" % where_stmt))
else:
rows = db.session.execute(sqlalchemy.text("SELECT * FROM segment_result %s" % where_stmt))
for row in rows:
result = results.segment_results.add()
row_to_protobuf(row, result, ['f3', 'f4', 'segment_id', 'event_subgroup_id', 'finish_time_str', 'f14', 'f17', 'f18'])
@app.route('/api/segment-results', methods=['POST'])
@jwt_to_session_cookie
@login_required
def api_segment_results():
if not request.stream:
return '', 400
data = request.stream.read()
result = segment_result_pb2.SegmentResult()
result.ParseFromString(data)
if result.segment_id == 1:
return '', 400
result.id = get_id('segment_result')
result.world_time = world_time()
result.finish_time_str = get_utc_date_time().strftime("%Y-%m-%dT%H:%M:%SZ")
result.f20 = 0
insert_protobuf_into_db('segment_result', result)
def handle_segment_results(request):
if request.method == 'POST':
if not request.stream:
return '', 400
data = request.stream.read()
result = segment_result_pb2.SegmentResult()
result.ParseFromString(data)
if result.segment_id == 1:
return '', 400
result.id = get_id('segment_result')
result.world_time = world_time()
result.finish_time_str = get_utc_date_time().strftime("%Y-%m-%dT%H:%M:%SZ")
result.f20 = 0
insert_protobuf_into_db('segment_result', result)
# Previously done in /relay/worlds/attributes
player_update = udp_node_msgs_pb2.WorldAttribute()
player_update.server_realm = udp_node_msgs_pb2.ZofflineConstants.RealmID
player_update.wa_type = udp_node_msgs_pb2.WA_TYPE.WAT_SR
player_update.payload = data
player_update.world_time_born = world_time()
player_update.world_time_expire = world_time() + 60000
player_update.timestamp = int(get_utc_time() * 1000000)
sending_player_id = result.player_id
if sending_player_id in online:
sending_player = online[sending_player_id]
for receiving_player_id in online.keys():
if receiving_player_id != sending_player_id:
receiving_player = online[receiving_player_id]
if get_course(sending_player) == get_course(receiving_player) or receiving_player.watchingRiderId == sending_player_id:
enqueue_player_update(receiving_player_id, player_update.SerializeToString())
# Previously done in /relay/worlds/attributes
player_update = udp_node_msgs_pb2.WorldAttribute()
player_update.server_realm = udp_node_msgs_pb2.ZofflineConstants.RealmID
player_update.wa_type = udp_node_msgs_pb2.WA_TYPE.WAT_SR
player_update.payload = data
player_update.world_time_born = world_time()
player_update.world_time_expire = world_time() + 60000
player_update.timestamp = int(get_utc_time() * 1000000)
sending_player_id = result.player_id
if sending_player_id in online:
sending_player = online[sending_player_id]
for receiving_player_id in online.keys():
if receiving_player_id != sending_player_id:
receiving_player = online[receiving_player_id]
if get_course(sending_player) == get_course(receiving_player) or receiving_player.watchingRiderId == sending_player_id:
enqueue_player_update(receiving_player_id, player_update.SerializeToString())
return {"id": result.id}
return {"id": result.id}
# request.method == GET
# world_id = int(request.args.get('world_id'))
player_id = request.args.get('player_id')
# full = request.args.get('full') == 'true'
# Require segment_id
if not request.args.get('segment_id'):
@app.route('/api/personal-records/my-records', methods=['GET'])
@jwt_to_session_cookie
@login_required
def api_personal_records_my_records():
if not request.args.get('segmentId'):
return '', 422
segment_id = int(request.args.get('segment_id')) & 0xffffffffffffffff
only_best = request.args.get('only-best') == 'true'
segment_id = int(request.args.get('segmentId')) & 0xffffffffffffffff
from_date = request.args.get('from')
to_date = request.args.get('to')
@@ -2790,27 +2767,19 @@ def handle_segment_results(request):
results.server_realm = udp_node_msgs_pb2.ZofflineConstants.RealmID
results.segment_id = segment_id
add_segment_results(segment_id, player_id, only_best, from_date, to_date, results)
where_stmt = ("WHERE segment_id = '%s' AND player_id = '%s'" % (segment_id, current_user.player_id))
if from_date:
where_stmt += (" AND strftime('%s', finish_time_str) > strftime('%s', '%s')" % ('%s', '%s', from_date))
if to_date:
where_stmt += (" AND strftime('%s', finish_time_str) < strftime('%s', '%s')" % ('%s', '%s', to_date))
rows = db.session.execute(sqlalchemy.text("SELECT * FROM segment_result %s" % where_stmt))
for row in rows:
result = results.segment_results.add()
row_to_protobuf(row, result, ['f3', 'f4', 'segment_id', 'event_subgroup_id', 'finish_time_str', 'f14', 'f17', 'f18'])
return results.SerializeToString(), 200
@app.route('/relay/segment-results', methods=['GET'])
def relay_segment_results():
return handle_segment_results(request)
@app.route('/api/segment-results', methods=['GET', 'POST'])
@jwt_to_session_cookie
@login_required
def api_segment_results():
#Checks that online player has values for ghosts and player_id
player_id = current_user.player_id
if request.method == 'POST' and player_id != current_user.player_id:
return '', 401
return handle_segment_results(request)
@app.route('/live-segment-results-service/leaders', methods=['GET'])
def live_segment_results_service_leaders():
results = segment_result_pb2.SegmentResults()