-1

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:

  1. How does the chrome console does it? Is there anyway to do it in the same way the chrome console does it?
  2. If not, can someone help me with how to fix all the issues that arise when trying to format the string to correct JSON?

If you need any more information, please let me know.

1
  • Pasting a JavaScript object literal into the console is the same as using eval. If you pasted some JavaScript that did malicious things into the console - that will happen with eval too. So I can’t recommend eval because of those risks, but it would be the easiest way to do what you are after. Commented Sep 27, 2024 at 13:39

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

So lets say I'm building a tool for people to import the NBT data following from '/data get', so lets say a text field and a button press. Is that still a risk? I'll use this format: function looseJsonParse(obj) { return eval?.(`"use strict";(${obj})`); } It is much much easier....
If the NBT data comes from a text field, the user can enter anything they want, including JavaScript code that would then be executed. If your tool is a web app and the eval runs in the browser, that usually wouldn't be a security risk because the code could only affect the user's own browser session. But if you run eval on the server, or in an electron app, etc. then it could be a risk.
Alright, yeah i'll check out some of the libraries but otherwise just use eval. It won't run on a server, all just locally and probably wouldn't even be used by anyone lol.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.