LTDV10/packet/kubejs/server_scripts/mbd2/reactor.js
2026-04-14 18:20:56 +08:00

388 lines
16 KiB
JavaScript

const $ForgeEnergyRecipeCapability = Java.loadClass("com.lowdragmc.mbd2.common.capability.recipe.ForgeEnergyRecipeCapability")
const $FluidRecipeCapability = Java.loadClass("com.lowdragmc.mbd2.common.capability.recipe.FluidRecipeCapability")
const $SwitchWidget = Java.loadClass("com.lowdragmc.lowdraglib.gui.widget.SwitchWidget")
//初始化CustomData
MBDMachineEvents.onStructureFormed("createdelight:fission_reactor", e => {
let customData = e.event.machine.customData
let machine = e.event.machine
let assembly_count = 0
/** @type {Internal.MBDMultiblockMachine} */
let multiblock = machine
multiblock.parts.forEach(part => {
/** @type {Internal.MBDPartMachine} */
let machinePart = part
if (machinePart.definition.id() == "createdelight:fission_fuel_assembly")
assembly_count++
})
if(customData.getInt("assembly_count") != assembly_count) {
customData.putInt("assembly_count", assembly_count)
}
if(!customData.getDouble("burning_rate")) {
customData.putDouble("burning_rate", 0)
}
if(!customData.getDouble("temperature")) {
customData.putDouble("temperature", 298.15)
}
if(!customData.getDouble("degree_of_damage")) {
customData.putDouble("degree_of_damage", 0)
}
if(!customData.getDouble("multiplier")) {
customData.putDouble("multiplier", 0)
}
})
const BASE_HEAT_RATE = 0.08 // 基础发热率
const BASE_COOL_RATE = 0.08 // 基础冷却率
const TEMP_MULTIPLIER = 0.0005 // 温度对效率的影响
const CRITICAL_TEMP = 1500.0 //临界温度,超出后增加损坏率
const MELTDOWN_TEMP = 2500.0 //融毁温度,超出后直接爆炸
//升温逻辑及代码判断
MBDMachineEvents.onTick("createdelight:fission_reactor", e => {
const { machine } = e.event
const customData = machine.customData
if (machine.level.time % 3 != 0) return
let temp = customData.getDouble("temperature")
let degree_of_damage = customData.getDouble("degree_of_damage")
let multiplier = machine.customData.getDouble("multiplier")
// 缓存冷却与发热,避免重复调用造成开销
const heatProduced = ReactorUtil.heatProduced(machine)
const cooling = ReactorUtil.cooling(machine)
const coolingTemp = cooling[0]
const coolingDamage = cooling[1]
let ambientCooling = 0.05 + (temp - 298.15) * 0.0001
let newTemp = Math.max(298.15, temp + heatProduced * 3 - coolingTemp * 3 - ambientCooling * 3)
customData.putDouble("temperature", newTemp)
let damageProduced = 0
if (newTemp >= CRITICAL_TEMP) {
damageProduced = 0.01 * customData.getInt("assembly_count") * 3
if(degree_of_damage > 50) {
machine.level.playSound(null, machine.pos.x, machine.pos.y, machine.pos.z, "alexscaves:nuclear_siren", "blocks", 1, 1)
}
}
let newDamage = Math.max(0, degree_of_damage + damageProduced - coolingDamage * 3)
if (newDamage != degree_of_damage) {customData.putDouble("degree_of_damage", newDamage)}
if (temp < 1000) { multiplier = 0 }
else if (temp >= 1000 && temp <= 1500) { multiplier = (1 + 2 * (temp - 1000) / 500) }
else { multiplier = 3 }
customData.putDouble("multiplier", multiplier)
if (degree_of_damage >= 100) {ReactorUtil.Bombbbb(machine)}
if (newTemp >= MELTDOWN_TEMP) {ReactorUtil.Bombbbb(machine)}
// machine.level.tell(`damageProduced:${damageProduced}, damageReducecd:${damageReducecd}, newDamage:${newDamage}, boolean:${newTemp >= CRITICAL_TEMP}`)
})
//温度对于产电的调节
MBDMachineEvents.onBeforeRecipeModify("createdelight:fission_reactor", e => {
const { machine, recipe } = e.event
let burning_rate = machine.customData.getDouble("burning_rate")
let assembly_count = machine.customData.getInt("assembly_count") * burning_rate
e.event.setRecipe(recipe.copy(ContentModifier.multiplier(Math.pow(1.0415, assembly_count)), false, "both"))
})
MBDMachineEvents.onAfterRecipeModify("createdelight:fission_reactor", e => {
const { machine, recipe } = e.event
let multiplier = machine.customData.getDouble("multiplier")
if(multiplier != 0) {
e.event.setRecipe(recipe.copy(ContentModifier.multiplier(multiplier), false, "both"))
} else {
e.event.setRecipe(recipe.copy(ContentModifier.multiplier(0), false, "out"))
}
})
// 输入槽位有流体且输出槽位可接受配方产出时,使连续工作的空配方失效
MBDMachineEvents.onAfterRecipeWorking("createdelight:fission_reactor", e => {
const { machine, recipe } = e.event
if (recipe.id && recipe.id == "createdelight:fission_react/empty") {
let recipeLogic = machine.recipeLogic
let fluid = machine.getCapability(ForgeCapabilities.FLUID_HANDLER).orElse(null)
let energy = machine.getCapability(ForgeCapabilities.ENERGY).orElse(null)
let maxFluidInput = ReactorUtil.inputFluid(machine)
let maxEnergyOutput = ReactorUtil.outputEnergy(machine)
let maxFluidOutput = ReactorUtil.outputFluid(machine)
// machine.level.recipeManager.getByType("createdelight:fission_react").forEach((id, r) => {
// let mbdRecipe = machine.getModifiedRecipe(r)
// mbdRecipe.getOutputContents($ForgeEnergyRecipeCapability.CAP).forEach(con => {
// if (maxEnergyOutput < con.getContent())
// maxEnergyOutput = con.getContent()
// })
// mbdRecipe.getOutputContents($FluidRecipeCapability.CAP).forEach(con => {
// if (maxFluidOutput < con.getContent().getAmount())
// maxFluidOutput = con.getContent().getAmount()
// })
// mbdRecipe.getInputContents($FluidRecipeCapability.CAP).forEach(con => {
// if(maxFluidInput < con.getContent().getAmount())
// maxFluidInput = con.getContent().getAmount()
// })
// })
//输入槽位有流体且输出槽位可接受配方产出时,使连续工作的空配方失效
if (!fluid.getFluidInTank(0).empty
&& fluid.getFluidInTank(0).amount >= maxFluidInput
&& fluid.getFluidInTank(1).amount + maxFluidOutput <= fluid.getTankCapacity(1)
&& energy.getEnergyStored() + maxEnergyOutput <= energy.getMaxEnergyStored()
) {
recipeLogic.markLastRecipeDirty()
}
}
})
//实现移除时核反应堆爆炸
MBDMachineEvents.onRemoved("createdelight:fission_reactor", e => {
// console.log(`machineStateName: ${e.event.machine.machineStateName}`)
if (e.event.machine.machineStateName == "working") {
ReactorUtil.Bombbbb(e.event.machine)
}
})
MBDMachineEvents.onStateChanged("createdelight:fission_reactor", e => {
// console.log(`newState: ${e.event.newState}, oldState: ${e.event.oldState}`)
if (e.event.newState == "base" && e.event.oldState == "working") {
/** @type {Internal.MBDMultiblockMachine} */
let multiblock = e.event.machine
if (!multiblock.formed) {
ReactorUtil.Bombbbb(e.event.machine)
}
}
})
MBDMachineEvents.onStructureInvalid("createdelight:fission_reactor", e => {
// console.log(`machineStateName: ${e.event.machine.machineStateName}`)
if (e.event.machine.machineStateName == "working") {
ReactorUtil.Bombbbb(e.event.machine)
}
})
//实现机器紧急启停效果
//UI实现
MBDMachineEvents.onUI("createdelight:fission_reactor", e => {
const { machine, root } = e.event
const customData = machine.customData
let burning_rate = customData.getDouble("burning_rate")
let damage = root.getFirstWidgetById("degree_of_damage")
let temperature = root.getFirstWidgetById("temperature")
let reactor_switch = root.getFirstWidgetById("switch")
/**@type {SwitchWidget} */
let reactor_on = root.getFirstWidgetById("reactor_on")
/**@type {SwitchWidget} */
let reactor_off = root.getFirstWidgetById("reactor_off")
let heatProduced = root.getFirstWidgetById("heatProduced")
let cooling = root.getFirstWidgetById("cooling")
let ambientCooling = root.getFirstWidgetById("ambientCooling")
let inputFluid = root.getFirstWidgetById("inputFluid")
let outputFluid = root.getFirstWidgetById("outputFluid")
let outputEnergy = root.getFirstWidgetById("outputEnergy")
let burningRate = root.getFirstWidgetById("burningRate")
/** @type {TextFieldWidget} */
let modify_burning_rate = root.getFirstWidgetById("modify_burning_rate")
if(burning_rate != 0) {
reactor_on.setPressed(true)
reactor_off.setPressed(false)
} else {
reactor_on.setPressed(false)
reactor_off.setPressed(true)
}
reactor_off.setOnPressCallback(p => {
if(!p.isRemote && reactor_off.pressed) {
reactor_on.setPressed(false)
customData.putDouble("burning_rate", 0)
}
if(!p.isRemote && !reactor_off.pressed) {
reactor_off.setPressed(true)
}
return
})
reactor_on.setOnPressCallback(p => {
if(!p.isRemote && reactor_on.pressed) {
reactor_off.setPressed(false)
customData.putDouble("burning_rate", 1)
}
if(!p.isRemote && !reactor_on.pressed) {
reactor_on.setPressed(true)
}
return
})
damage.setTextProvider(() =>
Component.translate("message.createdelight.fission_reactor.degree_of_damage", Math.round(customData.getDouble("degree_of_damage") * 100) / 100)
)
temperature.setTextProvider(() =>
Component.translate("message.createdelight.fission_reactor.temperature", Math.round(customData.getDouble("temperature") * 100) / 100)
)
reactor_switch.setTextProvider(() =>
Component.translate("message.createdelight.fission_reactor.switch").append(
customData.getDouble("temperature") >= 1500
? Component.translate(
customData.getDouble("temperature") >= 2000
? "message.createdelight.fission_reactor.meltdown_temp"
: "message.createdelight.fission_reactor.critical_temp"
)
: Component.translate(
customData.getDouble("burning_rate") != 0
? "message.createdelight.fission_reactor.switch_on"
: "message.createdelight.fission_reactor.switch_off"
)
)
)
modify_burning_rate.currentString = (burning_rate * 100 || 0).toFixed()
modify_burning_rate.setNumbersOnlyInt(0, 100)
modify_burning_rate.setTextResponder(num => {
if(num != 0) {
reactor_on.setPressed(true)
reactor_off.setPressed(false)
} else {
reactor_on.setPressed(false)
reactor_off.setPressed(true)
}
customData.putDouble("burning_rate", num / 100)
})
heatProduced.setTextProvider(() =>
Component.translate("message.createdelight.fission_reactor.heat_produced", Math.round(ReactorUtil.heatProduced(machine) * 100) / 100)
)
cooling.setTextProvider(() =>
Component.translate("message.createdelight.fission_reactor.fluid_cooling", Math.round(ReactorUtil.cooling(machine)[0] * 100) / 100)
)
ambientCooling.setTextProvider(() =>
Component.translate("message.createdelight.fission_reactor.ambient_cooling",
Math.round((0.05 + (customData.getDouble("temperature") - 298.15) * 0.0001) * 100) / 100
)
)
inputFluid.setTextProvider(() =>
Component.translate("message.createdelight.fission_reactor.input_fluid", Math.round(ReactorUtil.inputFluid(machine,) * 100) / 100)
)
outputFluid.setTextProvider(() =>
Component.translate("message.createdelight.fission_reactor.output_fluid", Math.round(ReactorUtil.outputFluid(machine) * 100) / 100)
)
outputEnergy.setTextProvider(() =>
Component.translate("message.createdelight.fission_reactor.output_energy", Math.round(ReactorUtil.outputEnergy(machine)) / 1000)
)
burningRate.setTextProvider(() =>
Component.translate("message.createdelight.fission_reactor.burning_rate", Math.round(customData.getDouble("burning_rate") * 100))
)
})
//配方逻辑
MBDMachineEvents.onBeforeRecipeWorking("createdelight:fission_reactor", e => {
const { machine } = e.event
if (machine.customData.getDouble("burning_rate") == 0) {
e.event.setCanceled(true)
}
})
MBDMachineEvents.onFuelRecipeModify("createdelight:fission_reactor", e => {
const { machine } = e.event
if (machine.customData.getDouble("burning_rate") == 0) {
e.event.setCanceled(true)
}
})
// /**
// *
// * @param {Internal.Level} level
// * @param {BlockPos} pos
// * @param {number} age
// * @param {Map<string, number>} list
// * @param {number} degree_of_damage
// * @returns {Map<string, number>}
// */
// function nuclearDiffusionByAge(level, pos, age, list, degree_of_damage) {
// if (age == 0)
// return -1
// let positions = [pos.above(), pos.below(), pos.north(), pos.south(), pos.east(), pos.west()]
// if (!level.getBlock(pos).hasTag("create_new_age:stops_radiation")
// || degree_of_damage > 50) {
// list.set(`${pos.x},${pos.y},${pos.z}`, age)
// positions.forEach(position => {
// if (list.get(`${position.x},${position.y},${position.z}`) == null) {
// nuclearDiffusionByAge(level, position, age - 1, list, degree_of_damage)
// }
// })
// }
// }
// /**
// *
// * @param {Internal.Level} level
// * @param {BlockPos} pos
// * @param {number} size
// * @param {Map<string, number>} list
// * @param {number} degree_of_damage
// * @returns {Map<string, number>}
// */
// function nuclearDiffusionByCount(level, pos, size, list, degree_of_damage) {
// if (list.size >= size)
// return
// let positions = [pos.above(), pos.below(), pos.north(), pos.south(), pos.east(), pos.west()]
// if (!level.getBlock(pos).hasTag("create_new_age:stops_radiation")
// || degree_of_damage > 50) {
// list.set(`${pos.x},${pos.y},${pos.z}`, age)
// positions.forEach(position => {
// if (list.get(`${position.x},${position.y},${position.z}`) == null) {
// nuclearDiffusionByCount(level, position, age - 1, list, degree_of_damage)
// }
// })
// }
// }
// let _reactor_map = new Map()
// MBDMachineEvents.onTick("createdelight:fission_fuel_assembly", e => {
// const { level, pos, machineStateName } = e.event.machine
// // console.log(machineStateName)
// if (machineStateName == "working") {
// let time = level.time
// if (time % 200 == 0) {
// /**
// * @type {Map<string, number>}
// */
// let map = _reactor_map
// map.clear()
// //理论上只有一个控制器
// /**
// * @type {Internal.MBDMultiblockMachine}
// */
// let multiblock = e.event.machine.controllers.get(0)
// nuclearDiffusionByAge(level, pos, 7, map, multiblock.customData.getDouble("degree_of_damage"))
// map.forEach((age, position) => {
// let poslist = position.split(",")
// let x = parseInt(poslist[0])
// let y = parseInt(poslist[1])
// let z = parseInt(poslist[2])
// // let particle = Utils.particleOptions(`dust 1 0 0 1`)
// // level.spawnParticles(particle, false, x + 0.5, y + 0.5, z + 0.5, 0, 1, 0, 1, 0.5)
// level.getEntitiesWithin(AABB.of(x + 1, y + 1, z + 1, x - 1, y - 1, z - 1)).forEach(entity => {
// if (entity.isLiving()) {
// /**
// * @type {Internal.LivingEntity}
// */
// let livingEntity = entity
// livingEntity.potionEffects.add("alexscaves:irradiated", 12000, 4, true, true)
// }
// })
// })
// }
// }
// })