Untitled

 avatar
unknown
plain_text
6 days ago
4.9 kB
2
Indexable
import hashlib
from hmac import HMAC
import math
import csv
import os

def byteGenerator(serverSeed, clientSeed, nonce, cursor=0):
    currentRound = 0
    currentRoundCursor = cursor

    while True:
        # hmac generation is the core of the rng process of the implementation
        hmac = HMAC(serverSeed.encode(), f"{clientSeed}:{nonce}:{currentRound}".encode(), hashlib.sha256)
        buffer = hmac.digest()

        # while the cursor function is included. dice does not use a round cursor higher than 0. if this script were adapted to another game this may be useful. 
        while currentRoundCursor < 32:
            yield buffer[currentRoundCursor]
            currentRoundCursor += 1

        currentRoundCursor = 0
        currentRound += 1

def generateFloats(serverSeed, clientSeed, nonce, cursor=0, count=1):
    # convert the hash output from the byteGenerator to floats
    rng = byteGenerator(serverSeed, clientSeed, nonce, cursor)
    bytes = []

    # this sets up the game event with the implementation of the rng
    while len(bytes) < count * 4:
        bytes.append(next(rng))

    # floats are used in the game event
    floats = []
    for bytesChunk in [bytes[i:i+4] for i in range(0, len(bytes), 4)]:
        result = 0
        for i, value in enumerate(bytesChunk):
            divider = 256 ** (i + 1)
            partialResult = value / divider
            result += partialResult
        floats.append(result)

    return floats

def diceRoll(float):
    # game event translation
    scaled_value = (float * 10001) / 100  # Multiply by 100 to get 2 decimal places
    rounded_down = math.floor(scaled_value * 100) / 100  # Round down and then divide by 100 to get 2 decimal places
    return rounded_down

def verify(clientSeed, serverSeed, nonce_start, nonce_end, output_file):

    # generates game events; each event is a roll. we can roll as many of these as desired. 
    results = []
    for nonce in range(nonce_start, nonce_end + 1):
        floats = generateFloats(serverSeed, clientSeed, str(nonce))
        rolls = [diceRoll(float) for float in floats]
        for roll in rolls:
            results.append([nonce, roll])

    # writing the rolls to csv files
    try:
        with open(output_file, 'w', newline='') as csvfile:
            writer = csv.writer(csvfile)
            writer.writerow(['Nonce', 'Roll','', 'Unhashed Server Seed:'+ serverSeed, 'Client Seed:' + clientSeed])
            writer.writerows(results)
    except PermissionError:
        print(f"Error: Unable to write to {output_file}. Creating a new file.")
        base_filename, ext = os.path.splitext(output_file)
        new_filename = f"{base_filename}_new{ext}"
        with open(new_filename, 'w', newline='') as csvfile:
            writer = csv.writer(csvfile)
            writer.writerow(['Nonce', 'Roll','', 'Unhashed Server Seed:'+ serverSeed, 'Client Seed:' + clientSeed])
            writer.writerows(results)
        print(f"Results written to {new_filename}")


# variables. for posterity I am including the sha256 encoder so that if something is incorrect, it will tell the user. 
# possible issues: if the user has special characters in their client seed, it may not work. that would require forcing a literal interpretation of the string. this is probably not hard to do but i didnt do it now.
# if you need to do this and the values are not matching up to corroborating evidence, change that to (exactly like the below) and remove the hashtag.
# clientSeed = '''clientseed'''
hserverSeed = input("Enter hashed server seed...")
serverSeed = input("Enter unhashed server seed...")
clientSeed = input("Enter client seed...")
# if desired, you can change the nonce start so that you can generate from a particular point. by default I am leaving it at 0
nonce_start = 0
nonce_end = int(input("Enter last nonce to count..."))
output_file = "rolls.csv"

# input both strings. they must be sha256, not sha512. 

def sha256_encode(data):
    # this will check if serverSeed is able to be resolved as hserverSeed. If it does, then you were not given a false server seed at any point. 
    return hashlib.sha256(data.encode()).hexdigest()

hashed_input = sha256_encode(serverSeed)

provided_hashed_result = hserverSeed

print("Encoded Server Seed:", hashed_input)
print("Provided hashed result:", provided_hashed_result)

#if hashed_input == provided_hashed_result:
#    print("Hashes match.")
#else:
#    print("Hashes do not match, please ensure these are the correct inputs.")
#    resolution = input("Do you still want to proceed with generating rolls? (Y/N): ")
#    if resolution != "Y":
#        exit()
#    else:
#        verify(clientSeed, serverSeed, nonce_start, nonce_end, output_file)
#        print("Finished, .csv file output to folder.")

    

# and then the function proceeds.
verify(clientSeed, serverSeed, nonce_start, nonce_end, output_file)
print("Finished, .csv file output to folder.")
Leave a Comment