Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
775088d
feat: extendable & additional multiblock demo
Gebardensprache Jun 15, 2026
8e79f5b
Merge branch 'GregTechLite:main' into og/extendable_multi
Gebardensprache Jun 15, 2026
689319e
clean up some syntax & use mutable list but not collection
MagicSweepy Jun 16, 2026
32bea4c
feat: decoupling logic & new connect logic
Gebardensprache Jun 17, 2026
5e84ceb
fix: move to correct dir & interface rewrite
Gebardensprache Jun 17, 2026
9c29340
l10n for machine name in request addition recipe property
MagicSweepy Jun 17, 2026
4860107
connect interaction between AMB and EMB via data stick
MagicSweepy Jun 17, 2026
c351bce
raw recipe logic
MagicSweepy Jun 17, 2026
e2103b0
try to support multi request additional structures
MagicSweepy Jun 18, 2026
8fa0539
multi value support & port pcb to extendable recipe logic
MagicSweepy Jun 18, 2026
5acaac8
some missing overriden in AMB and EMB
MagicSweepy Jun 18, 2026
1352297
render oriented front overlay for AMB
MagicSweepy Jun 18, 2026
7d70c9b
fix unmodifiable operation for abilities of EMB
MagicSweepy Jun 18, 2026
ba4a34a
reimpl working status and persist it
MagicSweepy Jun 18, 2026
96436be
first-step rework PCB factory & shortcut recipe display text
MagicSweepy Jun 18, 2026
38b56e7
parallel and overclocking mechanism for pcb factory
MagicSweepy Jun 18, 2026
56eadd9
fix: nbt data persistence
Gebardensprache Jun 18, 2026
01df015
recipes for new pcb machines
MagicSweepy Jun 18, 2026
0fa0f0b
clean up deprecated pcb factory tooltips
MagicSweepy Jun 18, 2026
8523146
allow water cooling tower has some speed bonus for pcb factory
MagicSweepy Jun 19, 2026
e4b7f31
feat(gui): additional list, highlight (TODO), additional controller m…
Gebardensprache Jun 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package gregtechlite.gtlitecore.api.capability.logic

import gregtech.api.capability.impl.MultiblockRecipeLogic
import gregtech.api.recipes.Recipe
import gregtechlite.gtlitecore.api.metatileentity.multiblock.extendable.AdditionalStructureManager
import gregtechlite.gtlitecore.api.metatileentity.multiblock.extendable.RecipeMapExtendableMultiblock
import gregtechlite.gtlitecore.api.recipe.property.RequestAdditionalProperty

open class ExtendableMultiblockRecipeLogic<T: RecipeMapExtendableMultiblock<T>>(controller: RecipeMapExtendableMultiblock<T>,
protected val manager: AdditionalStructureManager<T>)
: MultiblockRecipeLogic(controller)
{
override fun checkRecipe(recipe: Recipe): Boolean
= super.checkRecipe(recipe) && checkAdditionalRequirement(recipe)

override fun canProgressRecipe(): Boolean
= super.canProgressRecipe() && (previousRecipe?.let { checkAdditionalRequirement(it) } ?: true)

private fun checkAdditionalRequirement(recipe: Recipe): Boolean
{
if (!recipe.hasProperty(RequestAdditionalProperty)) return true
val requirement = recipe.getProperty(RequestAdditionalProperty, null) ?: return false
return requirement.additionalStructures.all { manager.get(it).isNotEmpty() }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package gregtechlite.gtlitecore.api.metatileentity.multiblock.extendable

import codechicken.lib.render.CCRenderState
import codechicken.lib.render.pipeline.IVertexOperation
import codechicken.lib.vec.Matrix4
import com.cleanroommc.modularui.api.widget.IWidget
import com.cleanroommc.modularui.drawable.ItemDrawable
import com.cleanroommc.modularui.value.sync.PanelSyncManager
import com.cleanroommc.modularui.widgets.ButtonWidget
import gregtech.api.capability.GregtechDataCodes.WORKING_ENABLED
import gregtech.api.capability.IControllable
import gregtech.api.capability.IDataStickIntractable
import gregtech.api.metatileentity.multiblock.MultiblockWithDisplayBase
import gregtech.api.metatileentity.multiblock.ui.MultiblockUIBuilder
import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory
import gregtech.api.util.KeyUtil
import gregtechlite.gtlitecore.api.gui.GTLiteMuiTextures
import net.minecraft.client.resources.I18n
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.network.PacketBuffer
import net.minecraft.util.ResourceLocation
import net.minecraft.util.text.TextComponentTranslation
import java.awt.event.MouseEvent

abstract class AdditionalMultiblockBase<T : ExtendableMultiblock<T>>(metaTileEntityId: ResourceLocation)
: MultiblockWithDisplayBase(metaTileEntityId), IControllable, IDataStickIntractable
{
@JvmField
protected var mainController: ExtendableMultiblock<T>? = null
@JvmField
protected var isWorkingEnabled: Boolean = false

override fun hasMaintenanceMechanics() = false

override fun isWorkingEnabled() = isStructureFormed && isConnected()

override fun setWorkingEnabled(workingStatus: Boolean)
{
isWorkingEnabled = workingStatus
markDirty()
if (world != null && !world.isRemote)
{
writeCustomData(WORKING_ENABLED) { it.writeBoolean(isWorkingEnabled) }
}
}

protected fun isConnected() = mainController != null && mainController!!.isWorkingEnabled()

fun connect(controller: ExtendableMultiblock<T>?)
{
mainController?.removeAdditional(pos)
mainController = controller
mainController?.addAdditional(this)
}

override fun writeToNBT(data: NBTTagCompound): NBTTagCompound
{
super.writeToNBT(data)
data.setBoolean("isWorkingEnabled", isWorkingEnabled)
return data
}

override fun readFromNBT(data: NBTTagCompound)
{
super.readFromNBT(data)
setWorkingEnabled(data.getBoolean("isWorkingEnabled"))
}

override fun writeInitialSyncData(buf: PacketBuffer)
{
super.writeInitialSyncData(buf)
buf.writeBoolean(isWorkingEnabled)
}

override fun receiveInitialSyncData(buf: PacketBuffer)
{
super.receiveInitialSyncData(buf)
setWorkingEnabled(buf.readBoolean())
}

override fun receiveCustomData(dataId: Int, buf: PacketBuffer)
{
super.receiveCustomData(dataId, buf)
if (dataId == WORKING_ENABLED)
{
isWorkingEnabled = buf.readBoolean()
scheduleRenderUpdate()
}
}

override fun configureWarningText(builder: MultiblockUIBuilder?)
{
if (mainController?.isStructureFormed!!)
{
builder?.addMaintenanceProblemLines(mainController?.maintenanceProblem!!, true)
}
}

override fun createUIFactory(): MultiblockUIFactory?
{
return super.createUIFactory()
.createFlexButton { _, guiSyncManager ->
guiSyncManager.registerSyncedAction("highlight_main_controller") { mainController?.highlightController() }
return@createFlexButton ButtonWidget()
.background(GTLiteMuiTextures.BUTTON_ENABLE_MODULE)
.disableHoverBackground()
.onMousePressed {
guiSyncManager.callSyncedAction("highlight_main_controller")
true
}
.tooltip { tooltip ->
tooltip.addLine(KeyUtil.lang("gtlitecore.machine.extendable.highlight_main_controller"))
}
}
}

fun highlightController() {
TODO()
}

fun getButton(panelSyncManager: PanelSyncManager): IWidget
{
panelSyncManager.registerSyncedAction("highlight_controller") { highlightController() }
return ButtonWidget()
.size(18, 18)
.overlay(ItemDrawable(stackForm))
.addTooltipStringLines(listOf(
I18n.format(this.metaFullName),
I18n.format("gtlitecore.machine.extendable.additional_button_action") // TODO
))
.onMousePressed {
if (it == 1)
{
// Highlight
panelSyncManager.callSyncedAction("highlight_controller")
return@onMousePressed true
}
else if (it == 2)
{
// Other action... TODO
return@onMousePressed true
}
else
{
return@onMousePressed false
}
}
}

override fun onDataStickLeftClick(player: EntityPlayer, stack: ItemStack)
{
val tag = stack.tagCompound ?: NBTTagCompound()
tag.setTag("AdditionalPos", NBTTagCompound().apply {
setInteger("X", pos.x)
setInteger("Y", pos.y)
setInteger("Z", pos.z)
})
stack.tagCompound = tag
stack.setTranslatableName("gtlitecore.machine.additional_structure.data_stick.name")
player.sendStatusMessage(TextComponentTranslation("gtlitecore.machine.additional_structure.pos_saved",
pos.x, pos.y, pos.z), true)
}

override fun onDataStickRightClick(player: EntityPlayer, stack: ItemStack): Boolean = false

override fun renderMetaTileEntity(
renderState: CCRenderState, translation: Matrix4,
pipeline: Array<out IVertexOperation>,
)
{
super.renderMetaTileEntity(renderState, translation, pipeline)
frontOverlay.renderOrientedState(renderState, translation, pipeline, frontFacing, isActive, isWorkingEnabled)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package gregtechlite.gtlitecore.api.metatileentity.multiblock.extendable

import com.cleanroommc.modularui.api.widget.IWidget
import com.cleanroommc.modularui.value.sync.PanelSyncManager
import gregtech.api.metatileentity.multiblock.MultiblockAbility
import gregtechlite.gtlitecore.api.collection.openHashMapOf
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.nbt.NBTTagList
import net.minecraft.util.ResourceLocation
import net.minecraft.util.math.BlockPos

open class AdditionalStructureManager<T: ExtendableMultiblock<T>>(protected val base: ExtendableMultiblock<T>)
{
protected val structures = openHashMapOf<BlockPos, AdditionalMultiblockBase<T>>()

fun add(additionalMultiblockBase: AdditionalMultiblockBase<T>)
{
structures[additionalMultiblockBase.pos] = additionalMultiblockBase
}

fun get(metaTileEntityId: ResourceLocation): MutableList<AdditionalMultiblockBase<T>>
= structures.values.filter { it.metaTileEntityId.equals(metaTileEntityId) }.toMutableList()

fun get(pos: BlockPos): AdditionalMultiblockBase<T>? = structures[pos]

fun remove(pos: BlockPos) = structures.remove(pos)

fun getWidgets(panelSyncManager: PanelSyncManager): List<IWidget> {
return structures.values.map { it.getButton(panelSyncManager) }.toList()
}

fun <A> getAbilities(ability: MultiblockAbility<A>): MutableList<A> {
val abilities = ArrayList<A>()
structures.values.forEach { it.getAbilities<A>(ability).also { ab -> abilities.addAll(ab) } }
return abilities
}

fun serialize(): NBTTagCompound
{
val nbt = NBTTagCompound()
val list = NBTTagList()
structures.keys.forEach {
val pos = NBTTagCompound().apply {
setInteger("X", it.x)
setInteger("Y", it.y)
setInteger("Z", it.z)
}
list.appendTag(pos)
}
nbt.setTag("BlockPoses", list)
return nbt
}

fun deserialize(nbt: NBTTagCompound): List<BlockPos>
= nbt.getTagList("BlockPoses", 10).filterIsInstance<NBTTagCompound>()
.map { BlockPos(it.getInteger("X"), it.getInteger("Y"), it.getInteger("Z")) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package gregtechlite.gtlitecore.api.metatileentity.multiblock.extendable

import gregtech.api.capability.IMultiblockController
import net.minecraft.util.math.BlockPos

interface ExtendableMultiblock<T: ExtendableMultiblock<T>>: IMultiblockController
{
var additionalStructureManager: AdditionalStructureManager<T>
val maintenanceProblem: Byte

fun getPos(): BlockPos

fun highlightController()

fun isWorkingEnabled(): Boolean

fun addAdditional(additionalMultiblockBase: AdditionalMultiblockBase<T>)
{
additionalStructureManager.add(additionalMultiblockBase)
}

fun removeAdditional(pos: BlockPos)
{
additionalStructureManager.remove(pos)
}
}
Loading