beeshops.sk

Created by AsuDev

Just so you know, we don't know the file format for every file. If it's just a bunch of random characters, it's probably a .zip or .jar.


# ###############################################################################

# BeeShops

# Create your own shops efficiently using skript code
# Currently supports: buying/selling, pages, infinite custom shops, custom items

# Possible future additions: more buy & sell click types (shift click etc)

# Credit: MaybeAsu

# ###############################################################################

# FUNCTIONS

# Open a shop to a player
function openShop(p: player, name: string):
	open {-shops::%{_name}%} to {_p}

# Creates a shop item that redirects the player to another shop
function redirectShopItem(item: item, name: string, hideflags: int = 0) :: item:
	set {_nc} to nbt compound of {_item}
	set tag "redirect" of {_nc} to {_name}
	if name of {_item} is not set:
		set name of {_item} to {_name}
	if {_hideflags} is not 0:
		set tag "HideFlags" of {_nc} to {_hideflags}
	return {_item}

# Creates a shop item that closes the players inventory
function closeShopItem(item: item, hideflags: int = 0) :: item:
	set {_nc} to nbt compound of {_item}
	set tag "close" of {_nc} to true
	if {_hideflags} is not 0:
		set tag "HideFlags" of {_nc} to {_hideflags}
	return {_item}

# Create a placeholder item
function placeholderShopItem(item: item, hideflags: int = 0) :: item:
	set {_nc} to nbt compound of {_item}
	set tag "placeholder" of {_nc} to true
	if {_hideflags} is not 0:
		set tag "HideFlags" of {_nc} to {_hideflags}
	return {_item}

# Format a number with commas (Useful for big numbers) -> 5000 = 5,000 / 5000.23 = 5,000.23
# BRING BACK REGEX
function numberFormat(n: number) :: string:
	set {_n} to "%{_n}%"
	if {_n} contains ".":
		set {_e::*} to split {_i} by "."
		set {_e::2} to ".%{_e::2}%"
		set {_n} to {_e::1}
	else:
		set {_e::2} to ""
	set {_r} to ""
	set {_l} to length of {_n}
	loop {_l} times:
		set {_r} to "%subtext of {_n} from {_l}-loop-value+1 to {_l}-loop-value+1%%{_r}%"
		if mod(loop-value, 3) = 0:
			if loop-value is not {_l}:
				set {_r} to ",%{_r}%"
	return "%{_r}%%{_e::2}%"

# Replace buy lore placeholder
function replaceBuyPlaceholder(item: item, amount: number, price: number) :: string:
	set {_t} to {-BuyDisplay}
	replace all "{buyprice}" with numberFormat({_price}) in {_t}
	replace all "{amount}" with "%{_amount}%" in {_t}
	return {_t}

# Replace sell lore placeholder
function replaceSellPlaceholder(item: item, amount: number, price: number) :: string:
	set {_t} to {-SellDisplay}
	replace all "{sellprice}" with numberFormat({_price}) in {_t}
	replace all "{amount}" with "%{_amount}%" in {_t}
	return {_t}

# NBT item in chat
function itemInChat(item: item, t: string) :: objects:
	set {_m::*} to split {_t} at "{item}"
	set {_t::1} to text component from {_m::1}
	if name of {_item} is set:
		set {_t::2} to text component from name of {_item}
	else:
		set {_t::2} to text component from translate component of type of {_item}
	set hover event of {_t::2} to hover event showing item {_item}
	set {_t::3} to {_m::2}
	return {_t::*}

# Shop messages for buying/selling items
function shopMessage(type: string, item: item, amount: number, price: number) :: objects:
	if {_type} is "sell":
		set {_t} to {-SellMessage}
		replace all "{sellprice}" with numberFormat({_price}) in {_t}
	else:
		set {_t} to {-BuyMessage}
		replace all "{buyprice}" with numberFormat({_price}) in {_t}
	replace all "{prefix}" with {-ShopPrefix} in {_t}
	replace all "{amount}" with "%{_amount}%" in {_t}
	if {_t} contains "{item}":
		set {_t::*} to itemInChat({_item}, {_t})
	else:
		set {_t::1} to text component from {_t}
	return {_t::*}	

# Format buy/sell info for lore of display shop item
function setShopDisplayLore(item: item, amount: number, buyable: boolean, sellable: boolean, buyprice: number, sellprice: number) :: item:
	if {_buyable} is true:
		if size of lore of {_item} is 0:
			set lore of {_item} to replaceBuyPlaceholder({_item}, {_amount}, {_buyprice})
		else:
			set lore of {_item} to lore of {_item}, "", replaceBuyPlaceholder({_item}, {_amount}, {_buyprice})
	if {_sellable} is true:
		if size of lore of {_item} is 0:
			set lore of {_item} to lore of {_item}, replaceSellPlaceholder({_item}, {_amount}, {_sellprice})
		else:
			set {_line} to line (size of lore of {_item}) of lore of {_item}
			if {_line} is not "":
				if {_buyable} is false:
					set lore of {_item} to lore of {_item}, ""
			set lore of {_item} to lore of {_item}, replaceSellPlaceholder({_item}, {_amount}, {_sellprice})
	return {_item}

# Create a shop item that you can buy/sell
function createShopItem(item: item, amount: number, buyable: boolean = true, buyprice: number, sellable: boolean = false, sellprice: number = {_buyprice}/2, hideflags: int = 0) :: item:
	set {_nc} to nbt compound of {_item}
	set compound tag "item" of {_nc} to full nbt compound of {_item}
	set byte tag "amount" of {_nc} to {_amount}
	set tag "buyable" of {_nc} to "%{_buyable}%"
	set tag "sellable" of {_nc} to "%{_sellable}%"
	set float tag "buyprice" of {_nc} to {_buyprice}
	set float tag "sellprice" of {_nc} to {_sellprice}
	if {_hideflags} is not 0:
		set tag "HideFlags" of {_nc} to {_hideflags}
	set {_item} to setShopDisplayLore({_item}, {_amount}, {_buyable}, {_sellable}, {_buyprice}, {_sellprice})
	set item amount of {_item} to {_amount}
	return {_item}

# Handle shop error messages
function shopErrorMessage(cause: string, p: player):
	if {_cause} is "money":
		set {_m} to {-NotEnoughMoneyMessage}
	else if {_cause} is "space":
		set {_m} to {-NotEnoughSpaceMessage}
	else if {_cause} is "items":
		set {_m} to {-NotEnoughItemsMessage}
	else if {_cause} is "perm" or "permission":
		set {_m} to {-NoPermission}
	else if {_cause} is "shop":
		set {_m} to {-ShopDoesNotExist}
	else:
		set {_m} to "{prefix} &cSomething went wrong..."
	replace all "{prefix}" with {-ShopPrefix} in {_m}
	send {_m} to {_p}

# Format shop list
function formatShopList(t: strings) :: objects:
	loop {_t::*}:
		set {_m::%loop-index%} to text component from "&7%loop-value%"
		set hover event of {_m::%loop-index%} to hover event showing "%{-ShopList}%%nl%&7Click to open shop &b%loop-value%"
		set click event of {_m::%loop-index%} to click event to run command "/osh %loop-value%"
	add text component from "%{-ShopList}% " to {_r::*}
	loop {_m::*}:
		add loop-value to {_r::*}
		if (size of {_m::*} != loop-index parsed as integer):
			add text component from ", " to {_r::*}
	return {_r::*}

# Buy items
function buyItem(p: player, item: item, amount: number, buyprice: number, buyable: string):
	if {_buyable} is "true":
		if {_p} has enough space for {_amount} of {_item}:
			if balance of {_p} >= {_buyprice}:
				remove {_buyprice} from balance of {_p}
				give ({_amount} of {_item}) to {_p}
				send components shopMessage("buy", {_item}, {_amount}, {_buyprice}) to {_p}
			else:
				shopErrorMessage("money", {_p})
		else:
			shopErrorMessage("space", {_p})

# Sell items
function sellItem(p: player, item: item, amount: number, sellprice: number, sellable: string):
	if {_sellable} is "true":
		set {_itemstack} to {_amount} of {_item}
		if (number of {_item} in {_p}'s inventory) >= item amount of {_itemstack}:
			remove ({_amount} of {_item}) from {_p}'s inventory
			add {_sellprice} to balance of {_p}
			send components shopMessage("sell", {_item}, {_amount}, {_sellprice}) to {_p}
		else:
			shopErrorMessage("items", {_p})

# Handles click requests for shop items
function handleShopItem(p: player, slot: slot, clicktype: click type):
	set {_nc} to nbt compound of {_slot}

	# Handle redirect items
	if {_nc} has tag "redirect":
		set {_redirect} to tag "redirect" of {_nc}
		openShop({_p}, {_redirect})

	# Handle close items
	if {_nc} has tag "close":
		close {_p}'s inventory

	# Handle buy/sell
	if {_nc} has tag "buyable":
		set {_amount} to tag "amount" of {_nc}
		set {_realitem} to compound tag "item" of {_nc}
		set {_item} to item from nbt {_realitem}
		if {_clicktype} is left mouse button:
			set {_buyable} to tag "buyable" of {_nc}
			set {_buyprice} to tag "buyprice" of {_nc}
			buyItem({_p}, {_item}, {_amount}, {_buyprice}, {_buyable})
		else if {_clicktype} is right mouse button:
			set {_sellable} to tag "sellable" of {_nc}
			set {_sellprice} to tag "sellprice" of {_nc}
			sellItem({_p}, {_item}, {_amount}, {_sellprice}, {_sellable})

# COMMANDS

# Main open shop command
command /openshop [<player=%player%>] [<text>]:
	aliases: openstore, oshop, ostore, osh
	trigger:
		if player has permission "shops.admin":
			if arg 2 is set:
				if {-shops::%arg 2%} is set:
					openShop(arg 1, arg 2)
				else:
					shopErrorMessage("shop", player)
			else:
				send "&7Correct usage: &c/openshop [<player>] <shop>"
		else:
			shopErrorMessage("perm", player)

# List of shops
command /shops:
	aliases: shop
	trigger:
		if size of {-shops::*} > 0:
			send components formatShopList(indexes of {-shops::*}) to player
		else:
			send "%{-ShopList}% &7No shops yet."

# EVENTS

# Main inventory click event
on inventory click:
	loop {-shops::*}:
		if event-inventory = loop-value:
			cancel event
			handleShopItem(player, clicked slot, click type)

# Complete tabs for shop commands
on tab complete of "/openshop", "/openstore", "/oshop", "ostore", "osh":
	set tab completions for position 1 to indexes of {-shops::*} and all players
	set tab completions for position 2 to indexes of {-shops::*}

# Create our shops and setup messages
on load:

	# Placeholders
	# {amount} - buy/sell amount
	# {buyprice} - buy price
	# {sellprice} - sell price
	# {item} - name of item
	# {prefix} - prefix for script
	set {-ShopPrefix} to "&7[&bShop&7]"
	set {-BuyDisplay} to "&b&l[BUY X{amount}] &a${buyprice} &7[Left Click]"
	set {-SellDisplay} to "&c&l[SELL X{amount}] &a${sellprice} &7[Right Click]"
	set {-BuyMessage} to "{prefix} You bought &e{amount} &7of &f{item} &7for &a${buyprice}&7."
	set {-SellMessage} to "{prefix} You sold &e{amount} &7of &f{item} &7for &a${sellprice}&7."
	set {-ShopList} to "&6&l[SHOPS]"
	set {-NotEnoughMoneyMessage} to "{prefix} &cYou do not have enough money to buy that!"
	set {-NotEnoughItemsMessage} to "{prefix} &cYou do not have enough of that item to sell!"
	set {-NotEnoughSpaceMessage} to "{prefix} &cYou do not have enough space to buy that!"
	set {-ShopDoesNotExist} to "{prefix} &cThat shop does not exist!"
	set {-NoPermission} to "{prefix} &cYou do not have permission to do that!"

	# Close any player's inventory who has a shop open
	loop all players:
		loop {-shops::*}:
			if loop-player's current inventory = loop-value-2:
				close inventory of loop-player
	
	# Clear all previous shops
	delete {-shops::*}


	# FUNCTIONS

	# redirectShopItem(display item, shop to redirect to)
	# Opens another shop to a player

	# createShopItem(item, amount, isBuyable, buy price, isSellable, sell price, hideflags value for display item)
	# Creates a buyable/sellable item for a shop

	# placeholderShopItem(item as placeholder)
	# Creates a placeholder item that does nothing

	# closeShopItem(display item)
	# Creates an item that closes the shop


	# Create your shops here
	# Main menu
	set {-shops::main} to chest inventory with 1 row named "&bSHOP"
	set slot 0 of {-shops::main} to redirectShopItem((diamond sword named "&cWEAPONS" with lore "&7&oClick to view weapons."), "weapons", 63)
	set slot 1 of {-shops::main} to redirectShopItem((wooden hoe named "&aTOOLS" with lore "&7&oClick to view tools."), "tools", 63)
	set slot 2 of {-shops::main} to redirectShopItem((grass named "&2BLOCKS" with lore "&7&oClick to view blocks."), "blocks")
	set slot 3 of {-shops::main} to redirectShopItem((cooked chicken named "&eFOOD" with lore "&7&oClick to view food."), "food")
	set slot 4 of {-shops::main} to redirectShopItem((feather named "&bLOOT" with lore "&7&oClick to view loot."), "loot")
	set slot 5 of {-shops::main} to redirectShopItem((diamond of sharpness 1 named "&dCUSTOM" with lore "&7&oClick to view custom items."), "custom", 63)
	set slot 7 of {-shops::main} to placeholderShopItem((diamond sword named "&7Just a placeholder" with nbt compound from "{Damage:750}", 63))
	set slot 8 of {-shops::main} to closeShopItem(barrier named "&4Close")

	# Weapons
	set {-shops::weapons} to chest inventory with 1 row named "&cWEAPONS"
	set slot 0 of {-shops::weapons} to createShopItem(wooden sword, 1, true, 20, false, 10, 63)
	set slot 1 of {-shops::weapons} to createShopItem(stone sword, 1, true, 50, false, 10, 63)
	set slot 2 of {-shops::weapons} to createShopItem(golden sword, 1, true, 100, false, 10, 63)
	set slot 3 of {-shops::weapons} to createShopItem(iron sword, 1, true, 150, false, 10, 63)
	set slot 4 of {-shops::weapons} to createShopItem(diamond sword, 1, true, 250, false, 10, 63)
	set slot 5 of {-shops::weapons} to createShopItem(netherite sword, 1, true, 1000, false, 10, 63)
	set slot 8 of {-shops::weapons} to redirectShopItem((arrow named "&c&lBACK" with lore "&7&oClick to return to shop menu."), "main")

	# Tools
	set {-shops::tools} to chest inventory with 2 row named "&aTOOLS"
	set slot 0 of {-shops::tools} to createShopItem(wooden axe, 1, true, 20, false, 10, 63)
	set slot 1 of {-shops::tools} to createShopItem(stone axe, 1, true, 50, false, 10, 63)
	set slot 2 of {-shops::tools} to createShopItem(golden axe, 1, true, 100, false, 10, 63)
	set slot 3 of {-shops::tools} to createShopItem(iron axe, 1, true, 150, false, 10, 63)
	set slot 4 of {-shops::tools} to createShopItem(diamond axe, 1, true, 250, false, 10, 63)
	set slot 5 of {-shops::tools} to createShopItem(netherite axe, 1, true, 1000, false, 10, 63)
	set slot 6 of {-shops::tools} to createShopItem(wooden hoe, 1, true, 20, false, 10, 63)
	set slot 7 of {-shops::tools} to createShopItem(stone hoe, 1, true, 50, false, 10, 63)
	set slot 8 of {-shops::tools} to createShopItem(golden hoe, 1, true, 100, false, 10, 63)
	set slot 9 of {-shops::tools} to createShopItem(iron hoe, 1, true, 150, false, 10, 63)
	set slot 10 of {-shops::tools} to createShopItem(diamond hoe, 1, true, 250, false, 10, 63)
	set slot 11 of {-shops::tools} to createShopItem(netherite hoe, 1, true, 1000, false, 10, 63)
	set slot 17 of {-shops::tools} to redirectShopItem((arrow named "&c&lBACK" with lore "&7&oClick to return to shop menu."), "main")

	# Blocks
	set {-shops::blocks} to chest inventory with 1 row named "&2Blocks"
	set slot 0 of {-shops::blocks} to createShopItem(dirt, 8, true, 15, true, 6)
	set slot 1 of {-shops::blocks} to createShopItem(grass, 8, true, 30, true, 12)
	set slot 2 of {-shops::blocks} to createShopItem(cobblestone, 8, true, 32, true, 10)
	set slot 8 of {-shops::blocks} to redirectShopItem((arrow named "&c&lBACK" with lore "&7&oClick to return to shop menu."), "main")

	# Food
	set {-shops::food} to chest inventory with 1 row named "&eFOOD"
	set slot 0 of {-shops::food} to createShopItem(cooked chicken, 1, true, 5, true, 3)
	set slot 1 of {-shops::food} to createShopItem(cooked porkchop, 1, true, 7, true, 4)
	set slot 2 of {-shops::food} to createShopItem(cooked mutton, 1, true, 9, true, 5)
	set slot 3 of {-shops::food} to createShopItem(cooked salmon, 1, true, 11, true, 6)
	set slot 4 of {-shops::food} to createShopItem(cooked cod, 1, true, 13, true, 7)
	set slot 5 of {-shops::food} to createShopItem(steak, 1, true, 15, true, 8)
	set slot 8 of {-shops::food} to redirectShopItem((arrow named "&c&lBACK" with lore "&7&oClick to return to shop menu."), "main")

	# Loot
	set {-shops::loot} to chest inventory with 1 row named "&bLOOT"
	set slot 0 of {-shops::loot} to createShopItem(iron ingot, 8, false, 5, true, 50)
	set slot 1 of {-shops::loot} to createShopItem(diamond, 4, false, 5, true, 125)	
	set slot 2 of {-shops::loot} to createShopItem(feather, 12, false, 5, true, 20)	
	set slot 3 of {-shops::loot} to createShopItem(string, 16, false, 5, true, 15)	
	set slot 8 of {-shops::loot} to redirectShopItem((arrow named "&c&lBACK" with lore "&7&oClick to return to shop menu."), "main")	

	# Custom
	set {-shops::custom} to chest inventory with 2 row named "&dCUSTOM (1)"
	set slot 0 of {-shops::custom} to createShopItem((diamond sword of sharpness 10 and unbreaking 5 named "&dGod Sword" with lore "", "&e&oA sword bestowed to the hero", "&e&oby God himself."), 1, true, 5000, false, 2500, 2)
	set slot 16 of {-shops::custom} to redirectShopItem((arrow named "&c&lBACK" with lore "&7&oClick to return to shop menu."), "main")
	set slot 17 of {-shops::custom} to redirectShopItem((feather named "&b&lNEXT PAGE ->" with lore "&7&oClick to go to next page."), "custom2")

	set {-shops::custom2} to chest inventory with 2 row named "&dCUSTOM (2)"
	set slot 0 of {-shops::custom2} to createShopItem((netherite axe of efficiency 10 and unbreaking 5 named "&dGod Axe" with lore "", "&e&oAn axe bestowed to the hero", "&e&oby God himself."), 1, true, 5000, true, 2500, 2)
	set slot 9 of {-shops::custom2} to redirectShopItem((feather named "&c&l<- Previous Page" with lore "&7&oClick to go to previous page."), "custom")