Create Crypts and Caverns API

Create a new script called CryptsAndCaverns. This script will contain functions to help load the NFT and do the conversion so it can be passed to the Build function of the MapBuilder API.

After creating the script, you will need to add the 3 scripts that were imported previously so that the CryptsAndCaverns code has references to them.

  1. Select the CryptsAndCaverns script in My Scripts found in Project Content.
  2. Add the Base64 script as a custom property.
  3. Add the JSON script as a custom property.
  4. Add the SVGParser script as a custom property.

Edit CryptsAndCaverns Script

Open up the CryptsAndCaverns script and add the following code that will require the libraries that were added as custom properties.

local BASE64 = require(script:GetCustomProperty("Base64"))
local JSON = require(script:GetCustomProperty("JSON"))
local SVG_PARSER = require(script:GetCustomProperty("SVGParser"))
Code language: Lua (lua)

Create CryptsAndCaverns Table

Create a table called CryptsAndCaverns and set up the properties for the contract address and the collection count. The reason for the collection count is so that a random token ID can be retrieved to load a random map if required.

local CryptsAndCaverns = {

	SMART_CONTRACT_ADDRESS = "0x86f7692569914b5060ef39aab99e62ec96a6ed45",
	COLLECTION_COUNT = 8784

}
Code language: Lua (lua)

Create Load Function

Create a new function called Load. This function will accept an optional parameter that will either load the NFT based on the token ID passed in, or load a random NFT. The function will use the libraries that have been required to decode the data and convert it into something usable that will be returned back.

Using the Blockchain API, you can retrieve a token using the GetToken function. This function request the smart contract address, and a token ID. When passing the token ID to the GetToken function, make sure it is a String type.

After fetching the token, you need to fetch the rawMetadata and extract the first Bas64 encoded string. When decoded, it will contain a table that contains information about the NFT, but most importantly it contains another Base64 encoded string that contains the image data in SVG format. The SVG string is sent to the SVG Parser which will create a map based on the data. This is then in a compatiable format that can be converted into ASCII.

function CryptsAndCaverns.Load(tokenId)
	local token = Blockchain.GetToken(CryptsAndCaverns.SMART_CONTRACT_ADDRESS, tostring(tokenId or math.random(CryptsAndCaverns.COLLECTION_COUNT)))
	
	if(token ~= nil) then
		local metadata = token.rawMetadata
		local _, base64String = CoreString.Split(metadata, ",")
		local decodedBase64String = BASE64.decode(base64String)
		local objMetadata = JSON.decode(decodedBase64String)
		local _, SVGBase64String = CoreString.Split(objMetadata.image, ",")
		local rawSVG = BASE64.decode(SVGBase64String)

		local parser = SVG_PARSER:New(rawSVG)
		local mapData = parser:GetMap()
		local rows = parser:GetRows()
		local cols = parser:GetCols()
		local convertedMapData = CryptsAndCaverns.ConvertData(mapData, rows, cols)
		local convertedASCII = CryptsAndCaverns.GetConvertedASCII(convertedMapData)

		return convertedASCII, rows, cols
	else
		warn("Could not load token.")
	end

	return "", 0, 0
end
Code language: Lua (lua)

Create ConvertData Function

Cretae a new function called ConvertData that will be called from within the Load function. It will receive the map data from the SVG Parser, the total columns and rows. This function will go through each cell of the mapData table to make sure it is all valid. It will add random enemies spawn points and a random player spawn point to the map. This is then a valid map that will then be converted to ASCII to be used to build the 3D map in world.

function CryptsAndCaverns.ConvertData(mapData, cols, rows)
	local wallString = nil
	local converted = {}
	local hasSpawn = false

	for row = 1, #mapData do
		for col = 1, #mapData[row] do
			if  mapData[row][col] ~= "-" and not wallString then
				wallString = mapData[row][col]
				break
			end
		end
	end

	local allZeroTiles = {}

	for row = 1, rows do
		table.insert(converted, {})

		for col = 1, cols do
			local entry = mapData[row][col]
				
			if entry == wallString then
				converted[row][col] = "1"
			else
				local spawnEnemy = math.random(1, 100)

				if spawnEnemy <= 10 then
					converted[row][col] = "E"
				else
					local value = "0"

					if(not hasSpawn) then
						local isSpawn = math.random(30)

						if(isSpawn == 1) then
							value = "S"
							hasSpawn = true
						end
					end

					converted[row][col] = value
					
					if value == "0" then
						allZeroTiles[#allZeroTiles + 1] = { row, col }
					end
				end
			end
		end
	end

	if(not hasSpawn and #allZeroTiles > 0) then
		local spawnTile = allZeroTiles[math.random(#allZeroTiles)]

		converted[spawnTile[1]][spawnTile[2]] = "S"
	end

	return converted
end
Code language: Lua (lua)

Create GetConvertedASCII Function

Create a new function called GetConvertedASCII that will turn the map data into a valid ASCII string that can then be sent to the MapBuilder script to build the map.

function CryptsAndCaverns.GetConvertedASCII(converted)
	local str = ""

	for r = 1, #converted do
		for c = 1, #converted[r] do
			str = str .. string.sub(tostring(converted[r][c]), 1, 1) .. ""
		end

		str = str .. "\n"
	end

	return str
end
Code language: Lua (lua)

Return CryptsAndCaverns

Whenever you created a Lua library/API you need to return something back so that scripts which require the library/api can use the functions within it. In this case you want to return the CryptsAndCaverns table and the end of the script.

return CryptsAndCaverns
Code language: Lua (lua)

The CryptsAndCaverns Script

local BASE64 = require(script:GetCustomProperty("Base64"))
local JSON = require(script:GetCustomProperty("JSON"))
local SVG_PARSER = require(script:GetCustomProperty("SVGParser"))

local CryptsAndCaverns = {

	SMART_CONTRACT_ADDRESS = "0x86f7692569914b5060ef39aab99e62ec96a6ed45",
	COLLECTION_COUNT = 8784

}

function CryptsAndCaverns.Load(tokenId)
	local token = Blockchain.GetToken(CryptsAndCaverns.SMART_CONTRACT_ADDRESS, tostring(tokenId or math.random(CryptsAndCaverns.COLLECTION_COUNT)))
	
	if(token ~= nil) then
		local metadata = token.rawMetadata

		local _, base64String = CoreString.Split(metadata, ",")
		local decodedBase64String = BASE64.decode(base64String)

		local objMetadata = JSON.decode(decodedBase64String)
		local _, SVGBase64String = CoreString.Split(objMetadata.image, ",")
		local rawSVG = BASE64.decode(SVGBase64String)

		local parser = SVG_PARSER:New(rawSVG)

		local mapData = parser:GetMap()
		local rows = parser:GetRows()
		local cols = parser:GetCols()
		local convertedMapData = CryptsAndCaverns.ConvertData(mapData, rows, cols)
		local convertedASCII = CryptsAndCaverns.GetConvertedASCII(convertedMapData)

		return convertedASCII, rows, cols
	else
		warn("Could not load token.")
	end

	return "", 0, 0
end

function CryptsAndCaverns.ConvertData(mapData, cols, rows)
	local wallString = nil
	local converted = {}
	local hasSpawn = false

	for row = 1, #mapData do
		for col = 1, #mapData[row] do
			if  mapData[row][col] ~= "-" and not wallString then
				wallString = mapData[row][col]
				break
			end
		end
	end

	local allZeroTiles = {}

	for row = 1, rows do
		table.insert(converted, {})

		for col = 1, cols do
			local entry = mapData[row][col]
				
			if entry == wallString then
				converted[row][col] = "1"
			else
				local spawnEnemy = math.random(1, 100)

				if spawnEnemy <= 10 then
					converted[row][col] = "E"
				else
					local value = "0"

					if(not hasSpawn) then
						local isSpawn = math.random(30)

						if(isSpawn == 1) then
							value = "S"
							hasSpawn = true
						end
					end

					converted[row][col] = value

					if value == "0" then
						allZeroTiles[#allZeroTiles + 1] = { row, col }
					end
				end
			end
		end
	end

	if(not hasSpawn and #allZeroTiles > 0) then
		local spawnTile = allZeroTiles[math.random(#allZeroTiles)]

		converted[spawnTile[1]][spawnTile[2]] = "S"
	end

	return converted
end

function CryptsAndCaverns.GetConvertedASCII(converted)
	local str = ""

	for r = 1, #converted do
		for c = 1, #converted[r] do
			str = str .. string.sub(tostring(converted[r][c]), 1, 1) .. ""
		end

		str = str .. "\n"
	end

	return str
end

return CryptsAndCaverns
Code language: Lua (lua)
Scroll to Top