mirror of
https://github.com/lcdr/utils.git
synced 2024-08-30 17:32:16 +00:00
Added support for paths.
This commit is contained in:
parent
b7b2a922ad
commit
eb1e10a10f
136
luzviewer.pyw
136
luzviewer.pyw
@ -1,4 +1,5 @@
|
|||||||
import configparser
|
import configparser
|
||||||
|
import enum
|
||||||
import os.path
|
import os.path
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import sys
|
import sys
|
||||||
@ -8,7 +9,17 @@ import tkinter.messagebox as messagebox
|
|||||||
from tkinter import END, Menu
|
from tkinter import END, Menu
|
||||||
|
|
||||||
import viewer
|
import viewer
|
||||||
from pyraknet.bitstream import BitStream, c_float, c_int64, c_ubyte, c_uint, c_uint64, c_ushort
|
from pyraknet.bitstream import BitStream, c_float, c_int, c_int64, c_ubyte, c_uint, c_uint64, c_ushort
|
||||||
|
|
||||||
|
class PathType(enum.IntEnum):
|
||||||
|
Movement = 0
|
||||||
|
MovingPlatform = 1
|
||||||
|
Property = 2
|
||||||
|
Camera = 3
|
||||||
|
Spawner = 4
|
||||||
|
Showcase = 5
|
||||||
|
Race = 6
|
||||||
|
Rail = 7
|
||||||
|
|
||||||
class LUZViewer(viewer.Viewer):
|
class LUZViewer(viewer.Viewer):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -40,34 +51,45 @@ class LUZViewer(viewer.Viewer):
|
|||||||
stream = BitStream(file.read())
|
stream = BitStream(file.read())
|
||||||
|
|
||||||
version = stream.read(c_uint)
|
version = stream.read(c_uint)
|
||||||
assert version in (40, 41), version
|
assert version in (36, 38, 39, 40, 41), version
|
||||||
unknown1 = stream.read(c_uint)
|
unknown1 = stream.read(c_uint)
|
||||||
world_id = stream.read(c_uint)
|
world_id = stream.read(c_uint)
|
||||||
|
if version >= 38:
|
||||||
spawnpoint_pos = stream.read(c_float), stream.read(c_float), stream.read(c_float)
|
spawnpoint_pos = stream.read(c_float), stream.read(c_float), stream.read(c_float)
|
||||||
spawnpoint_rot = stream.read(c_float), stream.read(c_float), stream.read(c_float), stream.read(c_float)
|
spawnpoint_rot = stream.read(c_float), stream.read(c_float), stream.read(c_float), stream.read(c_float)
|
||||||
|
|
||||||
zone = self.tree.insert("", END, text="Zone", values=(version, unknown1, world_id, spawnpoint_pos, spawnpoint_rot))
|
zone = self.tree.insert("", END, text="Zone", values=(version, unknown1, world_id, spawnpoint_pos, spawnpoint_rot))
|
||||||
|
else:
|
||||||
|
zone = self.tree.insert("", END, text="Zone", values=(version, unknown1, world_id))
|
||||||
|
|
||||||
### scenes
|
### scenes
|
||||||
scenes = self.tree.insert(zone, END, text="Scenes")
|
scenes = self.tree.insert(zone, END, text="Scenes")
|
||||||
for _ in range(stream.read(c_uint)):
|
|
||||||
|
if version >= 37:
|
||||||
|
number_of_scenes = stream.read(c_uint)
|
||||||
|
else:
|
||||||
|
number_of_scenes = stream.read(c_ubyte)
|
||||||
|
|
||||||
|
for _ in range(number_of_scenes):
|
||||||
filename = stream.read(str, char_size=1, length_type=c_ubyte)
|
filename = stream.read(str, char_size=1, length_type=c_ubyte)
|
||||||
scene_id = stream.read(c_uint)
|
scene_id = stream.read(c_uint64)
|
||||||
is_audio = stream.read(c_uint)
|
|
||||||
scene_name = stream.read(str, char_size=1, length_type=c_ubyte)
|
scene_name = stream.read(str, char_size=1, length_type=c_ubyte)
|
||||||
if is_audio:
|
scene = self.tree.insert(scenes, END, text="Scene", values=(filename, scene_id, scene_name))
|
||||||
assert scene_name == "Audio"
|
assert stream.read(bytes, length=3)
|
||||||
scene = self.tree.insert(scenes, END, text="Scene", values=(filename, scene_id, is_audio, scene_name))
|
|
||||||
assert stream.read(bytes, length=3) == b"\xff\xff\xff"
|
|
||||||
with open(os.path.join(os.path.dirname(luz_path), filename), "rb") as lvl:
|
with open(os.path.join(os.path.dirname(luz_path), filename), "rb") as lvl:
|
||||||
print("Loading lvl", filename)
|
print("Loading lvl", filename)
|
||||||
|
try:
|
||||||
self.parse_lvl(BitStream(lvl.read()), scene)
|
self.parse_lvl(BitStream(lvl.read()), scene)
|
||||||
|
except Exception:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
assert stream.read(c_ubyte) == 0
|
assert stream.read(c_ubyte) == 0
|
||||||
|
|
||||||
### terrain
|
### terrain
|
||||||
filename = stream.read(str, char_size=1, length_type=c_ubyte)
|
filename = stream.read(str, char_size=1, length_type=c_ubyte)
|
||||||
name = stream.read(str, char_size=1, length_type=c_ubyte)
|
name = stream.read(str, char_size=1, length_type=c_ubyte)
|
||||||
description = stream.read(str, char_size=1, length_type=c_ubyte)
|
description = stream.read(str, char_size=1, length_type=c_ubyte)
|
||||||
self.tree.insert(zone, END, text="Terrain", values=(filename, name, description))
|
self.tree.insert(zone, END, text="Terrain", values=(filename, name, description))
|
||||||
|
|
||||||
### unknown
|
### unknown
|
||||||
unknowns = self.tree.insert(zone, END, text="Unknowns")
|
unknowns = self.tree.insert(zone, END, text="Unknowns")
|
||||||
for _ in range(stream.read(c_uint)):
|
for _ in range(stream.read(c_uint)):
|
||||||
@ -75,10 +97,102 @@ class LUZViewer(viewer.Viewer):
|
|||||||
unknown1 = stream.read(c_uint64)
|
unknown1 = stream.read(c_uint64)
|
||||||
unknown2 = stream.read(c_float), stream.read(c_float), stream.read(c_float)
|
unknown2 = stream.read(c_float), stream.read(c_float), stream.read(c_float)
|
||||||
self.tree.insert(unknowns, END, text="Unknown", values=(unknown1, unknown2))
|
self.tree.insert(unknowns, END, text="Unknown", values=(unknown1, unknown2))
|
||||||
|
|
||||||
remaining_length = stream.read(c_uint)
|
remaining_length = stream.read(c_uint)
|
||||||
assert len(stream) - stream._read_offset//8 == remaining_length
|
assert len(stream) - stream._read_offset//8 == remaining_length
|
||||||
assert stream.read(c_uint) == 1
|
assert stream.read(c_uint) == 1
|
||||||
|
|
||||||
|
### paths
|
||||||
|
paths = self.tree.insert(zone, END, text="Paths")
|
||||||
|
for _ in range(stream.read(c_uint)):
|
||||||
|
path_version = stream.read(c_uint)
|
||||||
|
name = stream.read(str, length_type=c_ubyte)
|
||||||
|
path_type = stream.read(c_uint)
|
||||||
|
unknown1 = stream.read(c_uint)
|
||||||
|
unknown2 = stream.read(c_uint)
|
||||||
|
values = path_version, name, unknown1, unknown2
|
||||||
|
|
||||||
|
if path_type == PathType.MovingPlatform:
|
||||||
|
if path_version >= 18:
|
||||||
|
unknown3 = stream.read(c_ubyte)
|
||||||
|
values += unknown3,
|
||||||
|
elif path_version >= 13:
|
||||||
|
unknown_str = stream.read(str, length_type=c_ubyte)
|
||||||
|
values += unknown_str,
|
||||||
|
|
||||||
|
elif path_type == PathType.Property:
|
||||||
|
unknown3 = stream.read(c_int), stream.read(c_int), stream.read(c_int), stream.read(c_uint64)
|
||||||
|
unknown_str1 = stream.read(str, length_type=c_ubyte)
|
||||||
|
unknown_str2 = stream.read(str, length_type=c_uint)
|
||||||
|
unknown4 = stream.read(c_int), stream.read(c_int), stream.read(c_float)
|
||||||
|
unknown5 = stream.read(c_int), stream.read(c_int)
|
||||||
|
unknown6 = stream.read(c_float), stream.read(c_float), stream.read(c_float), stream.read(c_float)
|
||||||
|
values += unknown3, unknown_str1, unknown_str2, unknown4, unknown5, unknown6
|
||||||
|
|
||||||
|
elif path_type == PathType.Camera:
|
||||||
|
unknown_str = stream.read(str, length_type=c_ubyte)
|
||||||
|
values += unknown_str,
|
||||||
|
if path_version >= 14:
|
||||||
|
unknown3 = stream.read(c_ubyte)
|
||||||
|
values += unknown3,
|
||||||
|
|
||||||
|
elif path_type == PathType.Spawner:
|
||||||
|
spawn_lot = stream.read(c_uint)
|
||||||
|
unknown3 = stream.read(c_uint), stream.read(c_int), stream.read(c_uint)
|
||||||
|
object_id = stream.read(c_int64)
|
||||||
|
unknown4 = stream.read(c_ubyte)
|
||||||
|
values += spawn_lot, unknown3, object_id, unknown4
|
||||||
|
|
||||||
|
path = self.tree.insert(paths, END, text=PathType(path_type).name, values=values)
|
||||||
|
|
||||||
|
for _ in range(stream.read(c_uint)):
|
||||||
|
position = stream.read(c_float), stream.read(c_float), stream.read(c_float)
|
||||||
|
|
||||||
|
waypoint_values = position,
|
||||||
|
|
||||||
|
if path_type == PathType.MovingPlatform:
|
||||||
|
rotation = stream.read(c_float), stream.read(c_float), stream.read(c_float), stream.read(c_float)
|
||||||
|
waypoint_unknown2 = stream.read(c_ubyte)
|
||||||
|
waypoint_unknown3 = stream.read(c_float), stream.read(c_float)
|
||||||
|
waypoint_values += rotation, waypoint_unknown2, waypoint_unknown3
|
||||||
|
|
||||||
|
if path_version >= 13:
|
||||||
|
waypoint_audio_guid_1 = stream.read(str, length_type=c_ubyte)
|
||||||
|
waypoint_audio_guid_2 = stream.read(str, length_type=c_ubyte)
|
||||||
|
waypoint_values += waypoint_audio_guid_1, waypoint_audio_guid_2
|
||||||
|
|
||||||
|
elif path_type == PathType.Camera:
|
||||||
|
waypoint_unknown1 = (
|
||||||
|
stream.read(c_float), stream.read(c_float), stream.read(c_float),
|
||||||
|
stream.read(c_float), stream.read(c_float), stream.read(c_float),
|
||||||
|
stream.read(c_float), stream.read(c_float), stream.read(c_float))
|
||||||
|
waypoint_values += waypoint_unknown1,
|
||||||
|
|
||||||
|
elif path_type == PathType.Spawner:
|
||||||
|
rotation = stream.read(c_float), stream.read(c_float), stream.read(c_float), stream.read(c_float)
|
||||||
|
waypoint_values += rotation,
|
||||||
|
|
||||||
|
elif path_type == PathType.Race:
|
||||||
|
waypoint_unknown1 = stream.read(c_float), stream.read(c_float), stream.read(c_float), stream.read(c_float)
|
||||||
|
waypoint_unknown2 = stream.read(c_ubyte), stream.read(c_ubyte)
|
||||||
|
waypoint_unknown3 = stream.read(c_float), stream.read(c_float), stream.read(c_float)
|
||||||
|
waypoint_values += waypoint_unknown1, waypoint_unknown2, waypoint_unknown3
|
||||||
|
|
||||||
|
elif path_type == PathType.Rail:
|
||||||
|
waypoint_unknown1 = stream.read(c_float), stream.read(c_float), stream.read(c_float), stream.read(c_float)
|
||||||
|
waypoint_values += waypoint_unknown1,
|
||||||
|
if path_version >= 17:
|
||||||
|
waypoint_unknown2 = stream.read(c_float)
|
||||||
|
waypoint_values += waypoint_unknown2,
|
||||||
|
|
||||||
|
waypoint = self.tree.insert(path, END, text="Waypoint", values=waypoint_values)
|
||||||
|
|
||||||
|
if path_type in (PathType.Movement, PathType.Spawner, PathType.Rail):
|
||||||
|
for _ in range(stream.read(c_uint)):
|
||||||
|
config_name = stream.read(str, length_type=c_ubyte)
|
||||||
|
config_type_and_value = stream.read(str, length_type=c_ubyte)
|
||||||
|
self.tree.insert(waypoint, END, text="Config", values=(config_name, config_type_and_value))
|
||||||
|
|
||||||
def parse_lvl(self, stream, scene):
|
def parse_lvl(self, stream, scene):
|
||||||
while not stream.all_read():
|
while not stream.all_read():
|
||||||
assert stream._read_offset//8 % 16 == 0 # seems everything is aligned like this?
|
assert stream._read_offset//8 % 16 == 0 # seems everything is aligned like this?
|
||||||
@ -127,7 +241,7 @@ class LUZViewer(viewer.Viewer):
|
|||||||
if item_type == "Zone":
|
if item_type == "Zone":
|
||||||
cols = "version", "unknown1", "world_id", "spawnpoint_pos", "spawnpoint_rot"
|
cols = "version", "unknown1", "world_id", "spawnpoint_pos", "spawnpoint_rot"
|
||||||
elif item_type == "Scene":
|
elif item_type == "Scene":
|
||||||
cols = "filename", "scene_id", "is_audio", "scene_name"
|
cols = "filename", "scene_id", "scene_name"
|
||||||
elif item_type == "Terrain":
|
elif item_type == "Terrain":
|
||||||
cols = "filename", "name", "description"
|
cols = "filename", "name", "description"
|
||||||
elif item_type == "Unknown":
|
elif item_type == "Unknown":
|
||||||
|
Loading…
Reference in New Issue
Block a user