new material version

This commit is contained in:
Skillbert
2025-12-08 18:36:31 +01:00
parent a3af98e663
commit 73fc407bc1
7 changed files with 845 additions and 724 deletions

View File

@@ -117,4 +117,69 @@ export type materials = {
unkFFFF: Uint8Array,
endbyte: number,
} | null,
v2: {
flags: number,
opaque_2: number,
flag3: number,
hasDiffuse: number,
hasNormal: number,
hasCompound: number,
hasUVanimU: number,
hasUVanimV: number,
flag10: number,
flag11: number,
flag12: number,
flag13: number,
flag14: number,
flag15: number,
flag16: number,
ignore_vertexcol_17: number,
flag18: number,
flag19: number,
flag20: number,
flag21: number,
diffuse: {
size: number,
texture: number,
} | null,
normal: {
size: number,
texture: number,
} | null,
compound: {
size: number,
texture: number,
} | null,
flag13value: number | null,
flag14value: [
number,
number,
] | null,
flag15value: number | null,
flag18value: number | null,
flag16value: number | null,
flag12value: number | null,
flag11value: [
number,
number,
number,
] | null,
flag19value: [
number,
number,
number,
number,
number,
] | null,
normalScale: number | null,
flag17value: number | null,
uvanim_u: number | null,
uvanim_v: number | null,
always_0x0901: Uint8Array,
unknownbyte0: number,
alphamode: number,
alphacutoff: number | null,
unkFFFF: Uint8Array,
endbyte: number,
} | null,
};

416
generated/npcs.d.ts vendored
View File

@@ -1,208 +1,208 @@
// GENERATED DO NOT EDIT
// This source data is located at '..\src\opcodes\npcs.jsonc'
// run `npm run filetypes` to rebuild
export type npcs = {
models?: (number|number)[] | null
name?: string | null
examine?: string | null
unknown_08?: number | null
unknown_0B?: number | null
boundSize?: number | null
unk_0D?: number | null
unk_0E?: number | null
unk_11?: number[] | null
actions_0?: string | null
actions_1?: string | null
actions_2?: string | null
actions_3?: string | null
actions_4?: string | null
color_replacements?: [
number,
number,
][] | null
material_replacements?: [
number,
number,
][] | null
recolourPalette?: number[] | null
recolor_indices?: number | null
retexture_indices?: number | null
headModels?: (number|number)[] | null
drawMapDot?: false | null
combat?: number | null
scaleXZ?: number | null
scaleY?: number | null
unknown_63?: true | null
ambience?: number | null
modelContract?: number | null
head_icon_data?: number | null
unknown_67?: number | null
morphs_1?: {
unk1: number,
unk2: number[],
unk3: (number|number),
} | null
unknown_6B?: false | null
slowWalk?: false | null
animateIdle?: false | null
shadow?: {
SrcColor: number,
DstColor: number,
} | null
shadowAlphaIntensity?: {
Src: number,
Dst: number,
} | null
unknown_73?: [
number,
number,
] | null
morphs_2?: {
unk1: number,
unk2: number,
unk3: number[],
unk4: number,
} | null
movementCapabilities?: number | null
unknown_78?: [
number,
number,
number,
number,
] | null
translations?: Uint8Array[] | null
unk_7A?: number | null
iconHeight?: number | null
respawnDirection?: number | null
animation_group?: number | null
movementType?: number | null
ambient_sound?: {
unk1: number,
unk2: number,
unk3: number,
unk4: number,
unk45: number,
} | null
oldCursor?: {
Op: number,
Cursor: number,
} | null
oldCursor2?: {
Op: number,
Cursor: number,
} | null
attackCursor?: number | null
armyIcon?: number | null
unknown_8C?: number | null
unknown_8D?: true | null
mapFunction?: number | null
unknown_8F?: true | null
members_actions_0?: string | null
members_actions_1?: string | null
members_actions_2?: string | null
members_actions_3?: string | null
members_actions_4?: string | null
unknown_9B?: {
unknown_1: number,
unknown_2: number,
unknown_3: number,
unknown_4: number,
} | null
aByte3076_set_1?: true | null
aByte3076_set_0?: false | null
quests?: number[] | null
dummy_1?: true | null
unknown_A3?: number | null
unknown_A4?: {
unknown_1: number,
unknown_2: number,
} | null
unknown_A5?: number | null
unknown_A8?: number | null
unknown_A9?: false | null
action_cursors_0?: number | null
action_cursors_1?: number | null
action_cursors_2?: number | null
action_cursors_3?: number | null
action_cursors_4?: number | null
action_cursors_5?: number | null
dummy_2?: true | null
unknown_B3?: {
unknown_1: number,
unknown_2: number,
unknown_3: number,
unknown_4: number,
unknown_5: number,
unknown_6: number,
} | null
unknown_B4?: number | null
unknown_B5?: {
unknown_1: number,
unknown_2: number,
} | null
unknown_B6?: true | null
unknown_B7?: number | null
unknown_B8?: number | null
unknown_B9?: true | null
unknown_BA?: {
unk0: number,
varbit: number,
varp: number,
flags: number,
multimodel: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
extracount: number,
extra1: number | null,
extra2: number | null,
extra3: number | null,
}[],
}[] | null,
multiheadmodel: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
}[],
}[] | null,
multiretex: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
unk4: number,
}[],
}[] | null,
multirecol: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
unk4: number,
}[],
}[] | null,
multiretint: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
}[],
}[] | null,
default: number,
} | null
unknown_DB?: number | null
extra?: {
prop: number,
intvalue: number | null,
stringvalue: string | null,
}[] | null
unknown_FD?: number | null
};
// GENERATED DO NOT EDIT
// This source data is located at '..\src\opcodes\npcs.jsonc'
// run `npm run filetypes` to rebuild
export type npcs = {
models?: (number|number)[] | null
name?: string | null
examine?: string | null
unknown_08?: number | null
unknown_0B?: number | null
boundSize?: number | null
unk_0D?: number | null
unk_0E?: number | null
unk_11?: number[] | null
actions_0?: string | null
actions_1?: string | null
actions_2?: string | null
actions_3?: string | null
actions_4?: string | null
color_replacements?: [
number,
number,
][] | null
material_replacements?: [
number,
number,
][] | null
recolourPalette?: number[] | null
recolor_indices?: number | null
retexture_indices?: number | null
headModels?: (number|number)[] | null
drawMapDot?: false | null
combat?: number | null
scaleXZ?: number | null
scaleY?: number | null
unknown_63?: true | null
ambience?: number | null
modelContract?: number | null
head_icon_data?: number | null
unknown_67?: number | null
morphs_1?: {
unk1: number,
unk2: number[],
unk3: (number|number),
} | null
unknown_6B?: false | null
slowWalk?: false | null
animateIdle?: false | null
shadow?: {
SrcColor: number,
DstColor: number,
} | null
shadowAlphaIntensity?: {
Src: number,
Dst: number,
} | null
unknown_73?: [
number,
number,
] | null
morphs_2?: {
unk1: number,
unk2: number,
unk3: number[],
unk4: number,
} | null
movementCapabilities?: number | null
unknown_78?: [
number,
number,
number,
number,
] | null
translations?: Uint8Array[] | null
unk_7A?: number | null
iconHeight?: number | null
respawnDirection?: number | null
animation_group?: number | null
movementType?: number | null
ambient_sound?: {
unk1: number,
unk2: number,
unk3: number,
unk4: number,
unk45: number,
} | null
oldCursor?: {
Op: number,
Cursor: number,
} | null
oldCursor2?: {
Op: number,
Cursor: number,
} | null
attackCursor?: number | null
armyIcon?: number | null
unknown_8C?: number | null
unknown_8D?: true | null
mapFunction?: number | null
unknown_8F?: true | null
members_actions_0?: string | null
members_actions_1?: string | null
members_actions_2?: string | null
members_actions_3?: string | null
members_actions_4?: string | null
unknown_9B?: {
unknown_1: number,
unknown_2: number,
unknown_3: number,
unknown_4: number,
} | null
aByte3076_set_1?: true | null
aByte3076_set_0?: false | null
quests?: number[] | null
dummy_1?: true | null
unknown_A3?: number | null
unknown_A4?: {
unknown_1: number,
unknown_2: number,
} | null
unknown_A5?: number | null
unknown_A8?: number | null
unknown_A9?: false | null
action_cursors_0?: number | null
action_cursors_1?: number | null
action_cursors_2?: number | null
action_cursors_3?: number | null
action_cursors_4?: number | null
action_cursors_5?: number | null
dummy_2?: true | null
unknown_B3?: {
unknown_1: number,
unknown_2: number,
unknown_3: number,
unknown_4: number,
unknown_5: number,
unknown_6: number,
} | null
unknown_B4?: number | null
unknown_B5?: {
unknown_1: number,
unknown_2: number,
} | null
unknown_B6?: true | null
unknown_B7?: number | null
unknown_B8?: number | null
unknown_B9?: true | null
unknown_BA?: {
unk0: number,
varbit: number,
varp: number,
flags: number,
multimodel: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
extracount: number,
extra1: number | null,
extra2: number | null,
extra3: number | null,
}[],
}[] | null,
multiheadmodel: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
}[],
}[] | null,
multiretex: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
unk4: number,
}[],
}[] | null,
multirecol: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
unk4: number,
}[],
}[] | null,
multiretint: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
}[],
}[] | null,
default: number,
} | null
unknown_DB?: number | null
extra?: {
prop: number,
intvalue: number | null,
stringvalue: string | null,
}[] | null
unknown_FD?: number | null
};

492
generated/objects.d.ts vendored
View File

@@ -1,246 +1,246 @@
// GENERATED DO NOT EDIT
// This source data is located at '..\src\opcodes\objects.jsonc'
// run `npm run filetypes` to rebuild
export type objects = {
models?: ({
type: number,
values: (number|number)[],
}[]|{
values: (number|number)[],
type: number,
}[]) | null
name?: string | null
examine?: string | null
models_05?: ({
models: {
type: number,
values: (number|number)[],
}[],
unktail: [
(number|number),
(number|number),
][],
}|{
models: {
type: 10,
values: (number|number)[],
unktail: [
(number|number),
(number|number),
][],
}[],
}) | null
width?: number | null
length?: number | null
probably_nocollision?: true | null
maybe_allows_lineofsight?: true | null
deletable?: boolean | null
probably_morphFloor?: true | null
unknown_16?: true | null
occludes_1?: false | null
probably_animation?: number | null
maybe_blocks_movement?: true | null
wallkit_related_1C?: number | null
ambient?: number | null
actions_0?: string | null
actions_1?: string | null
actions_2?: string | null
actions_3?: string | null
actions_4?: string | null
contrast?: number | null
color_replacements?: [
number,
number,
][] | null
material_replacements?: [
number,
number,
][] | null
recolourPalette?: number[] | null
unknown_2C?: number | null
unknown_2D?: number | null
unknown_36?: true | null
unknown_37?: true | null
unknown_38?: true | null
unknown_39?: true | null
unknown_3c?: number | null
mirror?: true | null
unknown_40?: true | null
scaleX?: number | null
scaleY?: number | null
scaleZ?: number | null
mapscene_old?: number | null
dummy_45?: number | null
translateX?: number | null
translateY?: number | null
translateZ?: number | null
unknown_49?: true | null
unknown_4A?: true | null
unknown_4B?: number | null
morphs_1?: {
unk1: number,
unk2: (number|number)[],
unk3: (number|number),
} | null
light_source_related_4E?: {
maybe_color: number,
maybe_radius: number,
} | null
unknown_4F?: {
unknown_1: number,
unknown_2: number,
unknown_3: number,
unknown_4: number[],
} | null
unknown_51?: number | null
unknown_52?: true | null
is_members?: true | null
unknown_59?: true | null
unknown_5A?: true | null
isMembers?: true | null
morphs_2?: {
unk1: number,
unk2: (number|number),
unk3: (number|number)[],
unk4: (number|number),
} | null
tilt_xz?: [
number,
number,
] | null
under_water?: true | null
probably_morphCeilingOffset?: (number|0) | null
unknown_60?: true | null
ground_decoration_related_61?: true | null
has_animated_texture?: true | null
dummy_63?: {
unknown_2: number,
unknown_1: number,
} | null
dummy_64?: {
unknown_2: number,
unknown_1: number,
} | null
unused_65?: number | null
mapscene?: number | null
occludes_2?: false | null
interactable_related_68?: number | null
invertMapScene?: true | null
headModels?: {
model: number,
unknown_2: number,
}[] | null
mapFunction?: number | null
unknown_71?: number | null
members_action_1?: string | null
members_action_2?: string | null
members_action_3?: string | null
members_action_4?: string | null
members_action_5?: string | null
unknown_A0?: number[] | null
singleuse_A2?: number | null
unknown_A3?: {
unknown_1: number,
unknown_2: number,
unknown_3: number,
unknown_4: number,
} | null
singleuse_A4?: number | null
singleuse_A5?: number | null
singleuse_A6?: number | null
floor_thickness?: number | null
unused_a8?: true | null
unused_a9?: true | null
wallkit_related_AA?: number | null
possibly_wallkit_skew_AB?: number | null
lightsource_related_AD?: {
unknown_1: number,
unknown_2: number,
} | null
can_change_color?: true | null
unknown_B2?: number | null
unknown_BA?: number | null
dummy_bc?: true | null
treerockordoor_BD?: true | null
action_cursors_0?: number | null
action_cursors_1?: number | null
action_cursors_2?: number | null
action_cursors_3?: number | null
action_cursors_4?: number | null
action_cursors_5?: number | null
tileplacement_related_c4?: number | null
clan_citadel_C5?: number | null
invisible_c6?: true | null
flooroverlay_c7?: true | null
singleuse_C8?: true | null
unknown_C9?: {
unknown_1: number,
unknown_2: number,
unknown_3: number,
unknown_4: number,
unknown_5: number,
unknown_6: number,
} | null
singleuse_CA?: number | null
unknown_CB?: true | null
unknown_CC?: Uint8Array[] | null
unknown_CD?: {
unk0: number,
varbit: number,
varp: number,
flags: number,
multimodel: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
extracount: number,
extra1: number | null,
extra2: number | null,
extra3: number | null,
}[],
}[] | null,
multiheadmodel: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
}[],
}[] | null,
multiretex: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
unk4: number,
}[],
}[] | null,
multirecol: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
unk4: number,
}[],
}[] | null,
multiretint: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
}[],
}[] | null,
default: number,
} | null
extra?: {
prop: number,
intvalue: number | null,
stringvalue: string | null,
}[] | null
};
// GENERATED DO NOT EDIT
// This source data is located at '..\src\opcodes\objects.jsonc'
// run `npm run filetypes` to rebuild
export type objects = {
models?: ({
type: number,
values: (number|number)[],
}[]|{
values: (number|number)[],
type: number,
}[]) | null
name?: string | null
examine?: string | null
models_05?: ({
models: {
type: number,
values: (number|number)[],
}[],
unktail: [
(number|number),
(number|number),
][],
}|{
models: {
type: 10,
values: (number|number)[],
unktail: [
(number|number),
(number|number),
][],
}[],
}) | null
width?: number | null
length?: number | null
probably_nocollision?: true | null
maybe_allows_lineofsight?: true | null
deletable?: boolean | null
probably_morphFloor?: true | null
unknown_16?: true | null
occludes_1?: false | null
probably_animation?: number | null
maybe_blocks_movement?: true | null
wallkit_related_1C?: number | null
ambient?: number | null
actions_0?: string | null
actions_1?: string | null
actions_2?: string | null
actions_3?: string | null
actions_4?: string | null
contrast?: number | null
color_replacements?: [
number,
number,
][] | null
material_replacements?: [
number,
number,
][] | null
recolourPalette?: number[] | null
unknown_2C?: number | null
unknown_2D?: number | null
unknown_36?: true | null
unknown_37?: true | null
unknown_38?: true | null
unknown_39?: true | null
unknown_3c?: number | null
mirror?: true | null
unknown_40?: true | null
scaleX?: number | null
scaleY?: number | null
scaleZ?: number | null
mapscene_old?: number | null
dummy_45?: number | null
translateX?: number | null
translateY?: number | null
translateZ?: number | null
unknown_49?: true | null
unknown_4A?: true | null
unknown_4B?: number | null
morphs_1?: {
unk1: number,
unk2: (number|number)[],
unk3: (number|number),
} | null
light_source_related_4E?: {
maybe_color: number,
maybe_radius: number,
} | null
unknown_4F?: {
unknown_1: number,
unknown_2: number,
unknown_3: number,
unknown_4: number[],
} | null
unknown_51?: number | null
unknown_52?: true | null
is_members?: true | null
unknown_59?: true | null
unknown_5A?: true | null
isMembers?: true | null
morphs_2?: {
unk1: number,
unk2: (number|number),
unk3: (number|number)[],
unk4: (number|number),
} | null
tilt_xz?: [
number,
number,
] | null
under_water?: true | null
probably_morphCeilingOffset?: (number|0) | null
unknown_60?: true | null
ground_decoration_related_61?: true | null
has_animated_texture?: true | null
dummy_63?: {
unknown_2: number,
unknown_1: number,
} | null
dummy_64?: {
unknown_2: number,
unknown_1: number,
} | null
unused_65?: number | null
mapscene?: number | null
occludes_2?: false | null
interactable_related_68?: number | null
invertMapScene?: true | null
headModels?: {
model: number,
unknown_2: number,
}[] | null
mapFunction?: number | null
unknown_71?: number | null
members_action_1?: string | null
members_action_2?: string | null
members_action_3?: string | null
members_action_4?: string | null
members_action_5?: string | null
unknown_A0?: number[] | null
singleuse_A2?: number | null
unknown_A3?: {
unknown_1: number,
unknown_2: number,
unknown_3: number,
unknown_4: number,
} | null
singleuse_A4?: number | null
singleuse_A5?: number | null
singleuse_A6?: number | null
floor_thickness?: number | null
unused_a8?: true | null
unused_a9?: true | null
wallkit_related_AA?: number | null
possibly_wallkit_skew_AB?: number | null
lightsource_related_AD?: {
unknown_1: number,
unknown_2: number,
} | null
can_change_color?: true | null
unknown_B2?: number | null
unknown_BA?: number | null
dummy_bc?: true | null
treerockordoor_BD?: true | null
action_cursors_0?: number | null
action_cursors_1?: number | null
action_cursors_2?: number | null
action_cursors_3?: number | null
action_cursors_4?: number | null
action_cursors_5?: number | null
tileplacement_related_c4?: number | null
clan_citadel_C5?: number | null
invisible_c6?: true | null
flooroverlay_c7?: true | null
singleuse_C8?: true | null
unknown_C9?: {
unknown_1: number,
unknown_2: number,
unknown_3: number,
unknown_4: number,
unknown_5: number,
unknown_6: number,
} | null
singleuse_CA?: number | null
unknown_CB?: true | null
unknown_CC?: Uint8Array[] | null
unknown_CD?: {
unk0: number,
varbit: number,
varp: number,
flags: number,
multimodel: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
extracount: number,
extra1: number | null,
extra2: number | null,
extra3: number | null,
}[],
}[] | null,
multiheadmodel: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
}[],
}[] | null,
multiretex: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
unk4: number,
}[],
}[] | null,
multirecol: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
unk4: number,
}[],
}[] | null,
multiretint: {
value: number,
models: {
unk1: number,
unk2: number,
unk3: number,
}[],
}[] | null,
default: number,
} | null
extra?: {
prop: number,
intvalue: number | null,
stringvalue: string | null,
}[] | null
};

View File

@@ -1,7 +0,0 @@
// GENERATED DO NOT EDIT
// This source data is located at '..\src\opcodes\playerkit.jsonc'
// run `npm run filetypes` to rebuild
export type playerkit = {
name?: string | null
};

View File

@@ -1,105 +1,106 @@
import { HSL2RGBfloat, packedHSL2HSL } from "../utils";
import { parse } from "../opdecoder";
import type { materials } from "../../generated/materials";
import type { CacheFileSource } from "cache";
type TextureRepeatMode = "clamp" | "repeat" | "mirror";
export type MaterialData = {
textures: {
diffuse?: number,
normal?: number,
compound?: number
},
texmodes: TextureRepeatMode,
texmodet: TextureRepeatMode,
uvAnim: { u: number, v: number } | undefined,
baseColorFraction: number
baseColor: [number, number, number],
alphamode: "opaque" | "cutoff" | "blend",
alphacutoff: number,
stripDiffuseAlpha: boolean,
raw: materials | null
}
export function defaultMaterial(): MaterialData {
return {
textures: {},
texmodes: "repeat",
texmodet: "repeat",
uvAnim: undefined,
baseColorFraction: 0,
baseColor: [1, 1, 1],
alphamode: "opaque",
alphacutoff: 0.1,
stripDiffuseAlpha: false,
raw: null
}
}
export function materialCacheKey(matid: number, hasVertexAlpha: boolean, minimapVariant: boolean) {
return (matid == -1 ? 0x3fffff : matid) | (hasVertexAlpha ? 0x800000 : 0) | (minimapVariant ? 0x400000 : 0);
}
export function convertMaterial(data: Buffer, materialid: number, source: CacheFileSource) {
let rawparsed = parse.materials.read(data, source);
let mat = defaultMaterial();
mat.raw = rawparsed;
if (rawparsed.v0) {
let raw = rawparsed.v0;
let olddiffuse = raw.arr.find(q => q.op == 1);
if (olddiffuse) {
//in caches after this the diffuse prop exists, but is ignored...
if (source.getBuildNr() <= 838) {
mat.textures.diffuse = olddiffuse.value;
} else {
mat.textures.diffuse = materialid;
}
} else if (raw.diffuse) {
mat.textures.diffuse = raw.diffuse;
} else if (raw.textureflags & 0x11) {
mat.textures.diffuse = materialid;
}
if (raw.normal) {
mat.textures.normal = raw.normal;
} else if (raw.textureflags & 0x0a) {
mat.textures.normal = materialid;
}
let repeatu = raw.texrepeatflags & 0x7;
let repeatv = (raw.textureflags >> 2) & 0x7;
mat.texmodes = repeatu == 0 ? "mirror" : repeatu == 1 ? "repeat" : "clamp";
mat.texmodet = repeatv == 0 ? "mirror" : repeatv == 1 ? "repeat" : "clamp";
mat.alphamode = raw.alphamode == 0 ? "opaque" : raw.alphamode == 1 ? "cutoff" : "blend";
if (raw.alphacutoff) { mat.alphacutoff = raw.alphacutoff / 255; }
if (raw.animtexU || raw.animtexV) {
let scale = 1 / (1 << 15);
mat.uvAnim = { u: (raw.animtexU ?? 0) * scale, v: (raw.animtexV ?? 0) * scale };
}
if (raw.extra) {
mat.baseColorFraction = raw.extra.baseColorFraction / 255;
//seems like 0 is a special case, but unclear
mat.baseColor = (raw.extra.baseColor == 0 ? [1, 1, 1] : HSL2RGBfloat(packedHSL2HSL(raw.extra.baseColor)));
}
mat.stripDiffuseAlpha = (mat.alphamode == "opaque");
} else if (rawparsed.v1) {
let raw = rawparsed.v1;
//this is very wrong
mat.alphamode = (raw.opaque_2 && !raw.hasUVanimU ? "cutoff" : "blend");
mat.baseColorFraction = 1;
if (raw.diffuse) { mat.textures.diffuse = raw.diffuse.texture; }
if (raw.normal) { mat.textures.normal = raw.normal.texture; }
if (raw.compound) { mat.textures.compound = raw.compound.texture; }
if (raw.uvanim_u || raw.uvanim_v) {
let scale = 1 / (1 << 15);
mat.uvAnim = { u: (raw.uvanim_u ?? 0) * scale, v: (raw.uvanim_v ?? 0) * scale };
}
} else {
throw new Error("unkown material version " + rawparsed.version);
}
return mat;
}
import { HSL2RGBfloat, packedHSL2HSL } from "../utils";
import { parse } from "../opdecoder";
import type { materials } from "../../generated/materials";
import type { CacheFileSource } from "cache";
type TextureRepeatMode = "clamp" | "repeat" | "mirror";
export type MaterialData = {
textures: {
diffuse?: number,
normal?: number,
compound?: number
},
texmodes: TextureRepeatMode,
texmodet: TextureRepeatMode,
uvAnim: { u: number, v: number } | undefined,
baseColorFraction: number
baseColor: [number, number, number],
alphamode: "opaque" | "cutoff" | "blend",
alphacutoff: number,
stripDiffuseAlpha: boolean,
raw: materials | null
}
export function defaultMaterial(): MaterialData {
return {
textures: {},
texmodes: "repeat",
texmodet: "repeat",
uvAnim: undefined,
baseColorFraction: 0,
baseColor: [1, 1, 1],
alphamode: "opaque",
alphacutoff: 0.1,
stripDiffuseAlpha: false,
raw: null
}
}
export function materialCacheKey(matid: number, hasVertexAlpha: boolean, minimapVariant: boolean) {
return (matid == -1 ? 0x3fffff : matid) | (hasVertexAlpha ? 0x800000 : 0) | (minimapVariant ? 0x400000 : 0);
}
export function convertMaterial(data: Buffer, materialid: number, source: CacheFileSource) {
let rawparsed = parse.materials.read(data, source);
let mat = defaultMaterial();
mat.raw = rawparsed;
if (rawparsed.v0) {
let raw = rawparsed.v0;
let olddiffuse = raw.arr.find(q => q.op == 1);
if (olddiffuse) {
//in caches after this the diffuse prop exists, but is ignored...
if (source.getBuildNr() <= 838) {
mat.textures.diffuse = olddiffuse.value;
} else {
mat.textures.diffuse = materialid;
}
} else if (raw.diffuse) {
mat.textures.diffuse = raw.diffuse;
} else if (raw.textureflags & 0x11) {
mat.textures.diffuse = materialid;
}
if (raw.normal) {
mat.textures.normal = raw.normal;
} else if (raw.textureflags & 0x0a) {
mat.textures.normal = materialid;
}
let repeatu = raw.texrepeatflags & 0x7;
let repeatv = (raw.textureflags >> 2) & 0x7;
mat.texmodes = repeatu == 0 ? "mirror" : repeatu == 1 ? "repeat" : "clamp";
mat.texmodet = repeatv == 0 ? "mirror" : repeatv == 1 ? "repeat" : "clamp";
mat.alphamode = raw.alphamode == 0 ? "opaque" : raw.alphamode == 1 ? "cutoff" : "blend";
if (raw.alphacutoff) { mat.alphacutoff = raw.alphacutoff / 255; }
if (raw.animtexU || raw.animtexV) {
let scale = 1 / (1 << 15);
mat.uvAnim = { u: (raw.animtexU ?? 0) * scale, v: (raw.animtexV ?? 0) * scale };
}
if (raw.extra) {
mat.baseColorFraction = raw.extra.baseColorFraction / 255;
//seems like 0 is a special case, but unclear
mat.baseColor = (raw.extra.baseColor == 0 ? [1, 1, 1] : HSL2RGBfloat(packedHSL2HSL(raw.extra.baseColor)));
}
mat.stripDiffuseAlpha = (mat.alphamode == "opaque");
} else if (rawparsed.v1 || rawparsed.v2) {
// currently v1 and v2 have the same structure
let raw = (rawparsed.v1 || rawparsed.v2)!;
//this is very wrong
mat.alphamode = (raw.opaque_2 && !raw.hasUVanimU ? "cutoff" : "blend");
mat.baseColorFraction = 1;
if (raw.diffuse) { mat.textures.diffuse = raw.diffuse.texture; }
if (raw.normal) { mat.textures.normal = raw.normal.texture; }
if (raw.compound) { mat.textures.compound = raw.compound.texture; }
if (raw.uvanim_u || raw.uvanim_v) {
let scale = 1 / (1 << 15);
mat.uvAnim = { u: (raw.uvanim_u ?? 0) * scale, v: (raw.uvanim_v ?? 0) * scale };
}
} else {
throw new Error("unkown material version " + rawparsed.version);
}
return mat;
}

View File

@@ -1,44 +1,44 @@
import * as fs from "fs";
import * as path from "path";
import * as opcode_reader from "./opcode_reader";
import * as commentjson from "comment-json";
import { maprenderConfigSchema } from "./jsonschemas";
async function buildFileTypes() {
let basedir = path.resolve("./src/opcodes");
let outdir = path.resolve("./generated");
//generate config file metas
let files = fs.readdirSync(basedir);
if (files.some(f => !path.basename(f).match(/\.jsonc?$/))) {
console.error("non-json files matched, is path wrong?");
}
const typedef = commentjson.parse(fs.readFileSync(path.resolve(basedir, "typedef.jsonc"), "utf-8"), undefined, true);
for (let file of files) {
let srcfile = path.resolve(basedir, file);
let objname = path.parse(srcfile).name;
let jsontext = fs.readFileSync(srcfile, "utf8");
const opcodes = commentjson.parse(jsontext, undefined, true);
var typesfile =
"// GENERATED DO NOT EDIT\n" +
"// This source data is located at '" + path.relative(outdir, srcfile) + "'\n" +
"// run `npm run filetypes` to rebuild\n\n";
typesfile += "export type " + objname + " = ";
try {
typesfile += opcode_reader.buildParser(null, opcodes as any, typedef as any).getTypescriptType("") + ";\n";
} catch (e) {
//console.error(e);
typesfile += "any;\n";
typesfile += "// " + e.toString().replace(/\n/g, "\n//");
}
//I'm sorry, git made me do this
typesfile = typesfile.replace(/(?<!\r)\n/g, "\r\n");
let outfile = path.resolve(outdir, objname + ".d.ts");
fs.writeFileSync(outfile, typesfile);
}
//other one off files
fs.writeFileSync(path.resolve(outdir, "maprenderconfig.schema.json"), JSON.stringify(maprenderConfigSchema, undefined, "\t"));
}
import * as fs from "fs";
import * as path from "path";
import * as opcode_reader from "./opcode_reader";
import * as commentjson from "comment-json";
import { maprenderConfigSchema } from "./jsonschemas";
async function buildFileTypes() {
let basedir = path.resolve("./src/opcodes");
let outdir = path.resolve("./generated");
//generate config file metas
let files = fs.readdirSync(basedir);
if (files.some(f => !path.basename(f).match(/\.jsonc?$/))) {
console.error("non-json files matched, is path wrong?");
}
const typedef = commentjson.parse(fs.readFileSync(path.resolve(basedir, "typedef.jsonc"), "utf-8"), undefined, true);
for (let file of files) {
let srcfile = path.resolve(basedir, file);
let objname = path.parse(srcfile).name;
let jsontext = fs.readFileSync(srcfile, "utf8");
const opcodes = commentjson.parse(jsontext, undefined, true);
var typesfile =
"// GENERATED DO NOT EDIT\n" +
"// This source data is located at '" + path.relative(outdir, srcfile) + "'\n" +
"// run `npm run filetypes` to rebuild\n\n";
typesfile += "export type " + objname + " = ";
try {
typesfile += opcode_reader.buildParser(null, opcodes as any, typedef as any).getTypescriptType("") + ";\n";
} catch (e) {
//console.error(e);
typesfile += "any;\n";
typesfile += "// " + e.toString().replace(/\n/g, "\n//");
}
//I'm sorry, git made me do this
// typesfile = typesfile.replace(/(?<!\r)\n/g, "\r\n");
let outfile = path.resolve(outdir, objname + ".d.ts");
fs.writeFileSync(outfile, typesfile);
}
//other one off files
fs.writeFileSync(path.resolve(outdir, "maprenderconfig.schema.json"), JSON.stringify(maprenderConfigSchema, undefined, "\t"));
}
buildFileTypes();

View File

@@ -1,116 +1,178 @@
["struct",
["version",["match","buildnr",{">=887":"ubyte",">=0":0}]],
["v0",["opt",["version",0],["struct",
["unk0","ubyte"],//always 0-4
["texsize","ushort"],//256,512,0, but doesn't always correspond to actualtex
//always 0000 after 2015
["opt0","ubyte"],
["opt0data",["opt",["opt0",16],["tuple","ubyte","ushort"]]],
["arr",["nullarray","ubyte",["struct",
["op",["ref","$opcode"]],
["value","ushort"]
]]],
["textureflags","ubyte"],//always 1,3,9,16
["diffuse",["opt",["textureflags",17,"bitor"],["match","buildnr",{">=887":"uint",">=0":0}]]],
["normal",["opt",["textureflags",10,"bitor"],["match","buildnr",{">=887":"uint",">=0":0}]]],
["texrepeatflags",["match","buildnr",{">=876":"ubyte",">=0":0}]],
["unk3_skybox",["match","buildnr",{">=876":["buffer",3,"hex"],">=0":"null"}]],//looks like a bitflag thing, bit weird
["flags2","ubyte"],//always 12,13,14,28
["unkfloats",["opt",["flags2",4,"bitflag"],["tuple","float","float"]]],//always 1; 1,4,32
["unk7","ubyte"],//0,1,62,63,64,255
["weirdshit",["opt",["unk7",255],["buffer",19,"hex"]]],//only one single material that has this
["diffuse_related1",["match","buildnr",{">=887":["opt",["textureflags",4,"bitflag"],"ubyte"],">=0":"ubyte"}]],//always 1 or null
["normal_related",["opt",["textureflags",1,"bitflag"],["buffer",4,"hex"]]],//0x80000000 most of the time
["diffuse_related2",["match","buildnr",{">=887":["opt",["textureflags",0,"bitflag"],"ubyte"],">=0":"ubyte"}]],//always 1,0 or null
["diffuse_ralated2_data",["opt",["diffuse_related2",2],"ubyte"]],//last used 2015
["alphamode","ubyte"],//0,1 or 2
["alphacutoff",["opt",["alphamode",1],"ubyte"]],//128 most of the time
["animtex","ubyte"],//0123
["animtexU",["opt",["animtex",0,"bitflag"],["match","buildnr",{">=897":"short",">=0":"byte"}]]],
["animtexV",["opt",["animtex",1,"bitflag"],["match","buildnr",{">=897":"short",">=0":"byte"}]]],
["flagextra","bool"],
["extra",["opt",["flagextra",1],["struct",
["unk00_flags","ubyte"],//flags 1=alpha channel reuse,2=water/lava/bloom?,4=water/dg water,8=water, all skyboxes have 6
["unk01_flagsornumber","ubyte"],//0123 OR a high number (only 20 uses)
["unk02","ubyte"],//0 if unk01=0123 or number (only 4 uses)
["unknown",["buffer",4,"hex"]],//mostly 0 except for some ~15 water materials
["unk07_bool","bool"],
["unk08_flags","ubyte"],//0=5k,1=1,2=5k
["unk09_bool","bool"],//true=7
["unk0a_bool","bool"],
["specular","ubyte"],
["baseColorFraction","ubyte"],//indicates the mix ratio with colorint and vertex colors
["baseColor","ushort"]
]]]
]]],
["v1",["opt",["version",1],["struct",
["flags","uint"],
//0,1 unused
["opaque_2",["ref","flags",[2,1]]],//3061/3250
["flag3",["ref","flags",[3,1]]],//3095 most mats without are never used in a model
//4unused
["hasDiffuse",["ref","flags",[5,1]]],//3250, always true
["hasNormal",["ref","flags",[6,1]]],//2878
["hasCompound",["ref","flags",[7,1]]],//2223
["hasUVanimU",["ref","flags",[8,1]]],//44 uv anim u?
["hasUVanimV",["ref","flags",[9,1]]],//49 uv anim v?
["flag10",["ref","flags",[10,1]]],//282 possibly bloom
["flag11",["ref","flags",[11,1]]],//41 metalic?
["flag12",["ref","flags",[12,1]]],//1 use
["flag13",["ref","flags",[13,1]]],//73 glasslike diffraction/lensing? https://runescape.wiki/w/Altar_of_War
["flag14",["ref","flags",[14,1]]],//3179
["flag15",["ref","flags",[15,1]]],//2 use, skybox and https://runescape.wiki/w/Oathbreaker_Outfit
["flag16",["ref","flags",[16,1]]],//3069
["ignore_vertexcol_17",["ref","flags",[17,1]]],//338
["flag18",["ref","flags",[18,1]]],//24 uses different skybox? ghostlike stuff https://runescape.wiki/w/Closure%27s_robes
["flag19",["ref","flags",[19,1]]],//5 use gives aurora effect https://runescape.wiki/w/Bohr
["flag20",["ref","flags",[20,1]]],//40 seems to be used on flants/leafs
["flag21",["ref","flags",[21,1]]],//3250 all materials
//22+ unused
["diffuse",["opt",["hasDiffuse",1],["struct",
["size","ubyte"],//actual size (some times) equal to 2^(6+size)
["texture","uint"]
]]],
["normal",["opt",["hasNormal",1],["struct",
["size","ubyte"],//actual size (some times) equal to 2^(6+size)
["texture","uint"]
]]],
["compound",["opt",["hasCompound",1],["struct",
["size","ubyte"],//actual size (some times) equal to 2^(6+size)
["texture","uint"]
]]],
["flag13value",["opt",["flag13",1],"float"]],
["flag14value",["opt",["flag14",1],["tuple","ushort","ushort"]]],//0,8520 or 13083 only, referencing other material?
["flag15value",["opt",["flag15",1],"float"]],
["flag18value",["opt",["flag18",1],"float"]],//not sure about location
["flag16value",["opt",["flag16",1],"float"]],
["flag12value",["opt",["flag12",1],"float"]],//not sure about location
["flag11value",["opt",["flag11",1],["tuple","float","float","float"]]],
["flag19value",["opt",["flag19",1],["tuple","float","float","float","float","float"]]],//location unknown
["normalScale",["opt",["hasNormal",1],"float"]],
["flag17value",["opt",["ignore_vertexcol_17",1],"float"]],
["uvanim_u",["opt",["hasUVanimU",1],"short"]],
["uvanim_v",["opt",["hasUVanimV",1],"short"]],
["always_0x0901",["buffer",2,"hex"]],//only a couple with 0001
["unknownbyte0","ubyte"],//always 0
["alphamode","ubyte"],//0,1,2
["alphacutoff",["opt",["alphamode",1],"ubyte"]],//127 most of the time
["unkFFFF",["buffer",2,"hex"]],
["endbyte","ubyte"]//usually equal to max texture size always 0-4
]]]
["struct",
["version",["match","buildnr",{">=887":"ubyte",">=0":0}]],
["v0",["opt",["version",0],["struct",
["unk0","ubyte"],//always 0-4
["texsize","ushort"],//256,512,0, but doesn't always correspond to actualtex
//always 0000 after 2015
["opt0","ubyte"],
["opt0data",["opt",["opt0",16],["tuple","ubyte","ushort"]]],
["arr",["nullarray","ubyte",["struct",
["op",["ref","$opcode"]],
["value","ushort"]
]]],
["textureflags","ubyte"],//always 1,3,9,16
["diffuse",["opt",["textureflags",17,"bitor"],["match","buildnr",{">=887":"uint",">=0":0}]]],
["normal",["opt",["textureflags",10,"bitor"],["match","buildnr",{">=887":"uint",">=0":0}]]],
["texrepeatflags",["match","buildnr",{">=876":"ubyte",">=0":0}]],
["unk3_skybox",["match","buildnr",{">=876":["buffer",3,"hex"],">=0":"null"}]],//looks like a bitflag thing, bit weird
["flags2","ubyte"],//always 12,13,14,28
["unkfloats",["opt",["flags2",4,"bitflag"],["tuple","float","float"]]],//always 1; 1,4,32
["unk7","ubyte"],//0,1,62,63,64,255
["weirdshit",["opt",["unk7",255],["buffer",19,"hex"]]],//only one single material that has this
["diffuse_related1",["match","buildnr",{">=887":["opt",["textureflags",4,"bitflag"],"ubyte"],">=0":"ubyte"}]],//always 1 or null
["normal_related",["opt",["textureflags",1,"bitflag"],["buffer",4,"hex"]]],//0x80000000 most of the time
["diffuse_related2",["match","buildnr",{">=887":["opt",["textureflags",0,"bitflag"],"ubyte"],">=0":"ubyte"}]],//always 1,0 or null
["diffuse_ralated2_data",["opt",["diffuse_related2",2],"ubyte"]],//last used 2015
["alphamode","ubyte"],//0,1 or 2
["alphacutoff",["opt",["alphamode",1],"ubyte"]],//128 most of the time
["animtex","ubyte"],//0123
["animtexU",["opt",["animtex",0,"bitflag"],["match","buildnr",{">=897":"short",">=0":"byte"}]]],
["animtexV",["opt",["animtex",1,"bitflag"],["match","buildnr",{">=897":"short",">=0":"byte"}]]],
["flagextra","bool"],
["extra",["opt",["flagextra",1],["struct",
["unk00_flags","ubyte"],//flags 1=alpha channel reuse,2=water/lava/bloom?,4=water/dg water,8=water, all skyboxes have 6
["unk01_flagsornumber","ubyte"],//0123 OR a high number (only 20 uses)
["unk02","ubyte"],//0 if unk01=0123 or number (only 4 uses)
["unknown",["buffer",4,"hex"]],//mostly 0 except for some ~15 water materials
["unk07_bool","bool"],
["unk08_flags","ubyte"],//0=5k,1=1,2=5k
["unk09_bool","bool"],//true=7
["unk0a_bool","bool"],
["specular","ubyte"],
["baseColorFraction","ubyte"],//indicates the mix ratio with colorint and vertex colors
["baseColor","ushort"]
]]]
]]],
["v1",["opt",["version",1],["struct",
["flags","uint"],
//0,1 unused
["opaque_2",["ref","flags",[2,1]]],//3061/3250
["flag3",["ref","flags",[3,1]]],//3095 most mats without are never used in a model
//4unused
["hasDiffuse",["ref","flags",[5,1]]],//3250, always true
["hasNormal",["ref","flags",[6,1]]],//2878
["hasCompound",["ref","flags",[7,1]]],//2223
["hasUVanimU",["ref","flags",[8,1]]],//44 uv anim u?
["hasUVanimV",["ref","flags",[9,1]]],//49 uv anim v?
["flag10",["ref","flags",[10,1]]],//282 possibly bloom
["flag11",["ref","flags",[11,1]]],//41 metalic?
["flag12",["ref","flags",[12,1]]],//1 use
["flag13",["ref","flags",[13,1]]],//73 glasslike diffraction/lensing? https://runescape.wiki/w/Altar_of_War
["flag14",["ref","flags",[14,1]]],//3179
["flag15",["ref","flags",[15,1]]],//2 use, skybox and https://runescape.wiki/w/Oathbreaker_Outfit
["flag16",["ref","flags",[16,1]]],//3069
["ignore_vertexcol_17",["ref","flags",[17,1]]],//338
["flag18",["ref","flags",[18,1]]],//24 uses different skybox? ghostlike stuff https://runescape.wiki/w/Closure%27s_robes
["flag19",["ref","flags",[19,1]]],//5 use gives aurora effect https://runescape.wiki/w/Bohr
["flag20",["ref","flags",[20,1]]],//40 seems to be used on flants/leafs
["flag21",["ref","flags",[21,1]]],//3250 all materials
//22+ unused
["diffuse",["opt",["hasDiffuse",1],["struct",
["size","ubyte"],//actual size (some times) equal to 2^(6+size)
["texture","uint"]
]]],
["normal",["opt",["hasNormal",1],["struct",
["size","ubyte"],//actual size (some times) equal to 2^(6+size)
["texture","uint"]
]]],
["compound",["opt",["hasCompound",1],["struct",
["size","ubyte"],//actual size (some times) equal to 2^(6+size)
["texture","uint"]
]]],
["flag13value",["opt",["flag13",1],"float"]],
["flag14value",["opt",["flag14",1],["tuple","ushort","ushort"]]],//0,8520 or 13083 only, referencing other material?
["flag15value",["opt",["flag15",1],"float"]],
["flag18value",["opt",["flag18",1],"float"]],//not sure about location
["flag16value",["opt",["flag16",1],"float"]],
["flag12value",["opt",["flag12",1],"float"]],//not sure about location
["flag11value",["opt",["flag11",1],["tuple","float","float","float"]]],
["flag19value",["opt",["flag19",1],["tuple","float","float","float","float","float"]]],//location unknown
["normalScale",["opt",["hasNormal",1],"float"]],
["flag17value",["opt",["ignore_vertexcol_17",1],"float"]],
["uvanim_u",["opt",["hasUVanimU",1],"short"]],
["uvanim_v",["opt",["hasUVanimV",1],"short"]],
["always_0x0901",["buffer",2,"hex"]],//only a couple with 0001
["unknownbyte0","ubyte"],//always 0
["alphamode","ubyte"],//0,1,2
["alphacutoff",["opt",["alphamode",1],"ubyte"]],//127 most of the time
["unkFFFF",["buffer",2,"hex"]],
["endbyte","ubyte"]//usually equal to max texture size always 0-4
]]],
// seems to be the same as v1 so far
["v2",["opt",["version",2],["struct",
["flags","uint"],
//0,1 unused
["opaque_2",["ref","flags",[2,1]]],//3061/3250
["flag3",["ref","flags",[3,1]]],//3095 most mats without are never used in a model
//4unused
["hasDiffuse",["ref","flags",[5,1]]],//3250, always true
["hasNormal",["ref","flags",[6,1]]],//2878
["hasCompound",["ref","flags",[7,1]]],//2223
["hasUVanimU",["ref","flags",[8,1]]],//44 uv anim u?
["hasUVanimV",["ref","flags",[9,1]]],//49 uv anim v?
["flag10",["ref","flags",[10,1]]],//282 possibly bloom
["flag11",["ref","flags",[11,1]]],//41 metalic?
["flag12",["ref","flags",[12,1]]],//1 use
["flag13",["ref","flags",[13,1]]],//73 glasslike diffraction/lensing? https://runescape.wiki/w/Altar_of_War
["flag14",["ref","flags",[14,1]]],//3179
["flag15",["ref","flags",[15,1]]],//2 use, skybox and https://runescape.wiki/w/Oathbreaker_Outfit
["flag16",["ref","flags",[16,1]]],//3069
["ignore_vertexcol_17",["ref","flags",[17,1]]],//338
["flag18",["ref","flags",[18,1]]],//24 uses different skybox? ghostlike stuff https://runescape.wiki/w/Closure%27s_robes
["flag19",["ref","flags",[19,1]]],//5 use gives aurora effect https://runescape.wiki/w/Bohr
["flag20",["ref","flags",[20,1]]],//40 seems to be used on flants/leafs
["flag21",["ref","flags",[21,1]]],//3250 all materials
//22+ unused
["diffuse",["opt",["hasDiffuse",1],["struct",
["size","ubyte"],//actual size (some times) equal to 2^(6+size)
["texture","uint"]
]]],
["normal",["opt",["hasNormal",1],["struct",
["size","ubyte"],//actual size (some times) equal to 2^(6+size)
["texture","uint"]
]]],
["compound",["opt",["hasCompound",1],["struct",
["size","ubyte"],//actual size (some times) equal to 2^(6+size)
["texture","uint"]
]]],
["flag13value",["opt",["flag13",1],"float"]],
["flag14value",["opt",["flag14",1],["tuple","ushort","ushort"]]],//0,8520 or 13083 only, referencing other material?
["flag15value",["opt",["flag15",1],"float"]],
["flag18value",["opt",["flag18",1],"float"]],//not sure about location
["flag16value",["opt",["flag16",1],"float"]],
["flag12value",["opt",["flag12",1],"float"]],//not sure about location
["flag11value",["opt",["flag11",1],["tuple","float","float","float"]]],
["flag19value",["opt",["flag19",1],["tuple","float","float","float","float","float"]]],//location unknown
["normalScale",["opt",["hasNormal",1],"float"]],
["flag17value",["opt",["ignore_vertexcol_17",1],"float"]],
["uvanim_u",["opt",["hasUVanimU",1],"short"]],
["uvanim_v",["opt",["hasUVanimV",1],"short"]],
["always_0x0901",["buffer",2,"hex"]],//only a couple with 0001
["unknownbyte0","ubyte"],//always 0
["alphamode","ubyte"],//0,1,2
["alphacutoff",["opt",["alphamode",1],"ubyte"]],//127 most of the time
["unkFFFF",["buffer",2,"hex"]],
["endbyte","ubyte"]//usually equal to max texture size always 0-4
]]]
]