-- Server Script: ServerShop

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

-- Require SkiraManager module to access Skira currency
local SkiraManager = require(game.ServerScriptService.SkiraManager)

-- Configuration
local SPAWN_POSITION = Vector3.new(-15, 19, -63)
local CURRENCY_NAME = "Skira"

-- Remote Events and Functions (related to purchasing)
local PurchaseItemEvent = ReplicatedStorage:FindFirstChild("PurchaseItem")
if not PurchaseItemEvent then
	PurchaseItemEvent = Instance.new("RemoteEvent")
	PurchaseItemEvent.Name = "PurchaseItem"
	PurchaseItemEvent.Parent = ReplicatedStorage
end

local PurchaseFeedbackEvent = ReplicatedStorage:FindFirstChild("PurchaseFeedback")
if not PurchaseFeedbackEvent then
	PurchaseFeedbackEvent = Instance.new("RemoteEvent")
	PurchaseFeedbackEvent.Name = "PurchaseFeedback"
	PurchaseFeedbackEvent.Parent = ReplicatedStorage
end

local GetShopItemsFunction = ReplicatedStorage:FindFirstChild("GetShopItems")
if not GetShopItemsFunction then
	GetShopItemsFunction = Instance.new("RemoteFunction")
	GetShopItemsFunction.Name = "GetShopItems"
	GetShopItemsFunction.Parent = ReplicatedStorage
end

local IsLimitedItemAvailableFunction = ReplicatedStorage:FindFirstChild("IsLimitedItemAvailable")
if not IsLimitedItemAvailableFunction then
	IsLimitedItemAvailableFunction = Instance.new("RemoteFunction")
	IsLimitedItemAvailableFunction.Name = "IsLimitedItemAvailable"
	IsLimitedItemAvailableFunction.Parent = ReplicatedStorage
end

local LimitedItemStatusChangedEvent = ReplicatedStorage:FindFirstChild("LimitedItemStatusChanged")
if not LimitedItemStatusChangedEvent then
	LimitedItemStatusChangedEvent = Instance.new("RemoteEvent")
	LimitedItemStatusChangedEvent.Name = "LimitedItemStatusChanged"
	LimitedItemStatusChangedEvent.Parent = ReplicatedStorage
end

-- Shop items configuration
local ShopItems = {
	{
		Name = "Blahaj",
		Description = "Best, softest, cutest, squishy toy!",
		Price = 35,
		Limited = false,
		New = false
	},
	{
		Name = "Antler",
		Description = "Stolen antler that an employee stole after hitting a person",
		Price = 75,
		Limited = false,
		New = false
	},
	{
		Name = "Dynamite",
		Description = "An explosive stick filled with explosive powder.",
		Price = 15,
		Limited = false,
		New = true
	},
	{
		Name = "ECO Bricks Package",
		Description = "Eco Bricks for your needs!",
		Price = 5,
		Limited = false,
		New = false
	},
	{
		Name = "Glaggle ball",
		Description = "If the earth is round, how come the ball ain't even going nowhere?",
		Price = 18,
		Limited = false,
		New = false
	},
	{
		Name = "Mannequin",
		Description = "Has feelings, do not hurt",
		Price = 18,
		Limited = false,
		New = false
	},
	{
		Name = "Maxwell",
		Description = "Found this random cat on the road, decided to name it Maxwell",
		Price = 18,
		Limited = true,
		New = false,
		Stock = 1 -- Initial stock for limited item
	},
}

-- Table to keep track of limited item stocks
local LimitedItemStocks = {}

-- Initialize limited item stocks
local function initializeLimitedItemStocks()
	for _, item in ipairs(ShopItems) do
		if item.Limited then
			LimitedItemStocks[item.Name] = item.Stock or 1
		end
	end
end

initializeLimitedItemStocks()

-- Function to check if a limited item is available
local function IsLimitedItemAvailable(player, itemName)
	local stock = LimitedItemStocks[itemName]
	if stock and stock > 0 then
		return true
	else
		return false
	end
end

-- Bind the RemoteFunction
IsLimitedItemAvailableFunction.OnServerInvoke = IsLimitedItemAvailable

-- Function to provide shop items to the client
local function GetShopItems(player)
	-- Return the ShopItems table
	return ShopItems
end

GetShopItemsFunction.OnServerInvoke = GetShopItems

-- Function to handle item purchases
local function HandlePurchase(player, itemName)
	if not player or not itemName then
		warn("[Shop System] Invalid purchase request")
		return
	end

	-- Validate the item
	local itemData = nil
	for _, item in ipairs(ShopItems) do
		if item.Name == itemName then
			itemData = item
			break
		end
	end

	if not itemData then
		warn(string.format("[Shop System] Item '%s' not found in shop data", itemName))
		PurchaseFeedbackEvent:FireClient(player, "Item not found.")
		return
	end

	-- Check if the player can afford the item
	local playerCurrency = SkiraManager:GetPlayerSkira(player)
	if playerCurrency < itemData.Price then
		PurchaseFeedbackEvent:FireClient(player, "You don't have enough " .. CURRENCY_NAME .. " to purchase " .. itemData.Name .. ".")
		return
	end

	-- Handle limited items
	if itemData.Limited then
		local available = IsLimitedItemAvailable(player, itemName)
		if not available then
			PurchaseFeedbackEvent:FireClient(player, "Sorry, " .. itemData.Name .. " is sold out.")
			return
		else
			-- Reduce the availability count
			LimitedItemStocks[itemName] = LimitedItemStocks[itemName] - 1

			-- Notify all clients about the change in availability
			LimitedItemStatusChangedEvent:FireAllClients(itemName, LimitedItemStocks[itemName] > 0)
		end
	end

	-- Deduct the cost from the player's currency
	SkiraManager:AddPlayerSkira(player, -itemData.Price)
	-- Update the client with the new Skira amount
	local SkiraUpdateEvent = ReplicatedStorage:WaitForChild("SkiraUpdateEvent")
	local newSkiraAmount = SkiraManager:GetPlayerSkira(player)
	SkiraUpdateEvent:FireClient(player, newSkiraAmount)

	-- Spawn the item
	local spawnableItems = ReplicatedStorage:FindFirstChild("Spawnable items")
	if not spawnableItems then
		warn("[Shop System] Spawnable items folder not found")
		PurchaseFeedbackEvent:FireClient(player, "An error occurred while processing your purchase.")
		return
	end

	local spawnableItem = spawnableItems:FindFirstChild(itemData.Name)
	if not spawnableItem then
		warn(string.format("[Shop System] Failed to find item '%s' for purchase!", itemData.Name))
		PurchaseFeedbackEvent:FireClient(player, "An error occurred while processing your purchase.")
		return
	end

	-- Ensure SpawnedItems folder exists
	local spawnedItemsFolder = workspace:FindFirstChild("SpawnedItems")
	if not spawnedItemsFolder then
		spawnedItemsFolder = Instance.new("Folder")
		spawnedItemsFolder.Name = "SpawnedItems"
		spawnedItemsFolder.Parent = workspace
	end

	-- Spawn the item
	local success, errorMsg = pcall(function()
		local newItem = spawnableItem:Clone()
		newItem.Parent = spawnedItemsFolder

		-- Set the position of the item
		if newItem:IsA("Model") then
			if newItem.PrimaryPart then
				newItem:SetPrimaryPartCFrame(CFrame.new(SPAWN_POSITION))
			else
				-- If no PrimaryPart, move all BaseParts
				local center = newItem:GetBoundingBox().Position
				for _, part in ipairs(newItem:GetDescendants()) do
					if part:IsA("BasePart") then
						part.Position = part.Position - center + SPAWN_POSITION
					end
				end
			end
		elseif newItem:IsA("BasePart") then
			newItem.Position = SPAWN_POSITION
		else
			warn(string.format("[Shop System] Unsupported item type for '%s'", itemData.Name))
			PurchaseFeedbackEvent:FireClient(player, "An error occurred while processing your purchase.")
			return
		end
	end)

	if not success then
		warn(string.format("[Shop System] Failed to spawn item '%s': %s", itemData.Name, tostring(errorMsg)))
		PurchaseFeedbackEvent:FireClient(player, "An error occurred while processing your purchase.")
	else
		print(string.format("[Shop System] Successfully spawned item '%s' for player '%s'", itemData.Name, player.Name))
		PurchaseFeedbackEvent:FireClient(player, "You have successfully purchased " .. itemData.Name .. "!")
	end
end

-- Connect the purchase event
PurchaseItemEvent.OnServerEvent:Connect(HandlePurchase)

-- Client Script: ShopHandler

-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")

-- Configuration
local CURRENCY_NAME = "Skira"
local CAMERA_ROTATION_SPEED = 0.1 -- Rotations per second

-- Remote Functions and Events
local PurchaseItemEvent = ReplicatedStorage:WaitForChild("PurchaseItem")
local IsLimitedItemAvailableFunction = ReplicatedStorage:WaitForChild("IsLimitedItemAvailable")
local LimitedItemStatusChangedEvent = ReplicatedStorage:WaitForChild("LimitedItemStatusChanged")
local GetPlayerCurrencyFunction = ReplicatedStorage:WaitForChild("GetPlayerCurrency")
local PurchaseFeedbackEvent = ReplicatedStorage:WaitForChild("PurchaseFeedback")
local GetShopItemsFunction = ReplicatedStorage:WaitForChild("GetShopItems")
local SkiraUpdateEvent = ReplicatedStorage:WaitForChild("SkiraUpdateEvent")

-- Variables
local ITEMS_FOLDER = ReplicatedStorage:WaitForChild("Spawnable items")
local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local displayGui = playerGui:WaitForChild("Display")
local TEMPLATE_ELEMENT = displayGui.Frame.SDS.Frame.List:WaitForChild("ItemUI")
local ELEMENTS_CONTAINER = displayGui.Frame.SDS.Frame.List

-- Required UI elements
local REQUIRED_UI_ELEMENTS = {
	"Name",
	"Description",
	"Optional",
	"Buy",
	"ItemDisplay"
}

-- Shop items table (will be populated from the server)
local ShopItems = {}

-- Current player currency
local playerCurrency = 0

-- Function to display warnings
local function WarnMessage(message)
	warn("[Shop System] " .. message)
end

-- Function to display messages to the player
local function DisplayMessage(message)
	-- Implement your own UI message system here
	-- For now, we'll just print the message
	print("[Shop Message] " .. message)
end

-- Function to validate UI elements in the template
local function ValidateUIElement(template)
	local missingElements = {}
	for _, element in ipairs(REQUIRED_UI_ELEMENTS) do
		if not template:FindFirstChild(element) then
			table.insert(missingElements, element)
		end
	end

	if #missingElements > 0 then
		WarnMessage(string.format("Missing required UI elements: %s", table.concat(missingElements, ", ")))
		return false
	end

	return true
end

-- Function to validate shop item data
local function ValidateShopItem(itemData)
	if type(itemData) ~= "table" then
		WarnMessage("Invalid item data format")
		return false
	end
	local requiredFields = {"Name", "Description", "Price"}
	for _, field in ipairs(requiredFields) do
		if itemData[field] == nil then
			WarnMessage(string.format("Missing required field '%s' in item data", field))
			return false
		end
	end
	return true
end

-- Updated CleanModel function to fulfill your requests
local function CleanModel(model)
	for _, instance in ipairs(model:GetDescendants()) do
		-- Remove Scripts and LocalScripts
		if instance:IsA("Script") or instance:IsA("LocalScript") then
			instance:Destroy()
			-- Remove Sounds
		elseif instance:IsA("Sound") then
			instance:Destroy()
			-- Remove ProximityPrompts
		elseif instance:IsA("ProximityPrompt") then
			instance:Destroy()
			-- Remove any instances not suitable for ViewportFrames
		elseif not (instance:IsA("BasePart") or instance:IsA("Model") or instance:IsA("Folder") or instance:IsA("Attachment") or instance:IsA("Weld") or instance:IsA("WeldConstraint") or instance:IsA("Motor6D") or instance:IsA("MeshPart") or instance:IsA("SpecialMesh") or instance:IsA("UnionOperation")) then
			instance:Destroy()
			-- Delete items named "box" or "Cover"
		elseif instance.Name == "box" or instance.Name == "Cover" then
			instance:Destroy()
			-- For BaseParts, make sure Transparency is 0 and set other properties
		elseif instance:IsA("BasePart") then
			instance.Transparency = 0
			instance.Anchored = true
			instance.CanCollide = false
		end
	end
end

-- Function to set up the item in the viewport
local function SetupItemInViewport(itemDisplay, itemModel)
	-- Remove existing ViewportFrame
	local existingViewport = itemDisplay:FindFirstChild("ViewportFrame")
	if existingViewport then
		existingViewport:Destroy()
	end

	local viewportFrame = Instance.new("ViewportFrame")
	viewportFrame.Name = "ViewportFrame"
	viewportFrame.Size = UDim2.new(1, 0, 1, 0)
	viewportFrame.BackgroundTransparency = 1
	viewportFrame.BorderSizePixel = 0
	viewportFrame.Parent = itemDisplay

	local camera = Instance.new("Camera")
	viewportFrame.CurrentCamera = camera
	camera.Parent = viewportFrame

	local modelClone = itemModel:Clone()
	CleanModel(modelClone)
	modelClone.Parent = viewportFrame

	-- Calculate model size and center
	local modelCFrame, modelSize = modelClone:GetBoundingBox()
	local center = modelCFrame.Position
	local maxSize = math.max(modelSize.X, modelSize.Y, modelSize.Z)
	local distance = maxSize * 1.5

	-- Set initial camera position
	camera.CFrame = CFrame.new(center + Vector3.new(0, maxSize / 2, distance), center)

	-- Rotation animation
	local rotationConnection
	rotationConnection = RunService.RenderStepped:Connect(function(deltaTime)
		if not camera.Parent then
			rotationConnection:Disconnect()
			return
		end

		local elapsedTime = tick()
		local angle = elapsedTime * math.pi * 2 * CAMERA_ROTATION_SPEED
		local offset = CFrame.Angles(0, angle, 0) * Vector3.new(0, 0, distance)
		camera.CFrame = CFrame.new(center + offset + Vector3.new(0, maxSize / 2, 0), center)
	end)
end

-- Function to get the player's currency
local function GetPlayerCurrency()
	if GetPlayerCurrencyFunction and GetPlayerCurrencyFunction:IsA("RemoteFunction") then
		local success, result = pcall(function()
			return GetPlayerCurrencyFunction:InvokeServer()
		end)
		if success then
			playerCurrency = result -- Update the local variable
			return result
		else
			WarnMessage("Failed to get player currency")
			return 0
		end
	else
		WarnMessage("GetPlayerCurrency RemoteFunction not found")
		return 0
	end
end

-- Function to check limited item availability
local function CheckLimitedItemAvailability(itemName)
	if IsLimitedItemAvailableFunction and IsLimitedItemAvailableFunction:IsA("RemoteFunction") then
		local success, result = pcall(function()
			return IsLimitedItemAvailableFunction:InvokeServer(itemName)
		end)
		if success then
			return result
		else
			WarnMessage("Failed to get availability for item: " .. itemName)
			return false
		end
	else
		WarnMessage("IsLimitedItemAvailableFunction RemoteFunction not found")
		return false
	end
end

-- Function to create a shop item UI element
local function CreateShopItem(template, itemData)
	if not template then
		WarnMessage("Shop item template is nil")
		return nil
	end

	if not ValidateShopItem(itemData) then
		WarnMessage(string.format("Invalid shop item data for item: %s", itemData.Name or "Unknown"))
		return nil
	end

	if not ValidateUIElement(template) then
		WarnMessage("Template validation failed")
		return nil
	end

	local newItem = template:Clone()
	newItem.Visible = true

	-- Set up item UI elements
	local itemDisplay = newItem:FindFirstChild("ItemDisplay")
	if itemDisplay then
		local itemModel = ITEMS_FOLDER:FindFirstChild(itemData.Name)
		if itemModel then
			SetupItemInViewport(itemDisplay, itemModel)
		else
			WarnMessage("Item model not found: " .. itemData.Name)
		end
	end

	local nameLabel = newItem:FindFirstChild("Name")
	local descriptionLabel = newItem:FindFirstChild("Description")
	local buyButton = newItem:FindFirstChild("Buy")
	local optionalLabel = newItem:FindFirstChild("Optional")

	if nameLabel then nameLabel.Text = itemData.Name end
	if descriptionLabel then descriptionLabel.Text = itemData.Description end
	if buyButton then buyButton.Text = tostring(itemData.Price) .. " " .. CURRENCY_NAME end

	if optionalLabel then
		if itemData.New then
			optionalLabel.Text = "New!"
			optionalLabel.Visible = true
		elseif itemData.Limited then
			optionalLabel.Text = "Limited"
			optionalLabel.BackgroundColor3 = Color3.fromRGB(176, 113, 37)
			optionalLabel.Visible = true
		else
			optionalLabel.Visible = false
		end
	end

	local originalBuyButtonColor
	if buyButton then
		originalBuyButtonColor = buyButton.BackgroundColor3

		local function updateBuyButton()
			local itemAvailable = true
			if itemData.Limited then
				itemAvailable = CheckLimitedItemAvailability(itemData.Name)
			end

			if itemAvailable then
				-- Item is available
				buyButton.Text = tostring(itemData.Price) .. " " .. CURRENCY_NAME
				buyButton.Active = true
				buyButton.AutoButtonColor = true
				buyButton.BackgroundColor3 = originalBuyButtonColor
			else
				-- Item is sold out
				buyButton.Text = "Out of Stock"
				buyButton.Active = false
				buyButton.AutoButtonColor = false
				buyButton.BackgroundColor3 = Color3.fromRGB(128, 128, 128)
			end
		end

		updateBuyButton()

		-- Listen for LimitedItemStatusChangedEvent if the item is limited
		if itemData.Limited then
			if LimitedItemStatusChangedEvent and LimitedItemStatusChangedEvent:IsA("RemoteEvent") then
				LimitedItemStatusChangedEvent.OnClientEvent:Connect(function(changedItemName, availability)
					if changedItemName == itemData.Name then
						updateBuyButton()
					end
				end)
			else
				WarnMessage("LimitedItemStatusChangedEvent not found or not a RemoteEvent")
			end
		end

		-- Set up buy button behavior
		buyButton.MouseButton1Click:Connect(function()
			playerCurrency = GetPlayerCurrency() -- Update the local currency variable

			if playerCurrency < itemData.Price then
				-- Display message to the player that they don't have enough money
				local insufficientFundsMessage = "You don't have enough " .. CURRENCY_NAME .. " to buy " .. itemData.Name .. "."
				DisplayMessage(insufficientFundsMessage)
				return
			end

			-- For limited items, check availability again before buying
			if itemData.Limited then
				local itemAvailable = CheckLimitedItemAvailability(itemData.Name)
				if not itemAvailable then
					-- Item is sold out
					DisplayMessage("This item is sold out.")
					updateBuyButton()
					return
				end
			end

			if PurchaseItemEvent and PurchaseItemEvent:IsA("RemoteEvent") then
				PurchaseItemEvent:FireServer(itemData.Name)
			else
				WarnMessage("PurchaseItemEvent not found or not a RemoteEvent")
			end
		end)
	end

	newItem.Parent = ELEMENTS_CONTAINER

	return newItem
end

-- Function to update the CanvasSize of the ScrollingFrame
local function UpdateCanvasSize()
	local layout = ELEMENTS_CONTAINER:FindFirstChildWhichIsA("UIGridStyleLayout") or ELEMENTS_CONTAINER:FindFirstChildWhichIsA("UIListLayout")
	if layout then
		local contentSize = layout.AbsoluteContentSize
		ELEMENTS_CONTAINER.CanvasSize = UDim2.new(0, contentSize.X, 0, contentSize.Y)
	else
		WarnMessage("Layout not found in ELEMENTS_CONTAINER")
	end
end

-- Function to clear existing shop items
local function ClearShopItems()
	for _, child in ipairs(ELEMENTS_CONTAINER:GetChildren()) do
		if child:IsA("Frame") and child ~= TEMPLATE_ELEMENT then
			child:Destroy()
		end
	end
end

local function InitializeShop()
	print("Initializing shop...")

	ClearShopItems()

	local template = TEMPLATE_ELEMENT
	if not template then
		error("Shop template not found")
	end

	template.Visible = false

	-- Ensure a layout exists
	local layout = ELEMENTS_CONTAINER:FindFirstChildWhichIsA("UIGridStyleLayout") or ELEMENTS_CONTAINER:FindFirstChildWhichIsA("UIListLayout")
	if not layout then
		layout = Instance.new("UIListLayout")
		layout.FillDirection = Enum.FillDirection.Vertical
		layout.SortOrder = Enum.SortOrder.LayoutOrder
		layout.Padding = UDim.new(0, 5)
		layout.Parent = ELEMENTS_CONTAINER
	end

	-- Connect to changes in AbsoluteContentSize to update CanvasSize
	layout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(UpdateCanvasSize)

	-- Request shop items from the server
	if GetShopItemsFunction and GetShopItemsFunction:IsA("RemoteFunction") then
		local success, result = pcall(function()
			return GetShopItemsFunction:InvokeServer()
		end)
		if success and type(result) == "table" then
			ShopItems = result
		else
			WarnMessage("Failed to get shop items from server")
			return
		end
	else
		WarnMessage("GetShopItemsFunction not found")
		return
	end

	-- Sort items: New items first, then Limited, then others
	table.sort(ShopItems, function(a, b)
		if a.New ~= b.New then
			return a.New
		elseif a.Limited ~= b.Limited then
			return a.Limited
		else
			return a.Name < b.Name
		end
	end)

	-- Populate the shop items
	for _, itemData in ipairs(ShopItems) do
		local item = CreateShopItem(template, itemData)
		if not item then
			WarnMessage(string.format("Failed to create shop item: %s", itemData.Name or "Unknown"))
		end
	end

	print("Shop initialized successfully")
	UpdateCanvasSize()
end

-- Handle purchase feedback messages from the server
if PurchaseFeedbackEvent and PurchaseFeedbackEvent:IsA("RemoteEvent") then
	PurchaseFeedbackEvent.OnClientEvent:Connect(function(message)
		DisplayMessage(message)
		-- Update the player's currency display if you have one
		playerCurrency = GetPlayerCurrency()
	end)
else
	WarnMessage("PurchaseFeedbackEvent not found or not a RemoteEvent")
end

-- Handle Skira currency updates from the server
if SkiraUpdateEvent and SkiraUpdateEvent:IsA("RemoteEvent") then
	SkiraUpdateEvent.OnClientEvent:Connect(function(newSkiraAmount)
		playerCurrency = newSkiraAmount
		-- Update any currency display UI here
	end)
else
	WarnMessage("SkiraUpdateEvent not found or not a RemoteEvent")
end

-- Initialize the shop when the GUI is ready
local function OnDisplayGuiLoaded()
	InitializeShop()
end

if displayGui then
	OnDisplayGuiLoaded()
else
	playerGui.ChildAdded:Connect(function(child)
		if child.Name == "Display" then
			displayGui = child
			OnDisplayGuiLoaded()
		end
	end)
end

-- Also handle the case where the character is already loaded when the script runs
if player.Character then
	player.CharacterAdded:Connect(function()
		-- Reinitialize shop if needed when character respawns
		InitializeShop()
	end)
end

-- Fetch initial player currency
playerCurrency = GetPlayerCurrency()

Can you make it so that the canvas is 200% of the size, secondly make it so that the objects spins in the viewmodel, thirdly fix this annoying issue where when i die, a bunch of errors happens and the shop becomes empty only leaving the template, it only happens when the player dies, not when spawning for the  first time

  16:19:24.091  [Shop System] Missing required UI elements: Name, Description, Optional, Buy, ItemDisplay  -  Client - ShopHandler:47
  16:19:24.091  [Shop System] Template validation failed  -  Client - ShopHandler:47
  16:19:24.091  [Shop System] Failed to create shop item: Dynamite  -  Client - ShopHandler:47
  16:19:24.091  [Shop System] Missing required UI elements: Name, Description, Optional, Buy, ItemDisplay  -  Client - ShopHandler:47
  16:19:24.091  [Shop System] Template validation failed  -  Client - ShopHandler:47
  16:19:24.091  [Shop System] Failed to create shop item: Maxwell  -  Client - ShopHandler:47
  16:19:24.092  [Shop System] Missing required UI elements: Name, Description, Optional, Buy, ItemDisplay  -  Client - ShopHandler:47
  16:19:24.092  [Shop System] Template validation failed  -  Client - ShopHandler:47
  16:19:24.092  [Shop System] Failed to create shop item: Antler  -  Client - ShopHandler:47
  16:19:24.092  [Shop System] Missing required UI elements: Name, Description, Optional, Buy, ItemDisplay  -  Client - ShopHandler:47
  16:19:24.092  [Shop System] Template validation failed  -  Client - ShopHandler:47
  16:19:24.092  [Shop System] Failed to create shop item: Blahaj  -  Client - ShopHandler:47
  16:19:24.092  [Shop System] Missing required UI elements: Name, Description, Optional, Buy, ItemDisplay  -  Client - ShopHandler:47
  16:19:24.093  [Shop System] Template validation failed  -  Client - ShopHandler:47
  16:19:24.093  [Shop System] Failed to create shop item: ECO Bricks Package  -  Client - ShopHandler:47
  16:19:24.093  [Shop System] Missing required UI elements: Name, Description, Optional, Buy, ItemDisplay  -  Client - ShopHandler:47
  16:19:24.093  [Shop System] Template validation failed  -  Client - ShopHandler:47
  16:19:24.093  [Shop System] Failed to create shop item: Glaggle ball  -  Client - ShopHandler:47
  16:19:24.093  [Shop System] Missing required UI elements: Name, Description, Optional, Buy, ItemDisplay  -  Client - ShopHandler:47
  16:19:24.093  [Shop System] Template validation failed  -  Client - ShopHandler:47
  16:19:24.093  [Shop System] Failed to create shop item: Mannequin  -  Client - ShopHandler:47