#!/usr/bin/python3

import sqlite3
import struct
import sys

# 
# I don't know what the other 2 bytes there could be. DB version 1 had some more data there, but clearly you are on version 2, which doesn't. And also v1 had 14 bytes there, not just two.
# 
# The XZY has Yaw after it, as a 16bit int range between -pi and pi. followed by the modelname
# 
# The data should be
# int16 dbversion
# float32 x, y, z
# int16 yaw
# string modelname (edited)
# [11:28 AM]
# Also the floats and ints are in little endian. So your big endian conversion finding a position looks messed up.
# If I take the numbers as they should be, I get
# 
# 0200
# 0A772146 = 10333.76
# 62F50143 = 129.958527
# D64D1E46 = 10131.459
# 410D = 3393 -> (3393 / 65535) * (pi --pi) + -pi -> -2.816 radians -> -161.3 degrees (edited)
# [11:29 AM]
# Its funny that you managed to be off-by-two, and still managed to get valid/close-enough positions out of it (edited)
# [11:29 AM]
# and lbmaster's parser is just as wrong. It skips 2 bytes of the X coordinate, mangles up the coordinates, and then includes the YAW integer, into the float for the Z coordinate.. What a mess (edited)
# 

import sqlite3
import struct
import sys

def get_player_data(db_path, uid):
    """Retrieve player data from the database."""
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()

    cursor.execute("SELECT Data FROM Players WHERE uid = ?", (uid,))
    row = cursor.fetchone()
    conn.close()

    if row:
        return row[0]  # Return BLOB data
    else:
        print(f"No player found with UID {uid}.")
        return None

def modify_position(data_blob, new_x, new_y, new_z):
    """Modify only the position in the binary BLOB based on the documented structure."""
    try:
        # Keep dbversion unchanged and modify only x, y, z
        db_version = struct.unpack("<h", data_blob[:2])[0]
        modified_blob = struct.pack("<hfff", db_version, new_x, new_y, new_z) + data_blob[14:]
        return modified_blob
    except Exception as e:
        print(f"Error processing BLOB data: {e}")
        return None

def update_player_location(db_path, uid, new_x, new_y, new_z):
    """Update player location in the database."""
    data_blob = get_player_data(db_path, uid)
    if not data_blob:
        return

    modified_blob = modify_position(data_blob, new_x, new_y, new_z)
    if not modified_blob:
        return

    # Update database with modified BLOB
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    cursor.execute("UPDATE Players SET Data = ? WHERE uid = ?", (modified_blob, uid))
    conn.commit()
    conn.close()

    print(f"Updated player {uid} to new position: ({new_x}, {new_y}, {new_z})")

if __name__ == "__main__":
    if len(sys.argv) < 6:
        print("Usage: python3 update_dayz_location.py <db_path> <uid> <x> <y> <z>")
        sys.exit(1)

    db_path = sys.argv[1]
    uid = sys.argv[2]
    new_x = float(sys.argv[3])
    new_y = float(sys.argv[4])
    new_z = float(sys.argv[5])

    update_player_location(db_path, uid, new_x, new_y, new_z)

