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} list // * @param {number} degree_of_damage // * @returns {Map} // */ // 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} list // * @param {number} degree_of_damage // * @returns {Map} // */ // 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} // */ // 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) // } // }) // }) // } // } // })