Added mod files

This commit is contained in:
Jacob Vinding
2025-12-26 21:38:55 +01:00
parent 64c4d60c47
commit c4ad0f3e2e
5039 changed files with 894558 additions and 0 deletions

View File

@@ -0,0 +1,455 @@
// priority: 9999
// Java imports
const Registry = Java.loadClass("net.minecraft.core.Registry"); // registries, needed for almost everything involving Java classes
// const BlockPos = Java.loadClass('net.minecraft.core.BlockPos'); //Block position. For some reason we don't need to import this?
const TagKey = Java.loadClass("net.minecraft.tags.TagKey");
const AxisDirection = Java.loadClass("net.minecraft.core.Direction$AxisDirection");
const Random = Java.loadClass("java.util.Random")
const InputItem = Java.loadClass("dev.latvian.mods.kubejs.item.InputItem")
const OutputItem = Java.loadClass("dev.latvian.mods.kubejs.item.OutputItem")
const InputFluid = Java.loadClass("dev.latvian.mods.kubejs.fluid.InputFluid")
const OutputFluid = Java.loadClass("dev.latvian.mods.kubejs.fluid.OutputFluid")
const FluidStackJS = Java.loadClass("dev.latvian.mods.kubejs.fluid.FluidStackJS")
const JsonObject = Java.loadClass("com.google.gson.JsonObject")
const Level = Java.loadClass("net.minecraft.world.level.Level") // For some reason, Kubejs requires that you load this class to create explosions that damage blocks
const colours = ["white", "orange", "magenta", "light_blue", "lime", "pink", "purple", "light_gray", "gray", "cyan", "brown", "green", "blue", "red", "black", "yellow"]
const native_metals = ["iron", "zinc", "lead", "copper", "nickel", "gold"]
const wood_types = ["minecraft:oak", "minecraft:spruce", "minecraft:birch", "minecraft:jungle", "minecraft:acacia", "minecraft:dark_oak", "minecraft:mangrove", "minecraft:cherry", "minecraft:crimson", "minecraft:warped"]
// None of the modded axes are registered for some reason
const unregistered_axes = ["ae2:certus_quartz_axe", "ae2:nether_quartz_axe", "ae2:fluix_axe", "tconstruct:hand_axe", "tconstruct:mattock", "tconstruct:broad_axe", "thermal:flux_saw"]
const donutCraft = (event, output, center, ring) => {
return event.shaped(output, [
"SSS",
"SCS",
"SSS"
], {
C: center,
S: ring
})
}
/**
* Used to make smithing/mechanical crafting recipes which are common in A&B.
* If the fourth parameter is excluded, then a stonecutting recipe will be created instead.
*
* First parmeter is the "base" ingredient,
* third parameter is the output,
* fourth parameter is the secondary ingredient.
*
* @param {ItemStackJS|string} machineItem
* @param {RecipeEventJS} event
* @param {ItemStackJS|string} outputIngredient
* @param {ItemStackJS|string} inputIngredient
*/
// event is the second parameter so that machineItem doesn't look like it's the output item
const createMachine = (machineItem, event, outputIngredient, inputIngredient) => {
machineItem = Ingredient.of(machineItem)
outputIngredient = Item.of(outputIngredient)
event.remove({ output: outputIngredient })
if (inputIngredient) {
inputIngredient = Ingredient.of(inputIngredient)
event.custom({
"type": "create:item_application",
"ingredients": [
machineItem.toJson(),
inputIngredient.toJson()
],
"results": (outputIngredient.isBlock() && outputIngredient.getCount() > 1) ?
[
outputIngredient.withCount(1).toJson(),
outputIngredient.withCount(outputIngredient.getCount() - 1).toJson()
]
:
[
outputIngredient.toJson()
]
})
}
else
event.stonecutting(outputIngredient, machineItem)
}
const andesiteMachine = (event, outputIngredient, inputIngredient) => {
return createMachine("kubejs:andesite_machine", event, outputIngredient, inputIngredient)
}
const copperMachine = (event, outputIngredient, inputIngredient) => {
return createMachine("kubejs:copper_machine", event, outputIngredient, inputIngredient)
}
const goldMachine = (event, outputIngredient, inputIngredient) => {
return createMachine("kubejs:gold_machine", event, outputIngredient, inputIngredient)
}
const brassMachine = (event, outputIngredient, inputIngredient) => {
return createMachine("kubejs:brass_machine", event, outputIngredient, inputIngredient)
}
const zincMachine = (event, outputIngredient, inputIngredient) => {
return createMachine("kubejs:zinc_machine", event, outputIngredient, inputIngredient)
}
const leadMachine = (event, outputIngredient, inputIngredient) => {
return createMachine("kubejs:lead_machine", event, outputIngredient, inputIngredient)
}
const invarMachine = (event, outputIngredient, inputIngredient) => {
return createMachine("thermal:machine_frame", event, outputIngredient, inputIngredient)
}
const enderiumMachine = (event, outputIngredient, inputIngredient) => {
return createMachine("kubejs:enderium_machine", event, outputIngredient, inputIngredient)
}
const fluixMachine = (event, outputIngredient, inputIngredient) => {
return createMachine("ae2:controller", event, outputIngredient, inputIngredient)
}
const toThermalInputJson = (value) => {
if (value instanceof InputFluid) {
return (FluidStackJS.of(value)).toJson()
}
value = InputItem.of(value)
if (value.count > 1) {
let json = new JsonObject()
json.add("value", value.ingredient.toJson())
json.addProperty("count", value.count)
return json
} else {
return value.ingredient.toJson();
}
}
const toThermalOutputJson = (value) => {
if (value instanceof OutputFluid) {
return (FluidStackJS.of(value)).toJson();
}
value = OutputItem.of(value)
let json = new JsonObject()
json.addProperty("item", value.item.getId())
json.addProperty("count", value.item.getCount())
if (value.getNbt() != null) {
json.addProperty("nbt", value.getNbt().toString())
}
if (value.hasChance()) {
json.addProperty("chance", value.getChance())
}
if (value.rolls != null) {
json.addProperty("minRolls", value.rolls.getMinValue())
json.addProperty("maxRolls", value.rolls.getMaxValue())
}
return json;
}
const addTreeOutput = (event, trunk, leaf, fluid) => {
return event.custom({
type: "thermal:tree_extractor",
trunk: {
Name: trunk,
Properties: {
axis: "y"
}
},
leaves: {
Name: leaf,
Properties: {
persistent: "false"
}
},
// sapling: "minecraft:jungle_sapling",
// min_height: 5,
// max_height: 10,
// min_leaves: 8,
// max_leaves: 12,
result: fluid ? toThermalOutputJson(fluid) : {
fluid: "thermal:resin",
amount: 25
}
})
}
/**
* Creates smeltery casting recipes for nuggets, ingots, blocks, etc
* Also creates a chilling recipe for the ingot
* This helper function requires all the items and fluids involved to be tagged correctly with the nugget/ingot/block tags
* @param {RecipeEventJS} event recipe event
* @param {string} metalName the name of the metal to create casting recipes (ex: "forge:ingots/{metalName}")
* @param {number} castingTime the time it takes to cast a block in a casting table (nugget and ingot casting times will be calculated based on that)
*/
const metalCasting = (event, metalName, castingTime) => {
let fluidTag = "forge:molten_" + metalName
let blockTag = "forge:storage_blocks/" + metalName
// block casting
if (Ingredient.of(`#forge:storage_blocks/${metalName}`).first != Item.empty) {
event.custom({
"type": "tconstruct:casting_basin",
"fluid": {
"tag": fluidTag,
"amount": 810
},
"result": {"tag": blockTag},
"cooling_time": castingTime
}).id(`kubejs:smeltery/casting/metal/${metalName}/block`)
}
let castTypes = [
// {name: 'coin', fluidCost: 30, cooldownMultiplier: 1/(3*Math.sqrt(3))},
{name: "gear", fluidCost: 360, cooldownMultiplier: 2 / 3},
{name: "ingot", fluidCost: 90, cooldownMultiplier: 1 / 3},
{name: "nugget", fluidCost: 10, cooldownMultiplier: 1 / 9},
{name: "plate", fluidCost: 90, cooldownMultiplier: 1 / 3},
{name: "rod", fluidCost: 45, cooldownMultiplier: 1 / (3 * Math.SQRT2)},
{name: "wire", fluidCost: 45, cooldownMultiplier: 1 / (3 * Math.SQRT2)}
]
// casting into casts
castTypes.forEach(cast=>{
if (Ingredient.of(`#forge:${cast.name}s/${metalName}`).first != Item.empty) {
event.custom({
"type": "tconstruct:casting_table",
"cast": {
"tag": `tconstruct:casts/multi_use/${cast.name}`
},
"fluid": {
"tag": fluidTag,
"amount": cast.fluidCost
},
"result": {"tag": `forge:${cast.name}s/${metalName}`},
"cooling_time": Math.round(castingTime * cast.cooldownMultiplier)
}).id(`kubejs:smeltery/casting/metal/${metalName}/${cast.name}_gold_cast`)
event.custom({
"type": "tconstruct:casting_table",
"cast": {
"tag": `tconstruct:casts/single_use/${cast.name}`
},
"cast_consumed": true,
"fluid": {
"tag": fluidTag,
"amount": cast.fluidCost
},
"result": {"tag": `forge:${cast.name}s/${metalName}`},
"cooling_time": Math.round(castingTime * cast.cooldownMultiplier)
}).id(`kubejs:smeltery/casting/metal/${metalName}/${cast.name}_sand_cast`)
}
})
// ingot chilling
if (Ingredient.of(`#forge:ingots/${metalName}`).first != Item.empty) {
event.custom({
"type": "thermal:chiller",
"ingredients": [{
"fluid_tag": fluidTag,
"amount": 90
},{
"item": "thermal:chiller_ingot_cast"
}],
"result": [{
"item": getPreferredItemFromTag("forge:ingots/" + metalName),
"count": 1
}],
"energy": 5000
}).id(`kubejs:crucible/kubejs/smeltery/casting/metal/${metalName}/ingot_gold_cast`)
}
}
/**
* Creates smeltery melting recipes for nuggets, ingots, blocks, etc
* Also creates a magma crucible recipe for the ingot
* @param {RecipeEventJS} event recipe event
* @param {string} metalName the name of the metal to create melting recipes for
* @param {number} meltingTime the time it takes to melt a block in the smeltery
* @param {number} temperature the temperature required to melt a block in the smeltery
*/
const metalMelting = (event, metalName, outputFluid, meltingTime, temperature) => {
let fluidTag = "forge:molten_" + metalName
let blockTag = "forge:storage_blocks/" + metalName
// block melting
if (Ingredient.of(`#forge:storage_blocks/${metalName}`).first != Item.empty) {
event.custom({
"type": "tconstruct:melting",
"ingredient": {"tag": `forge:storage_blocks/${metalName}`},
"result": {
"fluid": outputFluid,
"amount": 810
},
"temperature": temperature,
"time": meltingTime
}).id(`kubejs:smeltery/melting/metal/${metalName}/block`)
}
let castTypes = [
{name: "coin", fluidAmount: 30, timeMultiplier: 1 / (3 * Math.sqrt(3))},
{name: "gear", fluidAmount: 360, timeMultiplier: 2 / 3},
{name: "ingot", fluidAmount: 90, timeMultiplier: 1 / 3},
{name: "nugget", fluidAmount: 10, timeMultiplier: 1 / 9},
{name: "plate", fluidAmount: 90, timeMultiplier: 1 / 3},
{name: "rod", fluidAmount: 45, timeMultiplier: 1 / (3 * Math.SQRT2)},
{name: "wire", fluidAmount: 45, timeMultiplier: 1 / (3 * Math.SQRT2)}
]
// melting cast shapes
castTypes.forEach(cast=>{
if (Ingredient.of(`#forge:${cast.name}s/${metalName}`).first != Item.empty) {
event.custom({
"type": "tconstruct:melting",
"ingredient": {"tag": `forge:${cast.name}s/${metalName}`},
"result": {
"fluid": outputFluid,
"amount": cast.fluidAmount
},
"temperature": temperature,
"time": meltingTime * cast.timeMultiplier
}).id(`kubejs:smeltery/melting/metal/${metalName}/${cast.name}`)
}
})
// ingot crucible melting
if (Ingredient.of(`#forge:ingots/${metalName}`).first != Item.empty) {
event.custom({
type:"thermal:crucible",
ingredient: {
"tag": `forge:ingots/${metalName}`
},
result:[{
fluid: outputFluid,
amount:90
}],
energy:Math.round(meltingTime / 3) * 50
}).id(`kubejs:crucible/kubejs/smeltery/melting/metal/${metalName}/ingot`)
}
}
/** Used in datapack events instead of recipe events */
const addChiselingRecipe = (event, id, items, overwrite) => {
const json = {
type: "rechiseled:chiseling",
entries: [],
overwrite: !!overwrite
}
items.forEach(item=>{
json.entries.push({
item: item
})
})
event.addJson(id, json)
}
/** Used in a datapack event to remove a configured feature by its resource location */
const removeFeature = function(event, featureName) {
featureName = featureName.split(":")
let namespace = featureName[0]
let identifier = featureName[1]
event.addJson(`${namespace}:worldgen/configured_feature/${identifier}`, {
"type": "minecraft:no_op",
"config": {}
})
}
/** Used in a datapack event to add ore generation for an ore to the overworld
* This function only works for ores with both a stone and deepslate variant
*/
const addOregenOverworld = function(event, featureName, blockName, heightType, heightMin, heightMax, veinCount, veinSize, discardChanceOnAirExposure) {
featureName = featureName.split(":")
let namespace = featureName[0]
let identifier = featureName[1]
blockName = blockName.split(":")
let blockNamespace = blockName[0]
let blockIdentifier = blockName[1]
event.addJson(`${namespace}:worldgen/configured_feature/${identifier}`, {
"type": "minecraft:ore",
"config": {
"discard_chance_on_air_exposure": discardChanceOnAirExposure,
"size": veinSize,
"targets": [
{
"state": {"Name": `${blockNamespace}:${blockIdentifier}`},
"target": {"predicate_type": "minecraft:tag_match", "tag": "minecraft:stone_ore_replaceables"}
},
{
"state": {"Name": `${blockNamespace}:deepslate_${blockIdentifier}`},
"target": {"predicate_type": "minecraft:tag_match", "tag": "minecraft:deepslate_ore_replaceables"}
}
]
}
})
let minInclusive = {"absolute": heightMin}
let maxInclusive = {"absolute": heightMax}
// EMI Oregen will display more useful information if we change to using Above Bottom where it makes sense to
if (heightMin < -64) {
minInclusive = {"above_bottom": heightMin + 64}
maxInclusive = {"above_bottom": heightMax + 64}
} else if (heightMax > 320) {
minInclusive = {"below_top": -(heightMin - 320)}
maxInclusive = {"below_top": -(heightMax - 320)}
}
event.addJson(`${namespace}:worldgen/placed_feature/${identifier}`, {
"feature": `${namespace}:${identifier}`,
"placement": [
{"type": "minecraft:count", "count": veinCount},
{"type": "minecraft:in_square"},
{
"type": "minecraft:height_range",
"height": {
"type": heightType,
"min_inclusive": minInclusive,
"max_inclusive": maxInclusive
}
},
{"type": "minecraft:biome"}
]
})
event.addJson(`${namespace}:forge/biome_modifier/${identifier}`, {
"type": "forge:add_features",
"biomes": "#minecraft:is_overworld",
"features": `${namespace}:${identifier}`,
"step": "underground_ores"
})
}
/**
* Gets the prefered item from a tag. Useful for porting Mantle recipes that use tags as outputs.
* @param {string} tag Don't include a hashtag in the tag name
*/
// const ItemOutput = Java.loadClass('slimeknights.mantle.recipe.helper.ItemOutput');
const getPreferredItemFromTag = (tag) => {
/* Tried using mantle for this and it didn't work on first launch unfortunately */
// return Item.of(ItemOutput.fromTag(TagKey.create(Registry.ITEM_REGISTRY, tag), 1).get()).getId();
/* Create a copy of the mantle preferred mods list */
const preferredMods = ["minecraft", "create", "alloyed", "createdeco", "createaddition", "createbigcannons", "create_dd", "thermal", "tconstruct", "tmechworks"];
const tagItems = Ingredient.of("#" + tag).itemIds;
for (let i = 0;i < preferredMods.length;++i) { let modId = preferredMods[i];
for (let j = 0;j < tagItems.length;++j) { let itemId = tagItems[j];
if (itemId.split(":")[0] === modId) {
return itemId;
}
}
}
if (tagItems.length > 0) {
return tagItems[0];
}
return "minecraft:air";
}