So i'm trying to get it so you can export NBT data from minecraft so it can be used in this online tool i'm making. Here is an example of the NBT data I am trying to convert:
const NbtString = "{ForgeCaps:{},Items:[{Count:1b,Slot:0b,id:"the_vault:card",tag:{data:{entries:[{colors:["RED"],groups:["Utility","Stat","Essence"],model:"the_vault:card/icon/mana_regeneration#inventory",modifier:{config:{attribute:"the_vault:mana_regen",maxTier:5b,pool:[{config:'{"min":0.01,"max":0.01,"step":0.01}',tier:1b},{config:'{"min":0.02,"max":0.02,"step":0.01}',tier:2b},{config:'{"min":0.03,"max":0.03,"step":0.01}',tier:3b},{config:'{"min":0.04,"max":0.04,"step":0.01}',tier:4b},{config:'{"min":0.05,"max":0.05,"step":0.01}',tier:5b}]},type:"gear",values:[{tier:1b,value:0.01f},{tier:2b,value:0.02f},{tier:3b,value:0.03f},{tier:4b,value:0.04f},{tier:5b,value:0.05f}]},name:'{"text":"Mana Regeneration Card"}'}],tier:1b}}},{Count:1b,Slot:1b,id:"the_vault:card",tag:{data:{entries:[{colors:["RED","GREEN","BLUE"],groups:["Wild","Stat","Temporal","Resource","Arcane","Evolution"],modifier:{config:{maxTier:1b},type:"dummy"},name:'{"text":"Blue Wild Card"}'}],tier:1b}}},{Count:1b,Slot:2b,id:"the_vault:card",tag:{data:{entries:[{colors:["BLUE"],condition:{config:{tiers:[{pool:[{filters:[{colorFilter:[{value:["GREEN"],weight:1b},{value:["BLUE"],weight:1b},{value:["YELLOW"],weight:1b},{value:["RED"],weight:1b}],groupFilter:[{value:["Stat"],weight:1b},{value:["Resource"],weight:1b},{value:["Evolution"],weight:1b}],minCount:{max:10b,min:7b,type:"uniform"},neighborFilter:[{weight:100b}],tierFilter:[]}],weight:1b},{filters:[{colorFilter:[{value:["GREEN"],weight:1b},{value:["BLUE"],weight:1b},{value:["YELLOW"],weight:1b},{value:["RED"],weight:1b}],groupFilter:[{value:["Stat"],weight:1b},{value:["Resource"],weight:1b},{value:["Evolution"],weight:1b}],minCount:{max:4b,min:3b,type:"uniform"},neighborFilter:[{value:["ROW"],weight:1b},{value:["COLUMN"],weight:1b},{value:["DIAGONAL"],weight:1b},{value:["ADJACENT"],weight:1b}],tierFilter:[]}],weight:1b},{filters:[{colorFilter:[{weight:1b}],groupFilter:[{value:["Arcane"],weight:1b}],maxCount:{max:3b,min:1b,type:"uniform"},neighborFilter:[{weight:1b}],tierFilter:[]}],weight:1b},{filters:[{colorFilter:[{weight:1b}],groupFilter:[{value:["Stat"],weight:1b},{value:["Resource"],weight:1b},{value:["Evolution"],weight:1b}],maxCount:{max:6b,min:4b,type:"uniform"},minCount:{max:2b,min:1b,type:"uniform"},neighborFilter:[{weight:1b}],tierFilter:[]}],weight:1b},{filters:[{colorFilter:[{value:["GREEN"],weight:1b},{value:["BLUE"],weight:1b},{value:["YELLOW"],weight:1b},{value:["RED"],weight:1b}],groupFilter:[{weight:1b}],maxCount:{max:6b,min:4b,type:"uniform"},minCount:{max:2b,min:1b,type:"uniform"},neighborFilter:[{weight:1b}],tierFilter:[]}],weight:1b},{filters:[{colorFilter:[{weight:1b}],groupFilter:[{weight:1b}],maxCount:{max:2b,min:1b,type:"uniform"},neighborFilter:[{value:["ROW"],weight:1b},{value:["COLUMN"],weight:1b},{value:["DIAGONAL"],weight:1b},{value:["ADJACENT"],weight:1b}],tierFilter:[]}],weight:1b}],tier:1b}]},filters:[{tier:1b,value:[{maxCount:1b,neighborFilter:["COLUMN"]}]}]},groups:["Offensive","Arcane"],model:"the_vault:card/icon/ice_blast#inventory",modifier:{config:{attribute:"the_vault:added_ability_level",maxTier:1b,pool:[{config:'{"abilityKey":"Ice_Bolt_Blast","levelChange":1}',tier:1b}]},type:"gear",values:[{tier:1b,value:{ability:"Ice_Bolt_Blast",levelChange:1}}]},name:'{"text":"Glacial Blast Card"}'}],tier:1b}}},{Count:1b,Slot:3b,id:"the_vault:card",tag:{data:{entries:[{colors:["GREEN"],groups:["Utility","Scaling"],model:"the_vault:card/icon/healing_efficiency#inventory",modifier:{config:{attribute:"the_vault:healing_effectiveness",maxTier:5b,pool:[{config:'{"min":0.002,"max":0.002,"step":1.0}',tier:1b},{config:'{"min":0.004,"max":0.004,"step":1.0}',tier:2b},{config:'{"min":0.006,"max":0.006,"step":1.0}',tier:3b},{config:'{"min":0.008,"max":0.008,"step":1.0}',tier:4b},{config:'{"min":0.01,"max":0.01,"step":1.0}',tier:5b}]},type:"gear",values:[{tier:1b,value:0.002f},{tier:2b,value:0.004f},{tier:3b,value:0.006f},{tier:4b,value:0.008f},{tier:5b,value:0.01f}]},name:'{"text":"Scaling Healing Efficiency Card"}',scaler:{config:{tiers:[{pool:[{filters:[{colorFilter:[{value:["GREEN"],weight:1b},{value:["BLUE"],weight:1b},{value:["YELLOW"],weight:1b},{value:["RED"],weight:1b}],groupFilter:[],neighborFilter:[{value:["ROW"],weight:5b},{value:["COLUMN"],weight:5b},{value:["DIAGONAL"],weight:3b},{value:["ADJACENT"],weight:5b},{value:["SURROUNDING"],weight:1b}],tierFilter:[]}],weight:1b},{filters:[{colorFilter:[{value:["GREEN"],weight:1b},{value:["BLUE"],weight:1b},{value:["YELLOW"],weight:1b},{value:["RED"],weight:1b}],groupFilter:[{value:["Stat"],weight:1b},{value:["Evolution"],weight:1b},{value:["Resource"],weight:1b}],neighborFilter:[{value:["ROW"],weight:5b},{value:["COLUMN"],weight:5b},{value:["DIAGONAL"],weight:3b},{value:["ADJACENT"],weight:5b},{value:["SURROUNDING"],weight:1b}],tierFilter:[]}],weight:1b},{filters:[{colorFilter:[],groupFilter:[{value:["Stat"],weight:1b},{value:["Evolution"],weight:1b},{value:["Resource"],weight:1b}],neighborFilter:[{value:["ROW"],weight:5b},{value:["COLUMN"],weight:5b},{value:["DIAGONAL"],weight:3b},{value:["ADJACENT"],weight:5b},{value:["SURROUNDING"],weight:1b}],tierFilter:[]}],weight:1b}],tier:1b}]},filters:[{tier:1b,value:[{colorFilter:["GREEN"],groupFilter:["Evolution"],neighborFilter:["SURROUNDING"]}]}]}}],tier:1b}}},{Count:1b,Slot:4b,id:"the_vault:card",tag:{data:{entries:[{colors:["GREEN"],groups:["Resource"],model:"the_vault:vault_plating#inventory",modifier:{config:{count:[{roll:{max:8b,min:3b,type:"uniform"},tier:1b}],highlightColor:65280,loot:[{item:"the_vault:vault_plating",weight:1.0d}],maxTier:1b,task:"@easy",tooltip:'{"color":"gold","extra":[{"color":"#FFFFFF","text":"${count}"},{"color":"yellow","text":" Vault Plating "},{"text":"${task}"}],"text":"+"}'},counts:[{count:7b,tier:1b}],task:{children:[],config:{filter:"@the_vault:living"},counter:{baseTarget:7b,config:{target:{max:7b,min:6b,type:"uniform"},variables:{targetTierContribution:1b}},current:0b,target:7b,type:"target"},operating:0b,renderer:{tooltip:'{"text":"per ${target} Living Chests looted"}',type:"card"},type:"loot_chest"},type:"task_loot",uuid:[I;-1335797438,959268282,-1831723904,956595013]},name:'{"text":"Vault Plating Card"}'}],tier:1b}}}],id:"quark:variant_chest",x:-317,y:112,z:473}"
That comes straight from Minecrafts "/data get" command.
I've created this function which fixes a lot of things already:
function parseNBT(data) {
return data
// Convert "1b", "2b", etc., to plain integers (byte to int)
.replace(/(\d+)b/g, '$1')
// Convert "1.0f", "0.2f", etc., to plain numbers (float to number)
.replace(/(\d*\.?\d+)f/g, '$1')
// Convert "1.0d", "0.5d" (double) to plain numbers
.replace(/(\d*\.?\d+)d/g, '$1')
// Handle "uuid:[I;...]" - Convert to valid JSON array
.replace(/uuid:\[I;([\d,-]+)\]/g, function (match, p1) {
return `"uuid": [${p1}]`;
})
}
I can actually put the string that that function returns inside a variable in the chrome console and the chrome console will parse it as an object.
But within my code i think i can only use JSON.parse and it needs to be formatted as JSON in that case. But that is where things get messy, because of the following reasons:
values with colons in them like "the_vault:card" or "quark:variant_chest". The usual way to put quotation marks is to find colons, but in this case that messes things up.
nested stuff like this part: pool:[{config:'{"min":0.01,"max":0.01,"step":0.01}',tier:1b},{config:'{"min":0.02,"max":0.02,"step":0.01}',tier:2b},{config:'{"min":0.03,"max":0.03,"step":0.01}',tier:3b},{config:'{"min":0.04,"max":0.04,"step":0.01}',tier:4b},{config:'{"min":0.05,"max":0.05,"step":0.01}',tier:5b}]
I've got two questions:
If you need any more information, please let me know.
How does the chrome console does it? Is there anyway to do it in the same way the chrome console does it?
The chrome console parses your input as JavaScript rather than JSON, which is less strict and allows e.g. unquoted property names. You can do approximately the same by running:
eval(`"use strict";(${parseNBT(NBTString)})`)
Be aware of the security implications of eval()
: It's a bad idea to use it unless you can trust the source of the NBT string.
If not, can someone help me with how to fix all the issues that arise when trying to format the string to correct JSON?
I would recommend going through the many open source NBT parser libraries, and either using one of them directly, or consulting its source code as a reference for your own implementation.