/Aimware

Aimware Libraries

Primary LanguageLua

# Aimware

Aimware Libraries local M = {}

-- -- dependencies

local ffi = require "ffi" local vtable = require "vtable" local csgo_weapons = require "csgo_weapons"

local string_gsub = string.gsub local math_floor = math.floor local cast = ffi.cast

-- -- ffi structs -- (mostly for image parsing)

local png_ihdr_t = ffi.typeof( [[ struct { char type[4]; uint32_t width; uint32_t height; char bitDepth; char colorType; char compression; char filter; char interlace; } * ]] )

local jpg_segment_t = ffi.typeof([[ struct { char type[2]; uint16_t size; } * ]])

local jpg_segment_sof0_t = ffi.typeof([[ struct { uint16_t size; char precision; uint16_t height; uint16_t width; } attribute((packed)) * ]])

local uint16_t_ptr = ffi.typeof("uint16_t*") local charbuffer = ffi.typeof("char[?]") local uintbuffer = ffi.typeof("unsigned int[?]")

-- -- constants

local INVALID_TEXTURE = -1 local PNG_MAGIC = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"

local JPG_MAGIC_1 = "\xFF\xD8\xFF\xDB" local JPG_MAGIC_2 = "\xFF\xD8\xFF\xE0\x00\x10\x4A\x46\x49\x46\x00\x01"

local JPG_SEGMENT_SOI = "\xFF\xD8" local JPG_SEGMENT_SOF0 = "\xFF\xC0" local JPG_SEGMENT_SOS = "\xFF\xDA" local JPG_SEGMENT_EOI = "\xFF\xD9"

local RENDERER_LOAD_FUNCS = { png = function(contents, width, height) local rgba, _width, _height = common.DecodePNG(contents) return draw.CreateTexture(rgba, _width, _height) end, svg = function(contents, width, height) local rgba, _width, _height = common.RasterizeSVG(contents) return draw.CreateTexture(rgba, _width, _height) end, jpg = function(contents, width, height) local rgba, _width, _height = common.DecodeJPEG(contents) return draw.CreateTexture(rgba, _width, _height) end, rgba = draw.CreateTexture }

-- -- utility functions

local function bswap_16(x) return bit.rshift(bit.bswap(x), 16) end

local function hexdump(str) local out = {} str:gsub( ".", function(chr) table.insert(out, string.format("%02x", string.byte(chr))) end ) return table.concat(out, " ") end

-- -- small filesystem implementation

local native_ReadFile = vtable.bind("filesystem_stdio.dll", "VBaseFileSystem011", 0, "int(__thiscall*)(void*, void*, int, void*)") local native_OpenFile = vtable.bind("filesystem_stdio.dll", "VBaseFileSystem011", 2, "void*(__thiscall*)(void*, const char*, const char*, const char*)") local native_CloseFile = vtable.bind("filesystem_stdio.dll", "VBaseFileSystem011", 3, "void(__thiscall*)(void*, void*)") local native_GetFileSize = vtable.bind("filesystem_stdio.dll", "VBaseFileSystem011", 7, "unsigned int(__thiscall*)(void*, void*)")

local function engine_read_file(filename) local handle = native_OpenFile(filename, "r", "MOD") if handle == nil then return end

local filesize = native_GetFileSize(handle)
if filesize == nil or filesize < 0 then
	return
end

local buffer = charbuffer(filesize + 1)
if buffer == nil then
	return
end

local read_success = native_ReadFile(buffer, filesize, handle)
if not read_success then
	return
end

return ffi.string(buffer, filesize)

end

-- -- ISteamFriends / ISteamUtils

-- That shit now use ingame context of steamapi instead of connecting to global user -- enjoy, by w7rus

ffi.cdef( [[ typedef struct { void* steam_client; void* steam_user; void* steam_friends; void* steam_utils; void* steam_matchmaking; void* steam_user_stats; void* steam_apps; void* steam_matchmakingservers; void* steam_networking; void* steam_remotestorage; void* steam_screenshots; void* steam_http; void* steam_unidentifiedmessages; void* steam_controller; void* steam_ugc; void* steam_applist; void* steam_music; void* steam_musicremote; void* steam_htmlsurface; void* steam_inventory; void* steam_video; } S_steamApiCtx_t; ]] )

local pS_SteamApiCtx = ffi.cast("S_steamApiCtx_t**", ffi.cast("char*", mem.FindPattern("client.dll", "FF 15 ?? ?? ?? ?? B9 ?? ?? ?? ?? E8 ?? ?? ?? ?? 6A")) + 7)[0] or error("invalid interface", 2)

local native_ISteamFriends = ffi.cast("void***", pS_SteamApiCtx.steam_friends) local native_ISteamUtils = ffi.cast("void***", pS_SteamApiCtx.steam_utils)

local native_ISteamFriends_GetSmallFriendAvatar = vtable.thunk(34, "int(__thiscall*)(void*, uint64_t)") local native_ISteamFriends_GetMediumFriendAvatar = vtable.thunk(35, "int(__thiscall*)(void*, uint64_t)") local native_ISteamFriends_GetLargeFriendAvatar = vtable.thunk(36, "int(__thiscall*)(void*, uint64_t)")

local native_ISteamUtils_GetImageSize = vtable.thunk(5, "bool(__thiscall*)(void*, int, uint32_t*, uint32_t*)") local native_ISteamUtils_GetImageRGBA = vtable.thunk(6, "bool(__thiscall*)(void*, int, unsigned char*, int)")

-- -- image object implementation

local function image_measure(self, width, height) if width ~= nil and height ~= nil then return math_floor(width), math_floor(height) else if self.width == nil or self.height == nil then error("Image dimensions not known, full size is required") elseif width == nil then height = height or self.height local width = math_floor(self.width * (height / self.height)) return width, height elseif height == nil then width = width or self.width local height = math_floor(self.height * (width / self.width)) return width, height else return math_floor(self.width), math_floor(self.height) end end end

local function image_draw(self, x, y, width, height, r, g, b, a, force_same_res_render) width, height = image_measure(self, width, height)

local id = string.format("%f_%f", width, height)
local texture = self.textures[id]

-- no texture with same width and height has been loaded
if texture == nil then
	if ({next(self.textures)})[2] == nil or force_same_res_render or force_same_res_render == nil then
		-- try and load the texture
		local func = RENDERER_LOAD_FUNCS[self.type]
		if func then
			if self.type == "rgba" then
				width, height = self.width, self.height
			end
			texture = func(self.contents, width, height)
		end

		if texture == nil then
			self.textures[id] = INVALID_TEXTURE
			error("failed to load texture for " .. width .. "x" .. height, 2)
		else
			-- client.log("loaded svg ", self.name, " for ", width, "x", height)
			self.textures[id] = texture
		end
	else
		--right now we just choose a random texture (determined by the pairs order aka unordered)
		--todo: select the texture with the highest or closest resolution?
		texture = ({next(self.textures)})[2]
	end
end

if texture == nil or texture == INVALID_TEXTURE then
	return
elseif a == nil or a > 0 then
	draw.SetTexture(texture)

	draw.Color(r or 255, g or 255, b or 255, a or 255)
	draw.FilledRect(x, y, x + width, y + height)
	draw.SetTexture(nil)
end

return width, height

end

local image_mt = { __index = { measure = image_measure, draw = image_draw } }

-- -- functions for loading images

local function load_png(contents) if contents:sub(1, 8) ~= PNG_MAGIC then error("Invalid magic", 2) return end

local ihdr_raw = contents:sub(13, 30)
if ihdr_raw:len() < 17 then
	error("Incomplete data", 2)
	return
end

local ihdr = cast(png_ihdr_t, cast("const uint8_t *", cast("const char*", ihdr_raw)))

if ffi.string(ihdr.type, 4) ~= "IHDR" then
	error("Invalid chunk type, expected IHDR", 2)
	return
end

local width = bit.bswap(ihdr.width)
local height = bit.bswap(ihdr.height)

if width <= 0 or height <= 0 then
	error("Invalid width or height", 2)
	return
end

return setmetatable(
	{
		type = "png",
		width = width,
		height = height,
		contents = contents,
		textures = {}
	},
	image_mt
)

end

local function load_jpg(contents) local buffer = ffi.cast("const uint8_t *", ffi.cast("const char *", contents)) local len_remaining = contents:len()

local width, height

if contents:sub(1, 4) == JPG_MAGIC_1 or contents:sub(1, 12) == JPG_MAGIC_2 then
	local got_soi, got_sos = false, false

	-- read segments until we find a SOF0 header (containing width/height)
	while len_remaining > 0 do
		local segment = ffi.cast(jpg_segment_t, buffer)
		local typ = ffi.string(segment.type, 2)

		buffer = buffer + 2
		len_remaining = len_remaining - 2

		if typ == JPG_SEGMENT_SOI then
			got_soi = true
		elseif not got_soi then
			error("expected SOI segment", 2)
		elseif typ == JPG_SEGMENT_SOS or typ == JPG_SEGMENT_EOI then
			if typ == JPG_SEGMENT_SOS then
				got_sos = true
			end
			break
		else
			-- endian convert of the size (be -> le)
			local size = bswap_16(segment.size)

			if typ == JPG_SEGMENT_SOF0 then
				local sof0 = cast(jpg_segment_sof0_t, buffer)

				height = bswap_16(sof0.height)
				width = bswap_16(sof0.width)

				if width <= 0 or height <= 0 then
					error("Invalid width or height")
					return
				end
			end

			buffer = buffer + size
			len_remaining = len_remaining - size
		end
	end

	if not got_soi then
		error("Incomplete image, missing SOI segment", 2)
		return
	elseif not got_sos then
		error("Incomplete image, missing SOS segment", 2)
		return
	elseif width == nil then
		error("Incomplete image, missing SOF0 segment", 2)
		return
	end
else
	error("Invalid magic", 2)
	return
end

return setmetatable(
	{
		type = "jpg",
		width = width,
		height = height,
		contents = contents,
		textures = {}
	},
	image_mt
)

end

local function load_svg(contents) -- try and find tag

local match = contents:match("<svg(.*)>.*</svg>")
if match == nil then
	error("Invalid svg, missing <svg> tag", 2)
	return
end

match = match:gsub("\r\n", ""):gsub("\n", "")

-- parse tag contents
local in_quote = false
local key, value = "", ""

local attributes = {}

local offset = 1
while true do
	local chr = match:sub(offset, offset)

	if chr == "" then
		break
	end

	if in_quote then
		-- text inside quotation marks
		if chr == '"' then
			in_quote = false
			attributes[key:gsub("\t", ""):lower()] = value
			key, value = "", ""
		else
			value = value .. chr
		end
	else
		-- normal text, not inside quotes
		if chr == ">" then
			break
		elseif chr == "=" then
			if match:sub(offset, offset + 1) == '="' then
				in_quote = true
				offset = offset + 1
			end
		elseif chr == " " then
			key = ""
		else
			key = key .. chr
		end
	end

	offset = offset + 1
end

-- heuristics to find valid image width and height
local width, height

if attributes["width"] ~= nil then
	width = tonumber((attributes["width"]:gsub("px$", ""):gsub("pt$", ""):gsub("mm$", "")))

	if width ~= nil and 0 >= width then
		width = nil
	end
end

if attributes["height"] ~= nil then
	height = tonumber((attributes["height"]:gsub("px$", ""):gsub("pt$", ""):gsub("mm$", "")))

	if height ~= nil and 0 >= height then
		height = nil
	end
end

if width == nil or height == nil and attributes["viewbox"] ~= nil then
	local x, y, w, h = attributes["viewbox"]:match("^%s*([%d.]*) ([%d.]*) ([%d.]*) ([%d.]*)%s*$")

	width, height = tonumber(width), tonumber(height)

	if width ~= nil and height ~= nil and (0 >= width or 0 >= height) then
		width, height = nil, nil
	end
end

local self =
	setmetatable(
	{
		type = "svg",
		contents = contents,
		textures = {}
	},
	image_mt
)

if width ~= nil and height ~= nil and width > 0 and height > 0 then
	self.width, self.height = width, height
end

return self

end

local function load_rgba(contents, width, height) if width == nil or height == nil or width <= 0 or height <= 0 then error("Invalid size: width and height are required and have to be greater than zero.") return end

local size = width * height * 4
if contents:len() ~= size then
	error("invalid buffer length, expected width*height*4", 2)
	return
end

-- load texture
local texture = draw.CreateTexture(contents, width, height)
if texture == nil then
	return
end

return setmetatable(
	{
		type = "rgba",
		width = width,
		height = height,
		contents = contents,
		textures = {[string.format("%f_%f", width, height)] = texture}
	},
	image_mt
)

end

local function load_image(contents) if type(contents) == "table" then if getmetatable(contents) == image_mt then return error("trying to load an existing image") else local result = {} for key, value in pairs(contents) do result[key] = load_image(value) end return result end else -- try and determine type etc by looking for magic value if type(contents) == "string" then if contents:sub(1, 8) == PNG_MAGIC then return load_png(contents) elseif contents:sub(1, 4) == JPG_MAGIC_1 or contents:sub(1, 12) == JPG_MAGIC_2 then return load_jpg(contents) elseif contents:match("^%s*%<%?xml") ~= nil then return load_svg(contents) else return error("Failed to determine image type") end end end end

local panorama_images = setmetatable({}, {__mode = "k"}) local function get_panorama_image(path) if panorama_images[path] == nil then local path_cleaned = string_gsub(string_gsub(string_gsub(string_gsub(string_gsub(path, "%z", ""), "%c", ""), "\", "/"), "%.%./", ""), "^/+", "") local contents = engine_read_file("materials/panorama/images/" .. path_cleaned)

	if contents then
		local image = load_image(contents)

		panorama_images[path] = image
	else
		panorama_images[path] = false
	end
end

if panorama_images[path] then
	return panorama_images[path]
end

end

local weapon_icons = setmetatable({}, {__mode = "k"}) local function get_weapon_icon(weapon_name) if weapon_icons[weapon_name] == nil then local weapon_name_cleaned local typ = type(weapon_name)

	if typ == "table" and weapon_name.console_name ~= nil then
		weapon_name_cleaned = weapon_name.console_name
	elseif typ == "number" then
		local weapon = csgo_weapons[weapon_name]
		if weapon == nil then
			weapon_icons[weapon_name] = false
			return
		end
		weapon_name_cleaned = weapon.console_name
	elseif typ == "string" then
		weapon_name_cleaned = tostring(weapon_name)
	elseif weapon_name ~= nil then
		weapon_icons[weapon_name] = nil
		return
	else
		return
	end

	weapon_name_cleaned = string_gsub(string_gsub(weapon_name_cleaned, "^weapon_", ""), "^item_", "")

	local image = get_panorama_image("icons/equipment/" .. weapon_name_cleaned .. ".svg")
	weapon_icons[weapon_name] = image or false
end

if weapon_icons[weapon_name] then
	return weapon_icons[weapon_name]
end

end

local steam_avatars = {} local function get_steam_avatar(steamid3_or_steamid64, size) local cache_key = string.format("%s_%d", steamid3_or_steamid64, size or 32)

if steam_avatars[cache_key] == nil then
	local func
	if size == nil then
		func = native_ISteamFriends_GetSmallFriendAvatar
	elseif size > 64 then
		func = native_ISteamFriends_GetLargeFriendAvatar
	elseif size > 32 then
		func = native_ISteamFriends_GetMediumFriendAvatar
	else
		func = native_ISteamFriends_GetSmallFriendAvatar
	end

	local steamid
	if type(steamid3_or_steamid64) == "string" then
		steamid = 76500000000000000ULL + tonumber(steamid3_or_steamid64:sub(4, -1))
	elseif type(steamid3_or_steamid64) == "number" then
		steamid = 76561197960265728ULL + steamid3_or_steamid64
	else
		return
	end

	local handle = func(native_ISteamFriends, steamid)

	if handle > 0 then
		local width = uintbuffer(1)
		local height = uintbuffer(1)
		if native_ISteamUtils_GetImageSize(native_ISteamUtils, handle, width, height) then
			if width[0] > 0 and height[0] > 0 then
				local rgba_buffer_size = width[0] * height[0] * 4
				local rgba_buffer = charbuffer(rgba_buffer_size)

				if native_ISteamUtils_GetImageRGBA(native_ISteamUtils, handle, rgba_buffer, rgba_buffer_size) then
					steam_avatars[cache_key] = load_rgba(ffi.string(rgba_buffer, rgba_buffer_size), width[0], height[0])
				end
			end
		end
	elseif handle ~= -1 then
		steam_avatars[cache_key] = false
	end
end

if steam_avatars[cache_key] then
	return steam_avatars[cache_key]
end

end

return { load = load_image, load_png = load_png, load_jpg = load_jpg, load_svg = load_svg, load_rgba = load_rgba, get_weapon_icon = get_weapon_icon, get_panorama_image = get_panorama_image, get_steam_avatar = get_steam_avatar }

Code


--
-- dependencies
--

local ffi = require "ffi"
local vtable = require "vtable"
local csgo_weapons = require "csgo_weapons"

local string_gsub = string.gsub
local math_floor = math.floor
local cast = ffi.cast

--
-- ffi structs
-- (mostly for image parsing)
--

local png_ihdr_t =
	ffi.typeof(
	[[
struct {
	char type[4];
	uint32_t width;
	uint32_t height;
	char bitDepth;
	char colorType;
	char compression;
	char filter;
	char interlace;
} *
]]
)

local jpg_segment_t = ffi.typeof([[
struct {
	char type[2];
	uint16_t size;
} *
]])

local jpg_segment_sof0_t =
	ffi.typeof([[
struct {
	uint16_t size;
	char precision;
	uint16_t height;
	uint16_t width;
} __attribute__((packed)) *
]])

local uint16_t_ptr = ffi.typeof("uint16_t*")
local charbuffer = ffi.typeof("char[?]")
local uintbuffer = ffi.typeof("unsigned int[?]")

--
-- constants
--

local INVALID_TEXTURE = -1
local PNG_MAGIC = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"

local JPG_MAGIC_1 = "\xFF\xD8\xFF\xDB"
local JPG_MAGIC_2 = "\xFF\xD8\xFF\xE0\x00\x10\x4A\x46\x49\x46\x00\x01"

local JPG_SEGMENT_SOI = "\xFF\xD8"
local JPG_SEGMENT_SOF0 = "\xFF\xC0"
local JPG_SEGMENT_SOS = "\xFF\xDA"
local JPG_SEGMENT_EOI = "\xFF\xD9"

local RENDERER_LOAD_FUNCS = {
	png = function(contents, width, height)
		local rgba, _width, _height = common.DecodePNG(contents)
		return draw.CreateTexture(rgba, _width, _height)
	end,
	svg = function(contents, width, height)
		local rgba, _width, _height = common.RasterizeSVG(contents)
		return draw.CreateTexture(rgba, _width, _height)
	end,
	jpg = function(contents, width, height)
		local rgba, _width, _height = common.DecodeJPEG(contents)
		return draw.CreateTexture(rgba, _width, _height)
	end,
	rgba = draw.CreateTexture
}

--
-- utility functions
--

local function bswap_16(x)
	return bit.rshift(bit.bswap(x), 16)
end

local function hexdump(str)
	local out = {}
	str:gsub(
		".",
		function(chr)
			table.insert(out, string.format("%02x", string.byte(chr)))
		end
	)
	return table.concat(out, " ")
end

--
-- small filesystem implementation
--

local native_ReadFile = vtable.bind("filesystem_stdio.dll", "VBaseFileSystem011", 0, "int(__thiscall*)(void*, void*, int, void*)")
local native_OpenFile =
	vtable.bind("filesystem_stdio.dll", "VBaseFileSystem011", 2, "void*(__thiscall*)(void*, const char*, const char*, const char*)")
local native_CloseFile = vtable.bind("filesystem_stdio.dll", "VBaseFileSystem011", 3, "void(__thiscall*)(void*, void*)")
local native_GetFileSize = vtable.bind("filesystem_stdio.dll", "VBaseFileSystem011", 7, "unsigned int(__thiscall*)(void*, void*)")

local function engine_read_file(filename)
	local handle = native_OpenFile(filename, "r", "MOD")
	if handle == nil then
		return
	end

	local filesize = native_GetFileSize(handle)
	if filesize == nil or filesize < 0 then
		return
	end

	local buffer = charbuffer(filesize + 1)
	if buffer == nil then
		return
	end

	local read_success = native_ReadFile(buffer, filesize, handle)
	if not read_success then
		return
	end

	return ffi.string(buffer, filesize)
end

--
-- ISteamFriends / ISteamUtils
--

-- That shit now use ingame context of steamapi instead of connecting to global user
-- enjoy, by w7rus

ffi.cdef(
	[[
	typedef struct
	{
		void* steam_client;
		void* steam_user;
		void* steam_friends;
		void* steam_utils;
		void* steam_matchmaking;
		void* steam_user_stats;
		void* steam_apps;
		void* steam_matchmakingservers;
		void* steam_networking;
		void* steam_remotestorage;
		void* steam_screenshots;
		void* steam_http;
		void* steam_unidentifiedmessages;
		void* steam_controller;
		void* steam_ugc;
		void* steam_applist;
		void* steam_music;
		void* steam_musicremote;
		void* steam_htmlsurface;
		void* steam_inventory;
		void* steam_video;
	} S_steamApiCtx_t;
]]
)

local pS_SteamApiCtx =
	ffi.cast("S_steamApiCtx_t**", ffi.cast("char*", mem.FindPattern("client.dll", "FF 15 ?? ?? ?? ?? B9 ?? ?? ?? ?? E8 ?? ?? ?? ?? 6A")) + 7)[0] or
	error("invalid interface", 2)

local native_ISteamFriends = ffi.cast("void***", pS_SteamApiCtx.steam_friends)
local native_ISteamUtils = ffi.cast("void***", pS_SteamApiCtx.steam_utils)

local native_ISteamFriends_GetSmallFriendAvatar = vtable.thunk(34, "int(__thiscall*)(void*, uint64_t)")
local native_ISteamFriends_GetMediumFriendAvatar = vtable.thunk(35, "int(__thiscall*)(void*, uint64_t)")
local native_ISteamFriends_GetLargeFriendAvatar = vtable.thunk(36, "int(__thiscall*)(void*, uint64_t)")

local native_ISteamUtils_GetImageSize = vtable.thunk(5, "bool(__thiscall*)(void*, int, uint32_t*, uint32_t*)")
local native_ISteamUtils_GetImageRGBA = vtable.thunk(6, "bool(__thiscall*)(void*, int, unsigned char*, int)")

--
-- image object implementation
--

local function image_measure(self, width, height)
	if width ~= nil and height ~= nil then
		return math_floor(width), math_floor(height)
	else
		if self.width == nil or self.height == nil then
			error("Image dimensions not known, full size is required")
		elseif width == nil then
			height = height or self.height
			local width = math_floor(self.width * (height / self.height))
			return width, height
		elseif height == nil then
			width = width or self.width
			local height = math_floor(self.height * (width / self.width))
			return width, height
		else
			return math_floor(self.width), math_floor(self.height)
		end
	end
end

local function image_draw(self, x, y, width, height, r, g, b, a, force_same_res_render)
	width, height = image_measure(self, width, height)

	local id = string.format("%f_%f", width, height)
	local texture = self.textures[id]

	-- no texture with same width and height has been loaded
	if texture == nil then
		if ({next(self.textures)})[2] == nil or force_same_res_render or force_same_res_render == nil then
			-- try and load the texture
			local func = RENDERER_LOAD_FUNCS[self.type]
			if func then
				if self.type == "rgba" then
					width, height = self.width, self.height
				end
				texture = func(self.contents, width, height)
			end

			if texture == nil then
				self.textures[id] = INVALID_TEXTURE
				error("failed to load texture for " .. width .. "x" .. height, 2)
			else
				-- client.log("loaded svg ", self.name, " for ", width, "x", height)
				self.textures[id] = texture
			end
		else
			--right now we just choose a random texture (determined by the pairs order aka unordered)
			--todo: select the texture with the highest or closest resolution?
			texture = ({next(self.textures)})[2]
		end
	end

	if texture == nil or texture == INVALID_TEXTURE then
		return
	elseif a == nil or a > 0 then
		draw.SetTexture(texture)

		draw.Color(r or 255, g or 255, b or 255, a or 255)
		draw.FilledRect(x, y, x + width, y + height)
		draw.SetTexture(nil)
	end

	return width, height
end

local image_mt = {
	__index = {
		measure = image_measure,
		draw = image_draw
	}
}

--
-- functions for loading images
--

local function load_png(contents)
	if contents:sub(1, 8) ~= PNG_MAGIC then
		error("Invalid magic", 2)
		return
	end

	local ihdr_raw = contents:sub(13, 30)
	if ihdr_raw:len() < 17 then
		error("Incomplete data", 2)
		return
	end

	local ihdr = cast(png_ihdr_t, cast("const uint8_t *", cast("const char*", ihdr_raw)))

	if ffi.string(ihdr.type, 4) ~= "IHDR" then
		error("Invalid chunk type, expected IHDR", 2)
		return
	end

	local width = bit.bswap(ihdr.width)
	local height = bit.bswap(ihdr.height)

	if width <= 0 or height <= 0 then
		error("Invalid width or height", 2)
		return
	end

	return setmetatable(
		{
			type = "png",
			width = width,
			height = height,
			contents = contents,
			textures = {}
		},
		image_mt
	)
end

local function load_jpg(contents)
	local buffer = ffi.cast("const uint8_t *", ffi.cast("const char *", contents))
	local len_remaining = contents:len()

	local width, height

	if contents:sub(1, 4) == JPG_MAGIC_1 or contents:sub(1, 12) == JPG_MAGIC_2 then
		local got_soi, got_sos = false, false

		-- read segments until we find a SOF0 header (containing width/height)
		while len_remaining > 0 do
			local segment = ffi.cast(jpg_segment_t, buffer)
			local typ = ffi.string(segment.type, 2)

			buffer = buffer + 2
			len_remaining = len_remaining - 2

			if typ == JPG_SEGMENT_SOI then
				got_soi = true
			elseif not got_soi then
				error("expected SOI segment", 2)
			elseif typ == JPG_SEGMENT_SOS or typ == JPG_SEGMENT_EOI then
				if typ == JPG_SEGMENT_SOS then
					got_sos = true
				end
				break
			else
				-- endian convert of the size (be -> le)
				local size = bswap_16(segment.size)

				if typ == JPG_SEGMENT_SOF0 then
					local sof0 = cast(jpg_segment_sof0_t, buffer)

					height = bswap_16(sof0.height)
					width = bswap_16(sof0.width)

					if width <= 0 or height <= 0 then
						error("Invalid width or height")
						return
					end
				end

				buffer = buffer + size
				len_remaining = len_remaining - size
			end
		end

		if not got_soi then
			error("Incomplete image, missing SOI segment", 2)
			return
		elseif not got_sos then
			error("Incomplete image, missing SOS segment", 2)
			return
		elseif width == nil then
			error("Incomplete image, missing SOF0 segment", 2)
			return
		end
	else
		error("Invalid magic", 2)
		return
	end

	return setmetatable(
		{
			type = "jpg",
			width = width,
			height = height,
			contents = contents,
			textures = {}
		},
		image_mt
	)
end

local function load_svg(contents)
	-- try and find <svg> tag

	local match = contents:match("<svg(.*)>.*</svg>")
	if match == nil then
		error("Invalid svg, missing <svg> tag", 2)
		return
	end

	match = match:gsub("\r\n", ""):gsub("\n", "")

	-- parse tag contents
	local in_quote = false
	local key, value = "", ""

	local attributes = {}

	local offset = 1
	while true do
		local chr = match:sub(offset, offset)

		if chr == "" then
			break
		end

		if in_quote then
			-- text inside quotation marks
			if chr == '"' then
				in_quote = false
				attributes[key:gsub("\t", ""):lower()] = value
				key, value = "", ""
			else
				value = value .. chr
			end
		else
			-- normal text, not inside quotes
			if chr == ">" then
				break
			elseif chr == "=" then
				if match:sub(offset, offset + 1) == '="' then
					in_quote = true
					offset = offset + 1
				end
			elseif chr == " " then
				key = ""
			else
				key = key .. chr
			end
		end

		offset = offset + 1
	end

	-- heuristics to find valid image width and height
	local width, height

	if attributes["width"] ~= nil then
		width = tonumber((attributes["width"]:gsub("px$", ""):gsub("pt$", ""):gsub("mm$", "")))

		if width ~= nil and 0 >= width then
			width = nil
		end
	end

	if attributes["height"] ~= nil then
		height = tonumber((attributes["height"]:gsub("px$", ""):gsub("pt$", ""):gsub("mm$", "")))

		if height ~= nil and 0 >= height then
			height = nil
		end
	end

	if width == nil or height == nil and attributes["viewbox"] ~= nil then
		local x, y, w, h = attributes["viewbox"]:match("^%s*([%d.]*) ([%d.]*) ([%d.]*) ([%d.]*)%s*$")

		width, height = tonumber(width), tonumber(height)

		if width ~= nil and height ~= nil and (0 >= width or 0 >= height) then
			width, height = nil, nil
		end
	end

	local self =
		setmetatable(
		{
			type = "svg",
			contents = contents,
			textures = {}
		},
		image_mt
	)

	if width ~= nil and height ~= nil and width > 0 and height > 0 then
		self.width, self.height = width, height
	end

	return self
end

local function load_rgba(contents, width, height)
	if width == nil or height == nil or width <= 0 or height <= 0 then
		error("Invalid size: width and height are required and have to be greater than zero.")
		return
	end

	local size = width * height * 4
	if contents:len() ~= size then
		error("invalid buffer length, expected width*height*4", 2)
		return
	end

	-- load texture
	local texture = draw.CreateTexture(contents, width, height)
	if texture == nil then
		return
	end

	return setmetatable(
		{
			type = "rgba",
			width = width,
			height = height,
			contents = contents,
			textures = {[string.format("%f_%f", width, height)] = texture}
		},
		image_mt
	)
end

local function load_image(contents)
	if type(contents) == "table" then
		if getmetatable(contents) == image_mt then
			return error("trying to load an existing image")
		else
			local result = {}
			for key, value in pairs(contents) do
				result[key] = load_image(value)
			end
			return result
		end
	else
		-- try and determine type etc by looking for magic value
		if type(contents) == "string" then
			if contents:sub(1, 8) == PNG_MAGIC then
				return load_png(contents)
			elseif contents:sub(1, 4) == JPG_MAGIC_1 or contents:sub(1, 12) == JPG_MAGIC_2 then
				return load_jpg(contents)
			elseif contents:match("^%s*%<%?xml") ~= nil then
				return load_svg(contents)
			else
				return error("Failed to determine image type")
			end
		end
	end
end

local panorama_images = setmetatable({}, {__mode = "k"})
local function get_panorama_image(path)
	if panorama_images[path] == nil then
		local path_cleaned = string_gsub(string_gsub(string_gsub(string_gsub(string_gsub(path, "%z", ""), "%c", ""), "\\", "/"), "%.%./", ""), "^/+", "")
		local contents = engine_read_file("materials/panorama/images/" .. path_cleaned)

		if contents then
			local image = load_image(contents)

			panorama_images[path] = image
		else
			panorama_images[path] = false
		end
	end

	if panorama_images[path] then
		return panorama_images[path]
	end
end

local weapon_icons = setmetatable({}, {__mode = "k"})
local function get_weapon_icon(weapon_name)
	if weapon_icons[weapon_name] == nil then
		local weapon_name_cleaned
		local typ = type(weapon_name)

		if typ == "table" and weapon_name.console_name ~= nil then
			weapon_name_cleaned = weapon_name.console_name
		elseif typ == "number" then
			local weapon = csgo_weapons[weapon_name]
			if weapon == nil then
				weapon_icons[weapon_name] = false
				return
			end
			weapon_name_cleaned = weapon.console_name
		elseif typ == "string" then
			weapon_name_cleaned = tostring(weapon_name)
		elseif weapon_name ~= nil then
			weapon_icons[weapon_name] = nil
			return
		else
			return
		end

		weapon_name_cleaned = string_gsub(string_gsub(weapon_name_cleaned, "^weapon_", ""), "^item_", "")

		local image = get_panorama_image("icons/equipment/" .. weapon_name_cleaned .. ".svg")
		weapon_icons[weapon_name] = image or false
	end

	if weapon_icons[weapon_name] then
		return weapon_icons[weapon_name]
	end
end

local steam_avatars = {}
local function get_steam_avatar(steamid3_or_steamid64, size)
	local cache_key = string.format("%s_%d", steamid3_or_steamid64, size or 32)

	if steam_avatars[cache_key] == nil then
		local func
		if size == nil then
			func = native_ISteamFriends_GetSmallFriendAvatar
		elseif size > 64 then
			func = native_ISteamFriends_GetLargeFriendAvatar
		elseif size > 32 then
			func = native_ISteamFriends_GetMediumFriendAvatar
		else
			func = native_ISteamFriends_GetSmallFriendAvatar
		end

		local steamid
		if type(steamid3_or_steamid64) == "string" then
			steamid = 76500000000000000ULL + tonumber(steamid3_or_steamid64:sub(4, -1))
		elseif type(steamid3_or_steamid64) == "number" then
			steamid = 76561197960265728ULL + steamid3_or_steamid64
		else
			return
		end

		local handle = func(native_ISteamFriends, steamid)

		if handle > 0 then
			local width = uintbuffer(1)
			local height = uintbuffer(1)
			if native_ISteamUtils_GetImageSize(native_ISteamUtils, handle, width, height) then
				if width[0] > 0 and height[0] > 0 then
					local rgba_buffer_size = width[0] * height[0] * 4
					local rgba_buffer = charbuffer(rgba_buffer_size)

					if native_ISteamUtils_GetImageRGBA(native_ISteamUtils, handle, rgba_buffer, rgba_buffer_size) then
						steam_avatars[cache_key] = load_rgba(ffi.string(rgba_buffer, rgba_buffer_size), width[0], height[0])
					end
				end
			end
		elseif handle ~= -1 then
			steam_avatars[cache_key] = false
		end
	end

	if steam_avatars[cache_key] then
		return steam_avatars[cache_key]
	end
end

return {
	load = load_image,
	load_png = load_png,
	load_jpg = load_jpg,
	load_svg = load_svg,
	load_rgba = load_rgba,
	get_weapon_icon = get_weapon_icon,
	get_panorama_image = get_panorama_image,
	get_steam_avatar = get_steam_avatar
} ```
				


        
       
                                    = math.floor local cast = ffi.cast -- -- ffi structs -- (mostly for image parsing) -- local png_ihdr_t = ffi.typeof( [[ struct { char type[4]; uint32_t width; uint32_t height; char bitDepth; char colorType; char compression;
                                    char filter; char interlace; } * ]] ) local jpg_segment_t = ffi.typeof([[ struct { char type[2]; uint16_t size; } * ]]) local jpg_segment_sof0_t = ffi.typeof([[ struct { uint16_t size; char precision; uint16_t height;
                                    uint16_t width; } __attribute__((packed)) * ]]) local uint16_t_ptr = ffi.typeof("uint16_t*") local charbuffer = ffi.typeof("char[?]") local uintbuffer = ffi.typeof("unsigned int[?]") --
                                    -- constants -- local INVALID_TEXTURE = -1 local PNG_MAGIC = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A" local JPG_MAGIC_1 = "\xFF\xD8\xFF\xDB" local JPG_MAGIC_2 = "\xFF\xD8\xFF\xE0\x00\x10\x4A\x46\x49\x46\x00\x01"
                                    local JPG_SEGMENT_SOI = "\xFF\xD8" local JPG_SEGMENT_SOF0 = "\xFF\xC0" local JPG_SEGMENT_SOS = "\xFF\xDA" local JPG_SEGMENT_EOI = "\xFF\xD9" local RENDERER_LOAD_FUNCS = { png
                                    = function(contents, width, height) local rgba, _width, _height = common.DecodePNG(contents) return draw.CreateTexture(rgba, _width, _height) end, svg = function(contents, width, height) local rgba, _width, _height
                                    = common.RasterizeSVG(contents) return draw.CreateTexture(rgba, _width, _height) end, jpg = function(contents, width, height) local rgba, _width, _height = common.DecodeJPEG(contents) return draw.CreateTexture(rgba,
                                    _width, _height) end, rgba = draw.CreateTexture } -- -- utility functions -- local function bswap_16(x) return bit.rshift(bit.bswap(x), 16) end local function hexdump(str) local out = {} str:gsub( ".", function(chr)
                                    table.insert(out, string.format("%02x", string.byte(chr))) end ) return table.concat(out, " ") end -- -- small filesystem implementation -- local native_ReadFile = vtable.bind("filesystem_stdio.dll",
                                    "VBaseFileSystem011", 0, "int(__thiscall*)(void*, void*, int, void*)") local native_OpenFile = vtable.bind("filesystem_stdio.dll", "VBaseFileSystem011", 2, "void*(__thiscall*)(void*,
                                    const char*, const char*, const char*)") local native_CloseFile = vtable.bind("filesystem_stdio.dll", "VBaseFileSystem011", 3, "void(__thiscall*)(void*, void*)") local native_GetFileSize
                                    = vtable.bind("filesystem_stdio.dll", "VBaseFileSystem011", 7, "unsigned int(__thiscall*)(void*, void*)") local function engine_read_file(filename) local handle = native_OpenFile(filename,
                                    "r", "MOD") if handle == nil then return end local filesize = native_GetFileSize(handle) if filesize == nil or filesize < 0 then return end local buffer = charbuffer(filesize + 1) if buffer ==
                                    nil then return end local read_success = native_ReadFile(buffer, filesize, handle) if not read_success then return end return ffi.string(buffer, filesize) end -- -- ISteamFriends / ISteamUtils -- -- That shit now use
                                    ingame context of steamapi instead of connecting to global user -- enjoy, by w7rus ffi.cdef( [[ typedef struct { void* steam_client; void* steam_user; void* steam_friends; void* steam_utils; void* steam_matchmaking;
                                    void* steam_user_stats; void* steam_apps; void* steam_matchmakingservers; void* steam_networking; void* steam_remotestorage; void* steam_screenshots; void* steam_http; void* steam_unidentifiedmessages; void* steam_controller;
                                    void* steam_ugc; void* steam_applist; void* steam_music; void* steam_musicremote; void* steam_htmlsurface; void* steam_inventory; void* steam_video; } S_steamApiCtx_t; ]] ) local pS_SteamApiCtx = ffi.cast("S_steamApiCtx_t**",
                                    ffi.cast("char*", mem.FindPattern("client.dll", "FF 15 ?? ?? ?? ?? B9 ?? ?? ?? ?? E8 ?? ?? ?? ?? 6A")) + 7)[0] or error("invalid interface", 2) local native_ISteamFriends = ffi.cast("void***",
                                    pS_SteamApiCtx.steam_friends) local native_ISteamUtils = ffi.cast("void***", pS_SteamApiCtx.steam_utils) local native_ISteamFriends_GetSmallFriendAvatar = vtable.thunk(34, "int(__thiscall*)(void*, uint64_t)")
                                    local native_ISteamFriends_GetMediumFriendAvatar = vtable.thunk(35, "int(__thiscall*)(void*, uint64_t)") local native_ISteamFriends_GetLargeFriendAvatar = vtable.thunk(36, "int(__thiscall*)(void*, uint64_t)")
                                    local native_ISteamUtils_GetImageSize = vtable.thunk(5, "bool(__thiscall*)(void*, int, uint32_t*, uint32_t*)") local native_ISteamUtils_GetImageRGBA = vtable.thunk(6, "bool(__thiscall*)(void*, int, unsigned
                                    char*, int)") -- -- image object implementation -- local function image_measure(self, width, height) if width ~= nil and height ~= nil then return math_floor(width), math_floor(height) else if self.width == nil
                                    or self.height == nil then error("Image dimensions not known, full size is required") elseif width == nil then height = height or self.height local width = math_floor(self.width * (height / self.height)) return
                                    width, height elseif height == nil then width = width or self.width local height = math_floor(self.height * (width / self.width)) return width, height else return math_floor(self.width), math_floor(self.height) end
                                    end end local function image_draw(self, x, y, width, height, r, g, b, a, force_same_res_render) width, height = image_measure(self, width, height) local id = string.format("%f_%f", width, height) local texture
                                    = self.textures[id] -- no texture with same width and height has been loaded if texture == nil then if ({next(self.textures)})[2] == nil or force_same_res_render or force_same_res_render == nil then -- try and load
                                    the texture local func = RENDERER_LOAD_FUNCS[self.type] if func then if self.type == "rgba" then width, height = self.width, self.height end texture = func(self.contents, width, height) end if texture == nil
                                    then self.textures[id] = INVALID_TEXTURE error("failed to load texture for " .. width .. "x" .. height, 2) else -- client.log("loaded svg ", self.name, " for ", width, "x",
                                    height) self.textures[id] = texture end else --right now we just choose a random texture (determined by the pairs order aka unordered) --todo: select the texture with the highest or closest resolution? texture = ({next(self.textures)})[2]
                                    end end if texture == nil or texture == INVALID_TEXTURE then return elseif a == nil or a > 0 then draw.SetTexture(texture) draw.Color(r or 255, g or 255, b or 255, a or 255) draw.FilledRect(x, y, x + width, y + height)
                                    draw.SetTexture(nil) end return width, height end local image_mt = { __index = { measure = image_measure, draw = image_draw } } -- -- functions for loading images -- local function load_png(contents) if contents:sub(1,
                                    8) ~= PNG_MAGIC then error("Invalid magic", 2) return end local ihdr_raw = contents:sub(13, 30) if ihdr_raw:len() < 17 then error("Incomplete data", 2) return end local ihdr = cast(png_ihdr_t,
                                    cast("const uint8_t *", cast("const char*", ihdr_raw))) if ffi.string(ihdr.type, 4) ~= "IHDR" then error("Invalid chunk type, expected IHDR", 2) return end local width = bit.bswap(ihdr.width)
                                    local height = bit.bswap(ihdr.height) if width <= 0 or height <= 0 then error("Invalid width or height", 2) return end return setmetatable( { type = "png", width = width, height = height, contents
                                    = contents, textures = {} }, image_mt ) end local function load_jpg(contents) local buffer = ffi.cast("const uint8_t *", ffi.cast("const char *", contents)) local len_remaining = contents:len() local
                                    width, height if contents:sub(1, 4) == JPG_MAGIC_1 or contents:sub(1, 12) == JPG_MAGIC_2 then local got_soi, got_sos = false, false -- read segments until we find a SOF0 header (containing width/height) while len_remaining
                                    > 0 do local segment = ffi.cast(jpg_segment_t, buffer) local typ = ffi.string(segment.type, 2) buffer = buffer + 2 len_remaining = len_remaining - 2 if typ == JPG_SEGMENT_SOI then got_soi = true elseif not got_soi
                                    then error("expected SOI segment", 2) elseif typ == JPG_SEGMENT_SOS or typ == JPG_SEGMENT_EOI then if typ == JPG_SEGMENT_SOS then got_sos = true end break else -- endian convert of the size (be -> le) local
                                    size = bswap_16(segment.size) if typ == JPG_SEGMENT_SOF0 then local sof0 = cast(jpg_segment_sof0_t, buffer) height = bswap_16(sof0.height) width = bswap_16(sof0.width) if width <= 0 or height <= 0 then error("Invalid
                                    width or height") return end end buffer = buffer + size len_remaining = len_remaining - size end end if not got_soi then error("Incomplete image, missing SOI segment", 2) return elseif not got_sos then
                                    error("Incomplete image, missing SOS segment", 2) return elseif width == nil then error("Incomplete image, missing SOF0 segment", 2) return end else error("Invalid magic", 2) return end
                                    return setmetatable( { type = "jpg", width = width, height = height, contents = contents, textures = {} }, image_mt ) end local function load_svg(contents) -- try and find <svg> tag local match = contents:match("<svg(.*)>.*</svg>")
                                    if match == nil then error("Invalid svg, missing <svg> tag", 2) return end match = match:gsub("\r\n", ""):gsub("\n", "") -- parse tag contents local in_quote =
                                    false local key, value = "", "" local attributes = {} local offset = 1 while true do local chr = match:sub(offset, offset) if chr == "" then break end if in_quote then -- text inside quotation
                                    marks if chr == '"' then in_quote = false attributes[key:gsub("\t", ""):lower()] = value key, value = "", "" else value = value .. chr end else -- normal text,
                                    not inside quotes if chr == ">" then break elseif chr == "=" then if match:sub(offset, offset + 1) == '="' then in_quote = true offset = offset + 1 end elseif chr == " "
                                    then key = "" else key = key .. chr end end offset = offset + 1 end -- heuristics to find valid image width and height local width, height if attributes["width"] ~= nil then width = tonumber((attributes["width"]:gsub("px$",
                                    ""):gsub("pt$", ""):gsub("mm$", ""))) if width ~= nil and 0 >= width then width = nil end end if attributes["height"] ~= nil then height = tonumber((attributes["height"]:gsub("px$",
                                    ""):gsub("pt$", ""):gsub("mm$", ""))) if height ~= nil and 0 >= height then height = nil end end if width == nil or height == nil and attributes["viewbox"]
                                    ~= nil then local x, y, w, h = attributes["viewbox"]:match("^%s*([%d.]*) ([%d.]*) ([%d.]*) ([%d.]*)%s*$") width, height = tonumber(width), tonumber(height) if width ~= nil and height ~= nil and (0
                                    >= width or 0 >= height) then width, height = nil, nil end end local self = setmetatable( { type = "svg", contents = contents, textures = {} }, image_mt ) if width ~= nil and height ~= nil and width
                                    > 0 and height > 0 then self.width, self.height = width, height end return self end local function load_rgba(contents, width, height) if width == nil or height == nil or width <= 0 or height <= 0 then error("Invalid
                                    size: width and height are required and have to be greater than zero.") return end local size = width * height * 4 if contents:len() ~= size then error("invalid buffer length, expected width*height*4",
                                    2) return end -- load texture local texture = draw.CreateTexture(contents, width, height) if texture == nil then return end return setmetatable( { type = "rgba", width = width, height = height, contents =
                                    contents, textures = {[string.format("%f_%f", width, height)] = texture} }, image_mt ) end local function load_image(contents) if type(contents) == "table" then if getmetatable(contents) == image_mt
                                    then return error("trying to load an existing image") else local result = {} for key, value in pairs(contents) do result[key] = load_image(value) end return result end else -- try and determine type etc by
                                    looking for magic value if type(contents) == "string" then if contents:sub(1, 8) == PNG_MAGIC then return load_png(contents) elseif contents:sub(1, 4) == JPG_MAGIC_1 or contents:sub(1, 12) == JPG_MAGIC_2 then
                                    return load_jpg(contents) elseif contents:match("^%s*%<%?xml") ~= nil then return load_svg(contents) else return error("Failed to determine image type") end end end end local panorama_images =
                                    setmetatable({}, {__mode = "k"}) local function get_panorama_image(path) if panorama_images[path] == nil then local path_cleaned = string_gsub(string_gsub(string_gsub(string_gsub(string_gsub(path, "%z",
                                    ""), "%c", ""), "\\", "/"), "%.%./", ""), "^/+", "") local contents = engine_read_file("materials/panorama/images/"
                                    .. path_cleaned) if contents then local image = load_image(contents) panorama_images[path] = image else panorama_images[path] = false end end if panorama_images[path] then return panorama_images[path] end end local
                                    weapon_icons = setmetatable({}, {__mode = "k"}) local function get_weapon_icon(weapon_name) if weapon_icons[weapon_name] == nil then local weapon_name_cleaned local typ = type(weapon_name) if typ == "table"
                                    and weapon_name.console_name ~= nil then weapon_name_cleaned = weapon_name.console_name elseif typ == "number" then local weapon = csgo_weapons[weapon_name] if weapon == nil then weapon_icons[weapon_name]
                                    = false return end weapon_name_cleaned = weapon.console_name elseif typ == "string" then weapon_name_cleaned = tostring(weapon_name) elseif weapon_name ~= nil then weapon_icons[weapon_name] = nil return else
                                    return end weapon_name_cleaned = string_gsub(string_gsub(weapon_name_cleaned, "^weapon_", ""), "^item_", "") local image = get_panorama_image("icons/equipment/" .. weapon_name_cleaned
                                    .. ".svg") weapon_icons[weapon_name] = image or false end if weapon_icons[weapon_name] then return weapon_icons[weapon_name] end end local steam_avatars = {} local function get_steam_avatar(steamid3_or_steamid64,
                                    size) local cache_key = string.format("%s_%d", steamid3_or_steamid64, size or 32) if steam_avatars[cache_key] == nil then local func if size == nil then func = native_ISteamFriends_GetSmallFriendAvatar elseif
                                    size > 64 then func = native_ISteamFriends_GetLargeFriendAvatar elseif size > 32 then func = native_ISteamFriends_GetMediumFriendAvatar else func = native_ISteamFriends_GetSmallFriendAvatar end local steamid if
                                    type(steamid3_or_steamid64) == "string" then steamid = 76500000000000000ULL + tonumber(steamid3_or_steamid64:sub(4, -1)) elseif type(steamid3_or_steamid64) == "number" then steamid = 76561197960265728ULL
                                    + steamid3_or_steamid64 else return end local handle = func(native_ISteamFriends, steamid) if handle > 0 then local width = uintbuffer(1) local height = uintbuffer(1) if native_ISteamUtils_GetImageSize(native_ISteamUtils,
                                    handle, width, height) then if width[0] > 0 and height[0] > 0 then local rgba_buffer_size = width[0] * height[0] * 4 local rgba_buffer = charbuffer(rgba_buffer_size) if native_ISteamUtils_GetImageRGBA(native_ISteamUtils,
                                    handle, rgba_buffer, rgba_buffer_size) then steam_avatars[cache_key] = load_rgba(ffi.string(rgba_buffer, rgba_buffer_size), width[0], height[0]) end end end elseif handle ~= -1 then steam_avatars[cache_key] = false
                                    end end if steam_avatars[cache_key] then return steam_avatars[cache_key] end end return { load = load_image, load_png = load_png, load_jpg = load_jpg, load_svg = load_svg, load_rgba = load_rgba, get_weapon_icon = get_weapon_icon,
                                    get_panorama_image = get_panorama_image, get_steam_avatar = get_steam_avatar } ```