Open m-vandeneede opened 5 years ago
CODE BELOW
import json
import sys
json_map = {
'F2P': 'Version', '8>q': 'Platform', '6f=': 'PlayerStateData',
'yhJ': 'UniverseAddress', 'Iis': 'RealityIndex', 'oZw': 'GalacticAddress',
'dZj': 'VoxelX', 'IyE': 'VoxelY', 'uXE': 'VoxelZ',
'vby': 'SolarSystemIndex', 'jsv': 'PlanetIndex', ';l5': 'Inventory',
':No': 'Slots', 'Vn8': 'Type', 'elv': 'InventoryType', 'b2n': 'Id',
'1o9': 'Amount', 'F9q': 'MaxAmount', 'eVk': 'DamageFactor',
'3ZH': 'Index', '>Qh': 'X', 'XJ>': 'Y', 'hl?': 'ValidSlotIndices',
'B@N': 'Class', '1o6': 'InventoryClass', '0H2':
'SubstanceMaxStorageMultiplier', 'cTY': 'ProductMaxStorageMultiplier',
'@bB': 'BaseStatValues', 'MMm': 'SpecialSlots', '=Tb': 'Width',
'N9>': 'Height', 'iF:': 'IsCool', 'PMT': 'Inventory_TechOnly',
'gan': 'Inventory_Cargo', '6<E': 'ShipInventory', 'Kgt': 'WeaponInventory',
'QL1': 'BaseStatID', '>MX': 'Value', '4eu': 'GraveInventory',
'BGQ': 'SpawnGrave', ';JQ': 'SpaceGrave', 'NFm': 'GraveUniverseAddress',
'4ia': 'GravePosition', 'gIh': 'GraveMatrixLookAt', 'YJU': 'GraveMatrixUp',
'rj2': 'ShipLayout', 'xbM': 'WeaponLayout', 'oJJ': 'CurrentShip',
'<d2': 'ProceduralTexture', 'bnT': 'Samplers', 'e6e': 'CurrentWeapon',
'93M': 'Filename', '@EL': 'Seed', 'QlJ': 'AltId', '9;o': 'Level',
'NNR': 'GenerationSeed', '4kj': 'KnownTech', 'eZ<': 'KnownProducts',
'24<': 'KnownSpecials', 'Ddk': 'KnownRefinerRecipes', ':JX': 'KnownWords',
'9wn': 'Word', 'D;o': 'Races', 'dwb': 'MissionProgress', 'p0c': 'Mission',
'tW6': 'Progress', '8?J': 'Data', 'eZ7': 'Participants', '5L6': 'UA',
'5bU': 'BuildingSeed', 'M?f': 'ParticipantType', 'wMC': 'Position',
'?eS': 'PostMissionIndex', ';R7': 'CurrentMissionID',
'k?G': 'CurrentMissionSeed', 'Mg<': 'PreviousMissionID',
'rej': 'PreviousMissionSeed', 'yq:': 'MissionVersion',
'EQt': 'MissionRecurrences', 'jGk': 'MissionID', 'oF@':
'RecurrenceDeadline', 'cmA': 'HoloExplorerInteraction',
'<>B': 'HoloScepticInteraction', ':=:': 'HoloNooneInteraction',
'fSZ': 'Health', 'KCM': 'ShipHealth', 'kLc': 'Shield',
'NE3': 'ShipShield', 'dcK': 'Energy', 'wGS': 'Units', '7QL':
'Nanites', 'kN;': 'Specials', 'cid': 'ThirdPersonShip',
'i8O': 'TimeAlive', 'Lg8': 'TotalPlayTime', 'A1f': 'MarkerStack',
'9@i': 'Table', 'FN5': 'Event', 'TWn': 'BuildingLocation',
'iqv': 'BuildingClass', 'ADw': 'Time', '1JW': 'MissionSeed',
'i;<': 'NewMPMarkerStack', 'gUR': 'Stats', ':rc': 'GroupId',
'2Ak': 'Address', '>vs': 'IntValue', 'eoL': 'FloatValue',
'm4I': 'TelemetryStats', 'a6j': 'StoredInteractions',
'O49': 'Interactions', 'RQA': 'MaintenanceInteractions',
'=yU': 'InventoryContainer', 'wx7': 'LastUpdateTimestamp',
'4>;': 'DamageTimers', 'XV5': 'Flags',
'VhC': 'PersonalMaintenanceInteractions', 'nwS': 'VisitedSystems',
'seg': 'Hazard', '9Lm': 'BoltAmmo', 'VPy': 'ScatterAmmo',
':ML': 'PulseAmmo', 'cO>': 'LaserAmmo', 'vaP': 'FirstSpawnPosition',
'E?v': 'SavedInteractionIndicies', 'SEK': 'SavedRaceIndicies',
'Wu?': 'SavedInteractionDialogTable', 'E=X': 'Hash', '2Fk': 'Dialog',
'wHR': 'InteractionProgressTable', 'vsV': 'AtlasStationAdressData',
'B9>': 'NewAtlasStationAdressData', ':A3': 'VisitedAtlasStationsData',
':0x': 'FirstAtlasStationDiscovered', 'kPF': 'UsesThirdPersonCharacterCam',
'DtI': 'ProgressionLevel', 'QNH': 'ProcTechIndex', 'eV1': 'IsNew',
'wc3': 'UseSmallerBlackholeJumps', '<dk': 'UsedEntitlements',
'aHM': 'PlanetPositions', '?=a': 'PlanetSeeds', '7Mc': 'PrimaryPlanet',
'05J': 'TimeLastSpaceBattle', '8br': 'WarpsLastSpaceBattle',
'8xx': 'ActiveSpaceBattleUA', 'IRi': 'TimeLastMiniStation',
'x=M': 'WarpsLastMiniStation', 'gpU': 'MiniStationUA',
'JvI': 'AnomalyPositionOverride', '5ST': 'GameStartAddress1',
'EeN': 'GameStartAddress2', 'M2Z': 'GalacticMapRequests',
'nTB': 'FirstShipPosition', 'G?:': 'HazardTimeAlive',
'tSD': 'RevealBlackHoles', 'kYq': 'CurrentFreighterHomeSystemSeed',
'bIR': 'CurrentFreighter', '>Yh': 'FreighterLayout',
'8ZP': 'FreighterInventory', '0wS': 'FreighterInventory_TechOnly',
'RB7': 'FreighterUniverseAddress', '9wg': 'FreighterMatrixAt',
'fUl': 'FreighterMatrixUp', 'lpm': 'FreighterMatrixPos',
'c5s': 'BaseBuildingObjects', 'b1:': 'Timestamp', 'r<7': 'ObjectID',
'ofi': 'RegionSeed', 'CVX': 'UserData', 'wJ0': 'Up', 'aNu': 'At',
'=o:': 'TerrainEditData', 'r:j': 'GalacticAddresses', 'eiy': 'BufferSizes',
'w0G': 'BufferAges', 'cL6': 'BufferAnchors', 'Mes': 'Edits',
'4Km': 'NPCWorkers', 'q08': 'ResourceElement', 'BKy': 'InteractionSeed',
'1wj': 'HiredWorker', 'gNy': 'FreighterBase', 'pNt': 'BaseUA',
'TJx': 'BaseOffset', 'F?0': 'PersistentPlayerBases', 'h4X': 'BaseVersion',
'oHw': 'Forward', '@ZJ': 'Objects', 'B2h': 'RID', '3?K': 'Owner',
'f5Q':'LID', 'K7E': 'UID', 'V?:': 'USN', '3I1': 'TS', 'NKm': 'Name',
'peI': 'BaseType', 'DPp': 'PersistentBaseTypes',
'nlG': 'TeleportEndpoints', 'gk4': 'Facing', 'iAF': 'TeleporterType',
'=3B': 'Chest1Layout', '3Nc': 'Chest1Inventory', '@ip': 'Chest2Layout',
'IDc': 'Chest2Inventory', '@Ik': 'Chest3Layout', 'M=:': 'Chest3Inventory',
'@1E': 'Chest4Layout', 'iYp': 'Chest4Inventory', 'XgV': 'Chest5Layout',
'<IP': 'Chest5Inventory', 'nw5': 'Chest6Layout', 'qYJ': 'Chest6Inventory',
'tLo': 'Chest7Layout', '@e5': 'Chest7Inventory', '7b?': 'Chest8Layout',
'5uh': 'Chest8Inventory', 'QBc': 'Chest9Layout', '5Tg': 'Chest9Inventory',
'wqf': 'Chest10Layout', 'Bq<': 'Chest10Inventory',
'v8;': 'ChestMagicLayout', ';?C': 'ChestMagicInventory',
'wFm': 'ChestMagic2Layout', 'fCh': 'ChestMagic2Inventory',
'Sjw': 'CurrentFreighterNPC', 'P;m': 'VehicleOwnership', 'NTx': 'Resource',
'pMa': 'InventoryLayout', 'YTa': 'Location', 'l?l': 'Direction',
'5sx': 'PrimaryVehicle', '@Cs': 'ShipOwnership',
'QA1': 'InventorySpecialSlotType', 'aBE': 'PrimaryShip',
'@Vn': 'MultiShipEnabled', 'rBG': 'PlayerWeaponName',
'vxi': 'PlayerFreighterName', 'h=c': 'StartGameShipPosition',
'nkF': 'TradingSupplyDataIndex', 'b69': 'TradingSupplyData',
'Iu7': 'Supply', 'pfp': 'Demand', 'JWK': 'Product', 'HbG': 'LastPortal',
'NQJ': 'VisitedPortal', '3fO': 'PortalSeed', 'K:U': 'LastPortalUA',
'vrS': 'KnownPortalRunes', 'DaC': 'OnOtherSideOfPortal',
'LIR': 'PortalMarkerPosition_Local', 'qW;': 'PortalMarkerPosition_Offset',
';DM': 'StartingPrimaryWeapon', 'Rfw': 'WeaponMode',
'SYl': 'StartingSecondaryWeapon', 'l:j': 'CharacterCustomisationData',
'VFd': 'SelectedPreset', 'wnR': 'CustomData', 'SMP': 'DescriptorGroups',
'Aak': 'Colours', 'T>1': 'TextureOptions', 'gsg': 'BoneScales',
'unY': 'Scale', '4hl': 'ShipUsesLegacyColours', '3Z>': 'FleetSeed',
';Du': 'FleetFrigates', 'SLc': 'ResourceSeed', '@ui': 'HomeSystemSeed',
'4kx': 'TimeOfLastIncomeCollection', 'fH8': 'CustomName',
'uw7': 'FrigateClass', 'SS2': 'Race', '0Hi': 'AlienRace',
'5es': 'TotalNumberOfExpeditions', 'v=L': 'TotalNumberOfSuccessfulEvents',
'5VG': 'TotalNumberOfFailedEvents', 'MuL': 'NumberOfTimesDamaged',
'Mjm': 'TraitIDs', 'yJC': 'RepairsMade', '7hK': 'DamageTaken',
'kw:': 'FleetExpeditions', 'o@4': 'SpawnPosition',
'4j2': 'TerminalPosition', 'b>d': 'SpeedMultiplier', 'hea': 'Powerups',
'3oW': 'InterventionEventMissionID', 'bc<': 'StartTime',
'?DC': 'PauseTime', 'dfZ': 'TimeOfLastUAChange',
'U87': 'NextEventToTrigger', 'xVB': 'ExpeditionCategory',
'TPK': 'ExpeditionDuration', 'sbg': 'ActiveFrigateIndices',
'WZs': 'DamagedFrigateIndices', '1xe': 'DestroyedFrigateIndices',
'lD@': 'AllFrigateIndices',
'omN': 'NumberOfSuccessfulEventsThisExpedition',
'G;H': 'NumberOfFailedEventsThisExpedition', 'tUs': 'Events',
'iaH': 'AffectedFrigateIndices', 'QJG': 'RepairingFrigateIndices',
'fe2': 'AffectedFrigateResponses', 'Mx@': 'EventID',
'7Q;': 'InterventionEventID', 'bbB': 'Success',
'fvN': 'IsInterventionEvent', '8GD': 'AvoidedIntervention',
'b78': 'InterventionPhoneCallActivated',
'ieD': 'ExpeditionSeedsSelectedToday', 'nxr': 'LastKnownDay',
'>db': 'SunTimer', 'vXX': 'MultiplayerLobbyID', 'YxD': 'MultiplayerUA',
'x<b': 'MultiplayerSpawn', 'mEH': 'PlayerPositionInSystem',
'l2U': 'PlayerTransformAt', 'tnP': 'ShipPositionInSystem',
'l4H': 'ShipTransformAt', 'jk4': 'LastKnownPlayerState',
'NGn': 'FreighterPositionInSystem', 'uAt': 'FreighterTransformAt',
'5Sg': 'FreighterTransformUp', 'wyZ': 'RepairTechBuffer',
'rnc': 'SpawnStateData', 'VuQ': 'GameKnowledgeData', 'yRy': 'Waypoints',
'S8b': 'GalaxyWaypointType', 'SSo': 'EventId',
'fDu': 'DiscoveryManagerData', 'ETO': 'DiscoveryData-v1',
'fgt': 'ReserveStore', 'xxK': 'ReserveManaged', 'OsQ': 'Store', '?fB':
'Record', '8P3': 'DD', '<Dn': 'DT', 'bEr': 'VP', 'q9a': 'DM','ksu': 'OWS',
'=wD': 'FL', 'bLr': 'C', 'tiH': 'tiH', 'brV': 'Available', 'kVv': 'TSrec',
';FZ': 'Enqueued', 'RVl': 'Palette', 'Ty=': 'ColourAlt', 'xEg': 'Colour',
'@6c': 'TextureOptionGroupName', '=Cv': 'TextureOptionName',
'tIm': 'BoneName', 'q5u': 'CN', 'kpg': 'MultiplayerPrivileges',
'M2L': 'EntitlementId', ';YC': 'MaintenanceContainer',
'WX8': 'InventoryIndex', 'V?r': 'H', 'sHl': 'Message', 'D6b': 'PTK',
'8GF': 'LastUABeforePortalWarp', 'eyv': 'LastCompletedTimestamp',
'FML': 'LastBrokenTimestamp', 'k8N': 'HotActions', 'sM@': 'KeyActions',
'TD8': 'Action', '<6x': 'QuickMenuActions', 'Y5p': 'Number',
'7Un': 'StoryPortalSeed', 'aPn': 'ShopNumber', 'rk3': 'ShopTier',
'QQp': 'HomeRealityIteration', 'MF2': 'KnownWordGroups',
'RiP': 'CookingIngredientsLayout', 'Kha': 'CookingIngredientsInventory',
'30s': 'OtherSideOfPortalReturnBase', 'Ue9': 'HasAccessToNexus',
'hiE': 'NexusUniverseAddress', 'Fk@': 'NexusMatrixAt',
'd72': 'NexusMatrixUp', 'Yel': 'NexusMatrixPos',
'j3Y': 'PhotoModeSettings', '9hR': 'BannerIcon',
'8DG': 'BannerMainColour', 'lmE': 'BannerBackgroundColour',
'qFl': 'TelemetryUploadVersion', 'qAx': 'Fog', '22a': 'CloudAmount',
'qLk': 'SunDir', 'OCG': 'SunDirSet', 'yGF': 'FoV', 'ARP': 'FoVSet',
'?sW': 'DepthOfField', '14a': 'DepthOfFieldAmount', 'L85': 'Vignette',
'HJQ': 'Filter', 'b76': 'FullyInstalled', 'MYl': 'Group',
'a>;': 'CalcWarpOffset', 'BpT': 'OriginalBaseVersion',
'J=S': 'LastEditedById', 'vyN': 'LastEditedByUsername'
}
def dump_file(save_filename, target_filename, decrypt=True):
# Load original file
save_file = open(save_filename, 'r', encoding='utf-8')
inpd = save_file.read()
if decrypt:
inpd = inpd[:-1]
save_data_raw = json.loads(inpd)
save_file.close()
# Parse json map
# json_map_f = open('jsonmap.txt', 'r', encoding='utf-8')
# json_map = {}
# json_map_r = {}
# for i in json_map_f.read().strip().split('\n'):
# _ = i.split('\t')
# if len(_) == 1:
# _.append(_[0])
# json_map[_[0]] = _[1]
# json_map_r[_[1]] = _[0]
json_map_r = {}
for i in json_map:
json_map_r[json_map[i]] = i
# Convert json
def conv(s, mp):
if isinstance(s, str):
return s
elif isinstance(s, list):
return list(conv(i, mp) for i in s)
elif isinstance(s, dict):
return dict((mp.get(i, i), conv(s[i], mp)) for i in s)
return s
if decrypt:
save_data = conv(save_data_raw, json_map)
output = json.dumps(save_data, indent=4)
else:
save_data = conv(save_data_raw, json_map_r)
output = json.dumps(save_data, indent=None,
separators=(',', ':')) + '\x00'
# Save file
t = open(target_filename, 'w')
t.write(output)
t.close()
return
if __name__ == '__main__':
if len(sys.argv) != 3:
print('python extract.py GAMESAVE.hg READABLE.json')
print('python extract.py READABLE.json GAMESAVE.hg')
print('either of the above')
else:
src = sys.argv[1]
trg = sys.argv[2]
dec = True
if not src.lower().endswith('.hg'):
dec = False
dump_file(src, trg, decrypt=dec)
exit(0)
Ayy thanks for that dude! Although the project only lived for around 48 hours, this will definitely come in handy in the future!
I'm currently working on a project that automatically unbricks savefiles (mainly for the BensAVirgin bug), but it would be nice if I could decrypt the savefile straight from a CLI command.. Something like https://github.com/matthew-humphrey/nmssavetool, but this one doesn't seem to properly work anymore