[Feature Request] Fluidstack NBT Support in the TPP, Refinery & Fluid Mixer
HipHopHuman opened this issue ยท 14 comments
I think it's worth having this as it's own issue :)
This would lay the groundwork for some possible future features but also be immensely useful for pack devs. With this I think it'd even be possible for me to build the ice cream / resource multiplying ideas into a pack using KubeJS to test how it'd work
Wanted to circle back on this one, since I can't quite remember where we left it :)
NBT support is in now for fluid ingredients & outputs (just specify NBT in the same way as you would for item ingredients & outputs). Do you recall what else was needed? Maybe it's worth trying some experimental recipes in the TPP/Refinery/Fluid Mixer and seeing what breaks. If the required fixes aren't too radical, I can probably get them in before the 1.18 port...
I can't really give you a technical answer to this question, since I have very little experience with coding mods. What I can do is fire up a test bed instance with PNCR+KubeJS and see what's possible. I think if I attempt to add a more basic version of the ice cream idea, it should shed some light on what's missing and I'll report those findings in this issue. It'll take a while though.
@desht I got to the point where I'm implementing the actual Ice Cream in the fluid mixer, with a default NBT { "flavor": "Regular" }
.
It's not working. This is the "datapack" (actually done via KubeJS):
event.custom({
type: "pneumaticcraft:fluid_mixer",
pressure: 3,
time: 300,
input1: {
type: "pneumaticcraft:fluid",
fluid: "kubejs:nitrogen",
amount: 1000
},
input2: {
type: "pneumaticcraft:fluid",
fluid: "kubejs:sweetened_milk",
amount: 1000
},
fluid_output: {
fluid: "kubejs:liquid_ice_cream",
nbt: `{"flavor":"Regular"}`,
amount: 1250
}
})
I have already tried adding type: "forge:nbt"
to the fluid_output
section, but it didn't work. When the Ice Cream is crafted, it comes out as just a plain Ice Cream fluid with no attached NBT data. Am I missing something?
Those look like backquotes there, which isn't valid JSON syntax. Correct would be:
"fluid_output": {
"fluid": "kubejs:liquid_ice_cream",
"nbt": "{\"flavor\":\"Regular\"}",
"amount": 1250
}
JSON requires double-quoted strings, and any embedded quotes must be escaped with a backslash \
.
(This comment is a WIP)
TPP Changes
Item NBT
The TPP needs dynamic NBT support on inputs and outputs, with the ability to specify a relationship between them. One should be able to determine the quantity of output based on the quantity of input. This is needed to facilitate a use case like that of an Air Canister's stored air producing a relative amount of Liquified Air in the TPP. Supporting this isn't even possible with KubeJS right now, and the integration with the Holding enchant makes determining a theoretical maximum more complicated.
Max Fluid Output Quantity
I toyed with the idea of allowing Reinforced Canisters - at the same ratio as the basic ones, the output amount equates to about 20,000ml. The TPP's internal tank does not support any more than 16kmb, even with volume upgrades, so any output value larger than 16kmb "stalls" the TPP.
Refinery Changes (optional for now)
I experimented with separating Liquified Air into its constituent gases. It was really hard to get an accurate real-life representation of the percentage distribution (which I'm assuming is due to fractional limitations with the millibucket unit) so some "hand-wavium" (as you call it) had to be used and it produces a little too much CO2 (not that I have a use in mind for that at all, just wanted to see what working with the Refinery datapack format was like).
I think an improvement could be made here - allow for much higher numbers (even exceeding 16000mb), but add a new field "increment
" to both the input and output fields to control the speed at which the fluid "refines". This way, one could get a percentage distribution like 78%, 21%, 0.9%, 0.1% (which is closer to but not quite as accurate as real life). Then have the information that renders in JEI be determined by the increment, rather than the input amount. This way, more accurate distributions can be made and JEI can still render them within reason.
@desht that's not the issue, this isn't JSON, it's JavaScript. Backticks are valid - I use them in several other scripts. KubeJS converts this JS Object into the correct JSON representation. I use them to avoid having ugly escape characters and they're more distinguishable from single quotes
Ah, ok. I think I need to get a copy of the kubejs config you're using so I can test where it's going wrong...
Sure thing. Once you've installed KubeJS:
Make a .js
file (filename doesn't matter) in the <instance>/kubejs/startup_scripts
folder, and paste this in:
onEvent('fluid.registry', event => {
// add a liquid air fluid
event.create('liquified_air')
.textureThin(0xa1c2f7)
.bucketColor(0xa1c2f7)
.displayName('Liquified Air');
// add a liquid nitrogen fluid
event.create('nitrogen')
.textureThin(0xe9f4f5)
.bucketColor(0xe9f4f5)
.displayName('Nitrogen');
// add a liquid oxygen fluid
event.create('oxygen')
.textureThin(0xa1f7ee)
.bucketColor(0xa1f7ee)
.displayName('Oxygen');
// add an Argon fluid
event.create('argon')
.textureThin(0xc5c8e3)
.bucketColor(0xc5c8e3)
.displayName('Argon');
// add a Co2 fluid
event.create('co2')
.textureThin(0xdbb13d)
.bucketColor(0xdbb13d)
.displayName('CO2');
// add a Sweetened Milk fluid
event.create('sweetened_milk')
.textureThin(0xffffff)
.bucketColor(0xffffff)
.displayName('Sweetened Milk');
// add an Ice Cream fluid
event.create('liquid_ice_cream')
.textureThick(0xfafaeb)
.bucketColor(0xfafaeb)
.displayName('Ice Cream');
})
Then, make a .js
file in the <instance>/kubejs/server_scripts
folder, and paste this in:
onEvent('recipes', event => {
// liquified air from air canisters in TPP
event.custom({
type: 'pneumaticcraft:thermo_plant',
exothermic: false,
speed: 0.2,
item_input: {
type: 'forge:nbt',
item: 'pneumaticcraft:air_canister',
nbt: `{"pneumaticcraft:air": 30000}`
},
temperature: {
max_temp: 77.15,
min_temp: 67.15
},
fluid_output: {
fluid: 'kubejs:liquified_air',
amount: 5000
},
item_output: {
item: 'pneumaticcraft:air_canister'
}
}).id('air_canister_to_liquid_air');
event.custom({
type: "pneumaticcraft:thermo_plant",
exothermic: false,
speed: 0.6,
item_input: {
type: 'forge:nbt',
item: 'pneumaticcraft:reinforced_air_canister',
nbt: `{"pneumaticcraft:air": 120000}`
},
temperature: {
max_temp: 77.15,
min_temp: 67.15
},
fluid_output: {
fluid: 'kubejs:liquified_air',
amount: 16000
},
item_output: {
item: 'pneumaticcraft:reinforced_air_canister'
}
}).id('reinforced_canister_to_liquid_air')
// sweetened milk
event.custom({
type: "pneumaticcraft:thermo_plant",
exothermic: true,
speed: 0.2,
pressure: 2,
temperature: {
min_temp: 345.15
},
item_input: {
item: "minecraft:sugar",
amount: 1
},
fluid_input: {
type: 'pneumaticcraft:fluid',
fluid: 'minecraft:milk',
amount: 1000
},
fluid_output: {
fluid: 'kubejs:sweetened_milk',
amount: 1000
}
})
// liquid air components
event.custom({
type: "pneumaticcraft:refinery",
temperature: {
max_temp: 73.15
},
input: {
type: "pneumaticcraft:fluid",
fluid: "kubejs:liquified_air",
amount: 10
},
results: [
{ fluid: "kubejs:nitrogen", amount: 4 },
{ fluid: "kubejs:oxygen", amount: 3 },
{ fluid: "kubejs:argon", amount: 2 },
{ fluid: "kubejs:co2", amount: 1 }
]
}).id('liquid_air_to_constituents')
// ice cream!
event.custom({
type: "pneumaticcraft:fluid_mixer",
pressure: 3,
time: 300,
input1: {
type: "pneumaticcraft:fluid",
fluid: "kubejs:nitrogen",
amount: 1000
},
input2: {
type: "pneumaticcraft:fluid",
fluid: "kubejs:sweetened_milk",
amount: 1000
},
fluid_output: {
fluid: "kubejs:liquid_ice_cream",
nbt: `{"flavor":"Regular"}`,
amount: 1250
}
})
})
Some helpful things to know as you make changes with KubeJS:
- typing
/kubejs hand
will give you the NBT/Item data for the item you're holding - typing
/kubejs reload <argument>
allows you to reload startup, server, and client scripts, as well as textures (so you don't have to restart the game all the time) - if those fail, you have the vanilla
/reload
command for reloading server stuff, as well asF3+T
for reloading clientside stuff - if all that fails, restart the game (might be needed if you change any fluid properties)
- warning/error logs can be found in the
<instance>/logs/kubejs
folder
Thanks. Already somewhat familiar with KubeJS (it's in my dev world already for testing purposes, need to be sure dynamic recipe management works as expected...)
Other question: what did you check to determine that the output fluid from the Fluid Mixer recipe was missing the NBT data?
Note, extracting that fluid with a bucket will not preserve the NBT, because NBT-preserving behaviour is not part of vanilla/Forge bucket handling by default. To preserve NBT, the custom fluid (i.e. your Ice Cream) would need to override FluidAttributes#getBucket()
to store the fluidstack NBT in the bucket itemstack (an example of a mod that does this is Immersive Engineering and its buckets of potion fluid). I'm not sure if KubeJS allows that level of customisability...
Also, for this to work sensibly, the FluidStack
class (a Forge class) would need a method to add tooltip text similar to the ItemStack#getTooltipLines()
method. Such a method doesn't exist, so there's no way of adding tooltip data in the GUI based on the the fluid's NBT.
At this point, I'm thinking you're really going to need a separate fluid for each flavour...
That bucket thing explains it then - I was under the impression that NBT data was preserved as long as the fluid was in a bucket or container, and only lost NBT when placed in the world, because I read that somewhere on the KubeJS Discord history. I'll have to look into it - KubeJS may not have anything to preserve NBT data on bucket items built in, but it does give me the ability to create custom items with NBT as well as the ability to override right-click actions and hooks into the underlying mod's API (I can theoretically check which fluids are stored in a machine), so it'll be tedious, but should be possible.
As for overriding tooltips, I actually requested that be a feature of KubeJS a while ago, with different text based on NBT (for my custom Tool Belt in my PNC pack) and it was implemented by Lat rather quickly - KubeJS can absolutely handle giving items custom tooltip text based on NBT and even overriding existing tooltip lines with custom colors. I'm not sure it would work inside a machine GUI though, but worth a try.