Matter panel sorting (with buttons), cleanup nbt extensions
This commit is contained in:
parent
f4146ffea9
commit
441f358e12
@ -638,6 +638,14 @@ private fun gui(provider: MatteryLanguageProvider) {
|
|||||||
|
|
||||||
gui("side_mode.pull", "Pull")
|
gui("side_mode.pull", "Pull")
|
||||||
gui("side_mode.push", "Push")
|
gui("side_mode.push", "Push")
|
||||||
|
|
||||||
|
gui("sorting.default", "Default sorting")
|
||||||
|
gui("sorting.name", "Sort by name")
|
||||||
|
gui("sorting.id", "Sort by ID")
|
||||||
|
gui("sorting.modid", "Sort by Namespace (mod) ID")
|
||||||
|
gui("sorting.count", "Sort by amount")
|
||||||
|
gui("sorting.ascending", "Ascending")
|
||||||
|
gui("sorting.descending", "Descending")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,6 +643,14 @@ private fun gui(provider: MatteryLanguageProvider) {
|
|||||||
|
|
||||||
gui("side_mode.pull", "Автоматическое вытягивание")
|
gui("side_mode.pull", "Автоматическое вытягивание")
|
||||||
gui("side_mode.push", "Автоматическое выталкивание")
|
gui("side_mode.push", "Автоматическое выталкивание")
|
||||||
|
|
||||||
|
gui("sorting.default", "Сортировка по умолчанию")
|
||||||
|
gui("sorting.name", "Сортировка по имени")
|
||||||
|
gui("sorting.id", "Сортировка по ID")
|
||||||
|
gui("sorting.modid", "Сортировка по пространству имён (моду)")
|
||||||
|
gui("sorting.count", "Сортировка по количеству")
|
||||||
|
gui("sorting.ascending", "Возрастающая")
|
||||||
|
gui("sorting.descending", "Убывающая")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,30 +2,23 @@ package ru.dbotthepony.mc.otm.block.entity
|
|||||||
|
|
||||||
import net.minecraft.ChatFormatting
|
import net.minecraft.ChatFormatting
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.core.Direction
|
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.world.item.BlockItem
|
import net.minecraft.world.item.BlockItem
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraft.world.item.TooltipFlag
|
import net.minecraft.world.item.TooltipFlag
|
||||||
import net.minecraft.world.level.BlockGetter
|
import net.minecraft.world.level.BlockGetter
|
||||||
import net.minecraft.world.level.Level
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import net.minecraftforge.common.capabilities.Capability
|
|
||||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||||
import net.minecraftforge.common.util.LazyOptional
|
|
||||||
import ru.dbotthepony.mc.otm.capability.*
|
import ru.dbotthepony.mc.otm.capability.*
|
||||||
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
|
|
||||||
import ru.dbotthepony.mc.otm.capability.energy.ItemEnergyStorageImpl
|
import ru.dbotthepony.mc.otm.capability.energy.ItemEnergyStorageImpl
|
||||||
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
import ru.dbotthepony.mc.otm.container.HandlerFilter
|
||||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.ifHas
|
|
||||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.map
|
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
|
||||||
|
|
||||||
abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(p_155228_, p_155229_, p_155230_) {
|
abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(p_155228_, p_155229_, p_155230_) {
|
||||||
val batteryContainer = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer)
|
val batteryContainer = MatteryContainer(::setChangedLight, 1).also(::addDroppableContainer)
|
||||||
|
@ -2,7 +2,7 @@ package ru.dbotthepony.mc.otm.block.entity
|
|||||||
|
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraftforge.common.util.INBTSerializable
|
import net.minecraftforge.common.util.INBTSerializable
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.getEnum
|
import ru.dbotthepony.mc.otm.core.nbt.mapString
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
import ru.dbotthepony.mc.otm.network.FieldSynchronizer
|
import ru.dbotthepony.mc.otm.network.FieldSynchronizer
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ abstract class AbstractRedstoneControl : INBTSerializable<CompoundTag?> {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
redstoneSetting = nbt.getEnum(SETTING_KEY)
|
redstoneSetting = nbt.mapString(SETTING_KEY, RedstoneSetting::valueOf, RedstoneSetting.LOW)
|
||||||
redstoneSignal = nbt.getInt(SIGNAL_KEY)
|
redstoneSignal = nbt.getInt(SIGNAL_KEY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
|||||||
import ru.dbotthepony.mc.otm.registry.MItems
|
import ru.dbotthepony.mc.otm.registry.MItems
|
||||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||||
import ru.dbotthepony.mc.otm.core.math.getSphericalBlockPositions
|
import ru.dbotthepony.mc.otm.core.math.getSphericalBlockPositions
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.mapIf
|
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
import ru.dbotthepony.mc.otm.matter.MatterManager
|
import ru.dbotthepony.mc.otm.matter.MatterManager
|
||||||
import ru.dbotthepony.mc.otm.triggers.BlackHoleTrigger
|
import ru.dbotthepony.mc.otm.triggers.BlackHoleTrigger
|
||||||
@ -164,7 +164,7 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mattery
|
|||||||
|
|
||||||
override fun load(tag: CompoundTag) {
|
override fun load(tag: CompoundTag) {
|
||||||
super.load(tag)
|
super.load(tag)
|
||||||
mass = tag.mapIf("mass", Decimal::deserializeNBT) ?: BASELINE_MASS
|
mass = tag.map("mass", Decimal::deserializeNBT) ?: BASELINE_MASS
|
||||||
spinDirection = tag.getBoolean("spin_direction")
|
spinDirection = tag.getBoolean("spin_direction")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package ru.dbotthepony.mc.otm.block.entity.matter
|
package ru.dbotthepony.mc.otm.block.entity.matter
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import ru.dbotthepony.mc.otm.menu.matter.MatterPanelMenu
|
import ru.dbotthepony.mc.otm.menu.matter.MatterPanelMenu
|
||||||
@ -11,13 +13,17 @@ import java.util.HashMap
|
|||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.ListTag
|
import net.minecraft.nbt.ListTag
|
||||||
import net.minecraft.nbt.Tag
|
|
||||||
import net.minecraft.network.chat.Component
|
|
||||||
import net.minecraft.server.level.ServerLevel
|
import net.minecraft.server.level.ServerLevel
|
||||||
import net.minecraft.world.level.Level
|
import net.minecraft.world.level.Level
|
||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import net.minecraftforge.common.util.INBTSerializable
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.capability.matter.*
|
import ru.dbotthepony.mc.otm.capability.matter.*
|
||||||
|
import ru.dbotthepony.mc.otm.core.nbt.getBoolean
|
||||||
|
import ru.dbotthepony.mc.otm.core.nbt.getCompoundList
|
||||||
|
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||||
|
import ru.dbotthepony.mc.otm.core.nbt.mapString
|
||||||
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.ItemSorter
|
||||||
import ru.dbotthepony.mc.otm.graph.Graph6Node
|
import ru.dbotthepony.mc.otm.graph.Graph6Node
|
||||||
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
|
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
|
||||||
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
|
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
|
||||||
@ -28,6 +34,26 @@ import java.util.stream.Stream
|
|||||||
class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||||
MatteryDeviceBlockEntity(MBlockEntities.MATTER_PANEL, p_155229_, p_155230_), IMatterGraphNode, IReplicationTaskProvider {
|
MatteryDeviceBlockEntity(MBlockEntities.MATTER_PANEL, p_155229_, p_155230_), IMatterGraphNode, IReplicationTaskProvider {
|
||||||
|
|
||||||
|
class PlayerSettings(var sorter: ItemSorter = ItemSorter.DEFAULT, var ascending: Boolean = true) : INBTSerializable<CompoundTag> {
|
||||||
|
override fun serializeNBT(): CompoundTag {
|
||||||
|
return CompoundTag().also {
|
||||||
|
it["sorter"] = sorter.name
|
||||||
|
it["ascending"] = ascending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deserializeNBT(nbt: CompoundTag) {
|
||||||
|
sorter = nbt.mapString("sorter", ItemSorter::valueOf, ItemSorter.DEFAULT)
|
||||||
|
ascending = nbt.getBoolean("ascending", true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val playerSettings = Object2ObjectOpenHashMap<UUID, PlayerSettings>()
|
||||||
|
|
||||||
|
fun getPlayerSettings(ply: Player): PlayerSettings {
|
||||||
|
return playerSettings.computeIfAbsent(ply.uuid, Object2ObjectFunction { PlayerSettings() })
|
||||||
|
}
|
||||||
|
|
||||||
private val listeners = ArrayList<MatterPanelMenu>()
|
private val listeners = ArrayList<MatterPanelMenu>()
|
||||||
override val matterNode = Graph6Node<IMatterGraphNode>(this)
|
override val matterNode = Graph6Node<IMatterGraphNode>(this)
|
||||||
|
|
||||||
@ -39,9 +65,6 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
|||||||
listeners.remove(menu)
|
listeners.remove(menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val defaultDisplayName: Component
|
|
||||||
get() = MACHINE_NAME
|
|
||||||
|
|
||||||
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
||||||
return MatterPanelMenu(containerID, inventory, this)
|
return MatterPanelMenu(containerID, inventory, this)
|
||||||
}
|
}
|
||||||
@ -131,13 +154,21 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
|||||||
list.add(task.serializeNBT())
|
list.add(task.serializeNBT())
|
||||||
}
|
}
|
||||||
|
|
||||||
nbt.put("tasks", list)
|
nbt["tasks"] = list
|
||||||
|
|
||||||
|
val settings = CompoundTag()
|
||||||
|
|
||||||
|
for ((uuid, value) in playerSettings) {
|
||||||
|
settings[uuid.toString()] = value.serializeNBT()
|
||||||
|
}
|
||||||
|
|
||||||
|
nbt["settings"] = settings
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun load(nbt: CompoundTag) {
|
override fun load(nbt: CompoundTag) {
|
||||||
super.load(nbt)
|
super.load(nbt)
|
||||||
_tasks.clear()
|
_tasks.clear()
|
||||||
val list = nbt.getList("tasks", Tag.TAG_COMPOUND.toInt())
|
val list = nbt.getCompoundList("tasks")
|
||||||
|
|
||||||
for (tag in list) {
|
for (tag in list) {
|
||||||
val task = ReplicationTask.deserializeNBT(tag)
|
val task = ReplicationTask.deserializeNBT(tag)
|
||||||
@ -146,6 +177,15 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
|||||||
_tasks[task.id] = task
|
_tasks[task.id] = task
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
playerSettings.clear()
|
||||||
|
|
||||||
|
nbt.map("settings") { it: CompoundTag ->
|
||||||
|
for (k in it.allKeys) {
|
||||||
|
playerSettings.computeIfAbsent(UUID.fromString(k), Object2ObjectFunction { PlayerSettings() })
|
||||||
|
.deserializeNBT(it.getCompound(k))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTask(id: UUID): ReplicationTask? {
|
override fun getTask(id: UUID): ReplicationTask? {
|
||||||
@ -184,8 +224,4 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
|||||||
|
|
||||||
_tasks.clear()
|
_tasks.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.matter_panel")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
|
|||||||
import ru.dbotthepony.mc.otm.network.MatteryPacket
|
import ru.dbotthepony.mc.otm.network.MatteryPacket
|
||||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||||
import ru.dbotthepony.mc.otm.container.set
|
import ru.dbotthepony.mc.otm.container.set
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.getEnum
|
import ru.dbotthepony.mc.otm.core.nbt.mapString
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
import ru.dbotthepony.mc.otm.menu.storage.ItemMonitorMenu
|
import ru.dbotthepony.mc.otm.menu.storage.ItemMonitorMenu
|
||||||
import ru.dbotthepony.mc.otm.storage.*
|
import ru.dbotthepony.mc.otm.storage.*
|
||||||
@ -93,9 +93,9 @@ class ItemMonitorPlayerSettings : INBTSerializable<CompoundTag>, MatteryPacket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun deserializeNBT(nbt: CompoundTag) {
|
override fun deserializeNBT(nbt: CompoundTag) {
|
||||||
ingredientPriority = nbt.getEnum(INGREDIENT_PRIORITY_KEY)
|
ingredientPriority = nbt.mapString(INGREDIENT_PRIORITY_KEY, IngredientPriority::valueOf, IngredientPriority.SYSTEM)
|
||||||
resultTarget = nbt.getEnum(RESULT_TARGET_KEY)
|
resultTarget = nbt.mapString(RESULT_TARGET_KEY, ResultTarget::valueOf, ResultTarget.MIXED)
|
||||||
craftingAmount = nbt.getEnum(QUICK_CRAFT_AMOUNT_KEY)
|
craftingAmount = nbt.mapString(QUICK_CRAFT_AMOUNT_KEY, Amount::valueOf, Amount.STACK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun read(buff: FriendlyByteBuf) {
|
fun read(buff: FriendlyByteBuf) {
|
||||||
|
@ -20,7 +20,6 @@ import ru.dbotthepony.mc.otm.core.math.BlockRotation
|
|||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.core.math.getDecimal
|
import ru.dbotthepony.mc.otm.core.math.getDecimal
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.getByteArrayList
|
import ru.dbotthepony.mc.otm.core.nbt.getByteArrayList
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.ifHas
|
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.map
|
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
import ru.dbotthepony.mc.otm.menu.tech.EnergyCounterMenu
|
import ru.dbotthepony.mc.otm.menu.tech.EnergyCounterMenu
|
||||||
@ -101,7 +100,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
|||||||
passed = nbt.getDecimal(PASSED_ENERGY_KEY)
|
passed = nbt.getDecimal(PASSED_ENERGY_KEY)
|
||||||
ioLimit = nbt.map(IO_LIMIT_KEY, Decimal.Companion::deserializeNBT)
|
ioLimit = nbt.map(IO_LIMIT_KEY, Decimal.Companion::deserializeNBT)
|
||||||
|
|
||||||
nbt.ifHas(POWER_HISTORY_POINTER_KEY, IntTag::class.java) {
|
nbt.map(POWER_HISTORY_POINTER_KEY) { it: IntTag ->
|
||||||
historyTick = it.asInt
|
historyTick = it.asInt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import ru.dbotthepony.mc.otm.core.*
|
|||||||
import ru.dbotthepony.mc.otm.core.math.BigInteger
|
import ru.dbotthepony.mc.otm.core.math.BigInteger
|
||||||
import ru.dbotthepony.mc.otm.core.math.isPositive
|
import ru.dbotthepony.mc.otm.core.math.isPositive
|
||||||
import ru.dbotthepony.mc.otm.core.math.serializeNBT
|
import ru.dbotthepony.mc.otm.core.math.serializeNBT
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.ifHas
|
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
import ru.dbotthepony.mc.otm.storage.*
|
import ru.dbotthepony.mc.otm.storage.*
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
@ -176,10 +176,7 @@ abstract class AbstractMatteryDrive<T : IStorageStack> @JvmOverloads constructor
|
|||||||
storedDifferentStacks = 0
|
storedDifferentStacks = 0
|
||||||
// nextID = 0L
|
// nextID = 0L
|
||||||
|
|
||||||
nbt.ifHas("capacity") {
|
driveCapacity = nbt.map("capacity", ::BigInteger) ?: driveCapacity
|
||||||
driveCapacity = BigInteger(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
maxDifferentStacks = nbt.getInt("max_different_stacks")
|
maxDifferentStacks = nbt.getInt("max_different_stacks")
|
||||||
|
|
||||||
for (entry in nbt.getList("items", Tag.TAG_COMPOUND.toInt())) {
|
for (entry in nbt.getList("items", Tag.TAG_COMPOUND.toInt())) {
|
||||||
|
@ -16,12 +16,10 @@ import net.minecraftforge.common.util.LazyOptional
|
|||||||
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.config.ConciseBalanceValues
|
import ru.dbotthepony.mc.otm.config.ConciseBalanceValues
|
||||||
import ru.dbotthepony.mc.otm.config.VerboseBalanceValues
|
import ru.dbotthepony.mc.otm.config.VerboseBalanceValues
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
|
||||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.core.math.defineDecimal
|
import ru.dbotthepony.mc.otm.core.math.defineDecimal
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.map
|
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.mapIf
|
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
|
|
||||||
sealed class BlockEnergyStorageImpl(
|
sealed class BlockEnergyStorageImpl(
|
||||||
@ -142,9 +140,9 @@ sealed class BlockEnergyStorageImpl(
|
|||||||
override fun deserializeNBT(nbt: CompoundTag?) {
|
override fun deserializeNBT(nbt: CompoundTag?) {
|
||||||
if (nbt == null) return
|
if (nbt == null) return
|
||||||
batteryLevel = nbt.map(ENERGY_STORED_KEY, Decimal.Companion::deserializeNBT) ?: Decimal.ZERO
|
batteryLevel = nbt.map(ENERGY_STORED_KEY, Decimal.Companion::deserializeNBT) ?: Decimal.ZERO
|
||||||
maxBatteryLevelStorage = nbt.mapIf(ENERGY_STORED_MAX_KEY, Decimal.Companion::deserializeNBT)
|
maxBatteryLevelStorage = nbt.map(ENERGY_STORED_MAX_KEY, Decimal.Companion::deserializeNBT)
|
||||||
maxInputStorage = nbt.mapIf(MAX_INPUT_KEY, Decimal.Companion::deserializeNBT)
|
maxInputStorage = nbt.map(MAX_INPUT_KEY, Decimal.Companion::deserializeNBT)
|
||||||
maxOutputStorage = nbt.mapIf(MAX_OUTPUT_KEY, Decimal.Companion::deserializeNBT)
|
maxOutputStorage = nbt.map(MAX_OUTPUT_KEY, Decimal.Companion::deserializeNBT)
|
||||||
}
|
}
|
||||||
|
|
||||||
var resolver: LazyOptional<IMatteryEnergyStorage> = LazyOptional.of { this }
|
var resolver: LazyOptional<IMatteryEnergyStorage> = LazyOptional.of { this }
|
||||||
|
@ -5,7 +5,7 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
|||||||
|
|
||||||
object WidgetLocation {
|
object WidgetLocation {
|
||||||
val LARGE_BUTTON = MatteryAtlas(ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets/large_button.png"), 72f, 18f)
|
val LARGE_BUTTON = MatteryAtlas(ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets/large_button.png"), 72f, 18f)
|
||||||
val STORAGE_CONTROLS = MatteryAtlas(ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets/storage_controls.png"), 90f, 18f)
|
val STORAGE_CONTROLS = MatteryAtlas(ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets/storage_controls.png"), 90f, 36f)
|
||||||
val MISC_18 = MatteryAtlas(ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets/misc18.png"), 72f, 72f)
|
val MISC_18 = MatteryAtlas(ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets/misc18.png"), 72f, 72f)
|
||||||
val SLOT_BACKGROUNDS = MatteryAtlas(ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets/slot_backgrounds.png"), 72f, 72f)
|
val SLOT_BACKGROUNDS = MatteryAtlas(ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets/slot_backgrounds.png"), 72f, 72f)
|
||||||
|
|
||||||
|
@ -34,12 +34,14 @@ object Widgets18 {
|
|||||||
val BUTTON_DISABLED_STRETCHABLE = makeButton(buttonGrids)
|
val BUTTON_DISABLED_STRETCHABLE = makeButton(buttonGrids)
|
||||||
val BUTTON_DISABLED = buttonGrids.next()
|
val BUTTON_DISABLED = buttonGrids.next()
|
||||||
|
|
||||||
private val storageGrid = WidgetLocation.STORAGE_CONTROLS.grid(rows = 1, columns = 5)
|
private val storageGrid = WidgetLocation.STORAGE_CONTROLS.grid(rows = 2, columns = 5)
|
||||||
val ARROW_DOWN = storageGrid.next()
|
val ARROW_DOWN = storageGrid.next()
|
||||||
val AZ = storageGrid.next()
|
val ARROW_UP = storageGrid.next()
|
||||||
val COUNT = storageGrid.next()
|
val SORT_DEFAULT = storageGrid.next()
|
||||||
val COLON = storageGrid.next()
|
val SORT_ALPHABET = storageGrid.next()
|
||||||
val C = storageGrid.next()
|
val SORT_COUNT = storageGrid.next()
|
||||||
|
val SORT_MODID = storageGrid.next()
|
||||||
|
val SORT_ID = storageGrid.next()
|
||||||
|
|
||||||
private val miscGrid = WidgetLocation.MISC_18.grid(4, 4)
|
private val miscGrid = WidgetLocation.MISC_18.grid(4, 4)
|
||||||
|
|
||||||
|
@ -8,15 +8,20 @@ import net.minecraft.world.item.ItemStack
|
|||||||
import ru.dbotthepony.mc.otm.capability.matter.IPatternState
|
import ru.dbotthepony.mc.otm.capability.matter.IPatternState
|
||||||
import ru.dbotthepony.mc.otm.capability.matter.IReplicationTask
|
import ru.dbotthepony.mc.otm.capability.matter.IReplicationTask
|
||||||
import ru.dbotthepony.mc.otm.client.render.WidgetLocation
|
import ru.dbotthepony.mc.otm.client.render.WidgetLocation
|
||||||
|
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
||||||
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
|
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.*
|
import ru.dbotthepony.mc.otm.client.screen.panels.*
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.button.ButtonPanel
|
import ru.dbotthepony.mc.otm.client.screen.panels.button.ButtonPanel
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.panels.button.DeviceControls
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeBooleanRectangleButtonPanel
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeEnumRectangleButtonPanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.input.EditBoxPanel
|
import ru.dbotthepony.mc.otm.client.screen.panels.input.EditBoxPanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
|
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.util.DiscreteScrollBarPanel
|
import ru.dbotthepony.mc.otm.client.screen.panels.util.DiscreteScrollBarPanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.util.ScrollBarConstants
|
import ru.dbotthepony.mc.otm.client.screen.panels.util.ScrollBarConstants
|
||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
import ru.dbotthepony.mc.otm.core.math.integerDivisionDown
|
import ru.dbotthepony.mc.otm.core.math.integerDivisionDown
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.ItemSorter
|
||||||
import ru.dbotthepony.mc.otm.menu.matter.MatterPanelMenu
|
import ru.dbotthepony.mc.otm.menu.matter.MatterPanelMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.matter.ReplicationRequestPacket
|
import ru.dbotthepony.mc.otm.menu.matter.ReplicationRequestPacket
|
||||||
import ru.dbotthepony.mc.otm.network.MenuNetworkChannel
|
import ru.dbotthepony.mc.otm.network.MenuNetworkChannel
|
||||||
@ -28,26 +33,50 @@ class MatterPanelScreen(
|
|||||||
inventory: Inventory,
|
inventory: Inventory,
|
||||||
title: Component
|
title: Component
|
||||||
) : MatteryScreen<MatterPanelMenu>(menu, inventory, title) {
|
) : MatteryScreen<MatterPanelMenu>(menu, inventory, title) {
|
||||||
override fun makeMainFrame(): FramePanel<out MatteryScreen<*>> {
|
override fun makeMainFrame(): FramePanel<MatteryScreen<*>> {
|
||||||
var isPatternView = true
|
var isPatternView = true
|
||||||
|
var scrollPatterns = 0
|
||||||
|
var scrollTasks = 0
|
||||||
|
|
||||||
val frame = FramePanel.padded(this, null, GRID_WIDTH * AbstractSlotPanel.SIZE + ScrollBarConstants.WIDTH + 4f, GRID_HEIGHT * AbstractSlotPanel.SIZE, title)
|
val frame = FramePanel.padded(this, null, GRID_WIDTH * AbstractSlotPanel.SIZE + ScrollBarConstants.WIDTH + 4f, GRID_HEIGHT * AbstractSlotPanel.SIZE, title)
|
||||||
|
|
||||||
|
val controls = DeviceControls(this, frame)
|
||||||
|
|
||||||
|
LargeBooleanRectangleButtonPanel(this, controls,
|
||||||
|
prop = menu.isAscendingGS,
|
||||||
|
skinElementActive = Widgets18.ARROW_UP,
|
||||||
|
skinElementInactive = Widgets18.ARROW_DOWN,
|
||||||
|
tooltipActive = TranslatableComponent("otm.gui.sorting.ascending"),
|
||||||
|
tooltipInactive = TranslatableComponent("otm.gui.sorting.descending"),
|
||||||
|
).also {
|
||||||
|
controls.addButton(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
LargeEnumRectangleButtonPanel(this, controls, enum = ItemSorter::class.java, prop = menu.sortingGS, defaultValue = ItemSorter.DEFAULT).also {
|
||||||
|
controls.addButton(it)
|
||||||
|
it.add(ItemSorter.DEFAULT, skinElement = Widgets18.SORT_DEFAULT, tooltip = ItemSorter.DEFAULT.title)
|
||||||
|
it.add(ItemSorter.NAME, skinElement = Widgets18.SORT_ALPHABET, tooltip = ItemSorter.NAME.title)
|
||||||
|
it.add(ItemSorter.ID, skinElement = Widgets18.SORT_ID, tooltip = ItemSorter.ID.title)
|
||||||
|
it.add(ItemSorter.MOD, skinElement = Widgets18.SORT_MODID, tooltip = ItemSorter.MOD.title)
|
||||||
|
}
|
||||||
|
|
||||||
val scrollBar = DiscreteScrollBarPanel(this, frame, {
|
val scrollBar = DiscreteScrollBarPanel(this, frame, {
|
||||||
if (isPatternView) {
|
if (isPatternView) {
|
||||||
integerDivisionDown(menu.patterns.size, GRID_WIDTH)
|
scrollPatterns = integerDivisionDown(menu.patterns.size, GRID_WIDTH)
|
||||||
|
scrollPatterns
|
||||||
} else {
|
} else {
|
||||||
integerDivisionDown(menu.tasks.size, GRID_WIDTH)
|
scrollTasks = integerDivisionDown(menu.tasks.size, GRID_WIDTH)
|
||||||
|
scrollTasks
|
||||||
}
|
}
|
||||||
}, { _, _, _ -> })
|
}, { _, _, _ -> })
|
||||||
|
|
||||||
scrollBar.dock = Dock.RIGHT
|
scrollBar.dock = Dock.RIGHT
|
||||||
|
|
||||||
frame.Tab(onOpen = { isPatternView = true }, activeIcon = PATTERN_LIST_ACTIVE, inactiveIcon = PATTERN_LIST_INACTIVE).also {
|
frame.Tab(onOpen = { isPatternView = true; scrollBar.scroll = scrollPatterns }, activeIcon = PATTERN_LIST_ACTIVE, inactiveIcon = PATTERN_LIST_INACTIVE).also {
|
||||||
it.tooltip = TranslatableComponent("otm.container.matter_panel.patterns")
|
it.tooltip = TranslatableComponent("otm.container.matter_panel.patterns")
|
||||||
}
|
}
|
||||||
|
|
||||||
frame.Tab(onOpen = { isPatternView = false }, activeIcon = TASK_LIST_ACTIVE, inactiveIcon = TASK_LIST_INACTIVE).also {
|
frame.Tab(onOpen = { isPatternView = false; scrollBar.scroll = scrollTasks }, activeIcon = TASK_LIST_ACTIVE, inactiveIcon = TASK_LIST_INACTIVE).also {
|
||||||
it.tooltip = TranslatableComponent("otm.container.matter_panel.tasks")
|
it.tooltip = TranslatableComponent("otm.container.matter_panel.tasks")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,6 +162,8 @@ class MatterPanelScreen(
|
|||||||
private fun openTask(task: IReplicationTask<*>) {
|
private fun openTask(task: IReplicationTask<*>) {
|
||||||
val frame = FramePanel.padded(this, null, 170f, 20f, TranslatableComponent("otm.container.matter_panel.task"))
|
val frame = FramePanel.padded(this, null, 170f, 20f, TranslatableComponent("otm.container.matter_panel.task"))
|
||||||
|
|
||||||
|
frame.closeOnEscape = true
|
||||||
|
|
||||||
object : AbstractSlotPanel<MatterPanelScreen>(this@MatterPanelScreen, frame) {
|
object : AbstractSlotPanel<MatterPanelScreen>(this@MatterPanelScreen, frame) {
|
||||||
init {
|
init {
|
||||||
dock = Dock.LEFT
|
dock = Dock.LEFT
|
||||||
@ -175,6 +206,8 @@ class MatterPanelScreen(
|
|||||||
private fun openPattern(pattern: IPatternState) {
|
private fun openPattern(pattern: IPatternState) {
|
||||||
val frame = FramePanel.padded(this, null, 213f, (ButtonPanel.HEIGHT + 3f) * 4f, TranslatableComponent("otm.container.matter_panel.task"))
|
val frame = FramePanel.padded(this, null, 213f, (ButtonPanel.HEIGHT + 3f) * 4f, TranslatableComponent("otm.container.matter_panel.task"))
|
||||||
|
|
||||||
|
frame.closeOnEscape = true
|
||||||
|
|
||||||
val rowTop = EditablePanel(this, frame, height = ButtonPanel.HEIGHT)
|
val rowTop = EditablePanel(this, frame, height = ButtonPanel.HEIGHT)
|
||||||
val rowInput = EditablePanel(this, frame, height = ButtonPanel.HEIGHT)
|
val rowInput = EditablePanel(this, frame, height = ButtonPanel.HEIGHT)
|
||||||
val rowBottom = EditablePanel(this, frame, height = ButtonPanel.HEIGHT)
|
val rowBottom = EditablePanel(this, frame, height = ButtonPanel.HEIGHT)
|
||||||
|
@ -345,10 +345,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
|||||||
|
|
||||||
fun flash() {
|
fun flash() {
|
||||||
isFlashing = true
|
isFlashing = true
|
||||||
|
popup()
|
||||||
if (parent == null) {
|
|
||||||
popup()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val isFlashFrame: Boolean
|
val isFlashFrame: Boolean
|
||||||
@ -1338,11 +1335,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
|||||||
|
|
||||||
final override fun mouseClicked(x: Double, y: Double, button: Int): Boolean {
|
final override fun mouseClicked(x: Double, y: Double, button: Int): Boolean {
|
||||||
if (!isVisible() || !acceptMouseInput) return false
|
if (!isVisible() || !acceptMouseInput) return false
|
||||||
|
if (flashAnyBlocker()) return true
|
||||||
if (flashAnyBlocker()) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grabMouseInput) return mouseClickedInner(x, y, button)
|
if (grabMouseInput) return mouseClickedInner(x, y, button)
|
||||||
|
|
||||||
for (child in visibleChildrenInternal) {
|
for (child in visibleChildrenInternal) {
|
||||||
@ -1366,9 +1359,11 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
|||||||
if (!isVisible() || !acceptMouseInput) return false
|
if (!isVisible() || !acceptMouseInput) return false
|
||||||
|
|
||||||
if (isGrabbingMouseInput() || withinBounds(x, y)) {
|
if (isGrabbingMouseInput() || withinBounds(x, y)) {
|
||||||
if (acceptMouseInput && parent == null) popup()
|
popup()
|
||||||
return mouseClicked(x, y, button)
|
return mouseClicked(x, y, button)
|
||||||
} else if (withinExtendedBounds(x, y)) {
|
} else if (withinExtendedBounds(x, y)) {
|
||||||
|
popup(false)
|
||||||
|
|
||||||
for (child in visibleChildrenInternal) {
|
for (child in visibleChildrenInternal) {
|
||||||
if (child.mouseClickedChecked(x, y, button)) {
|
if (child.mouseClickedChecked(x, y, button)) {
|
||||||
killFocusForEverythingExcept(child)
|
killFocusForEverythingExcept(child)
|
||||||
@ -1390,11 +1385,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
|||||||
|
|
||||||
final override fun mouseReleased(x: Double, y: Double, button: Int): Boolean {
|
final override fun mouseReleased(x: Double, y: Double, button: Int): Boolean {
|
||||||
if (!isVisible() || !acceptMouseInput) return false
|
if (!isVisible() || !acceptMouseInput) return false
|
||||||
|
if (flashAnyBlocker(false)) return true
|
||||||
if (flashAnyBlocker(false)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grabMouseInput) return mouseReleasedInner(x, y, button)
|
if (grabMouseInput) return mouseReleasedInner(x, y, button)
|
||||||
|
|
||||||
for (child in visibleChildrenInternal) {
|
for (child in visibleChildrenInternal) {
|
||||||
@ -1434,11 +1425,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
|||||||
|
|
||||||
final override fun mouseDragged(x: Double, y: Double, button: Int, xDelta: Double, yDelta: Double): Boolean {
|
final override fun mouseDragged(x: Double, y: Double, button: Int, xDelta: Double, yDelta: Double): Boolean {
|
||||||
if (!isVisible() || !acceptMouseInput) return false
|
if (!isVisible() || !acceptMouseInput) return false
|
||||||
|
if (flashAnyBlocker(false)) return true
|
||||||
if (flashAnyBlocker(false)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grabMouseInput) return mouseDraggedInner(x, y, button, xDelta, yDelta)
|
if (grabMouseInput) return mouseDraggedInner(x, y, button, xDelta, yDelta)
|
||||||
|
|
||||||
for (child in visibleChildrenInternal) {
|
for (child in visibleChildrenInternal) {
|
||||||
@ -1472,7 +1459,6 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected open fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
|
protected open fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -1537,6 +1523,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (focusedAsParent) return keyPressedInternal(key, scancode, mods)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1560,6 +1547,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (focusedAsParent) return keyReleasedInternal(key, scancode, mods)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1641,14 +1629,18 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
|||||||
isRemoved = true
|
isRemoved = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun popup() {
|
fun popup(focus: Boolean = true) {
|
||||||
if (isRemoved) {
|
if (isRemoved) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (screen is MatteryScreen<*>) {
|
if (screen is MatteryScreen<*> && parent == null) {
|
||||||
screen.popup(this as EditablePanel<MatteryScreen<*>>)
|
screen.popup(this as EditablePanel<MatteryScreen<*>>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (focus && !isEverFocused()) {
|
||||||
|
requestFocus()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun asGrid(): FlexGridPanel<*> {
|
fun asGrid(): FlexGridPanel<*> {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ru.dbotthepony.mc.otm.client.screen.panels
|
package ru.dbotthepony.mc.otm.client.screen.panels
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.platform.InputConstants
|
||||||
import com.mojang.blaze3d.systems.RenderSystem
|
import com.mojang.blaze3d.systems.RenderSystem
|
||||||
import com.mojang.blaze3d.vertex.PoseStack
|
import com.mojang.blaze3d.vertex.PoseStack
|
||||||
import net.minecraft.client.gui.narration.NarratableEntry
|
import net.minecraft.client.gui.narration.NarratableEntry
|
||||||
@ -133,6 +134,8 @@ open class FramePanel<out S : Screen>(
|
|||||||
|
|
||||||
protected var dragging = false
|
protected var dragging = false
|
||||||
|
|
||||||
|
var closeOnEscape = false
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setDockPadding(PADDING, if (title != null) PADDING_TOP else PADDING, PADDING, PADDING)
|
setDockPadding(PADDING, if (title != null) PADDING_TOP else PADDING, PADDING, PADDING)
|
||||||
}
|
}
|
||||||
@ -182,6 +185,15 @@ open class FramePanel<out S : Screen>(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun keyPressedInternal(key: Int, scancode: Int, mods: Int): Boolean {
|
||||||
|
if (key == InputConstants.KEY_ESCAPE && closeOnEscape) {
|
||||||
|
remove()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.keyPressedInternal(key, scancode, mods)
|
||||||
|
}
|
||||||
|
|
||||||
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
|
||||||
RECTANGLE.render(stack, width = width, height = height)
|
RECTANGLE.render(stack, width = width, height = height)
|
||||||
|
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package ru.dbotthepony.mc.otm.client.screen.panels.button
|
package ru.dbotthepony.mc.otm.client.screen.panels.button
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack
|
import com.mojang.blaze3d.vertex.PoseStack
|
||||||
|
import net.minecraft.ChatFormatting
|
||||||
import net.minecraft.client.gui.screens.Screen
|
import net.minecraft.client.gui.screens.Screen
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
import ru.dbotthepony.mc.otm.client.minecraft
|
import ru.dbotthepony.mc.otm.client.minecraft
|
||||||
import ru.dbotthepony.mc.otm.client.render.AbstractMatterySprite
|
import ru.dbotthepony.mc.otm.client.render.AbstractMatterySprite
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||||
import ru.dbotthepony.mc.otm.core.GetterSetter
|
import ru.dbotthepony.mc.otm.core.GetterSetter
|
||||||
|
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||||
import ru.dbotthepony.mc.otm.core.value
|
import ru.dbotthepony.mc.otm.core.value
|
||||||
import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback
|
||||||
|
|
||||||
@ -17,9 +20,11 @@ abstract class BooleanRectangleButtonPanel<out S : Screen>(
|
|||||||
width: Float,
|
width: Float,
|
||||||
height: Float,
|
height: Float,
|
||||||
val prop: GetterSetter<Boolean>,
|
val prop: GetterSetter<Boolean>,
|
||||||
val skinElementActive: AbstractMatterySprite? = null,
|
var skinElementActive: AbstractMatterySprite? = null,
|
||||||
val skinElementInactive: AbstractMatterySprite? = null,
|
var skinElementInactive: AbstractMatterySprite? = null,
|
||||||
val onChange: ((newValue: Boolean) -> Unit)? = null,
|
val onChange: ((newValue: Boolean) -> Unit)? = null,
|
||||||
|
var tooltipActive: Component? = null,
|
||||||
|
var tooltipInactive: Component? = null,
|
||||||
) : RectangleButtonPanel<S>(screen, parent, x, y, width, height, null) {
|
) : RectangleButtonPanel<S>(screen, parent, x, y, width, height, null) {
|
||||||
override fun onClick(mouseButton: Int) {
|
override fun onClick(mouseButton: Int) {
|
||||||
val newValue = !prop.value
|
val newValue = !prop.value
|
||||||
@ -27,6 +32,39 @@ abstract class BooleanRectangleButtonPanel<out S : Screen>(
|
|||||||
onChange?.invoke(newValue)
|
onChange?.invoke(newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun innerRenderTooltips(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float): Boolean {
|
||||||
|
if (isHovered) {
|
||||||
|
val tooltipActive = tooltipActive
|
||||||
|
val tooltipInactive = tooltipInactive
|
||||||
|
val tooltipList = tooltipList
|
||||||
|
val tooltip = tooltip
|
||||||
|
|
||||||
|
if (tooltipActive != null || tooltipInactive != null || tooltipList != null || tooltip != null) {
|
||||||
|
val tooltips = ArrayList<Component>(2)
|
||||||
|
|
||||||
|
if (tooltipList != null) {
|
||||||
|
tooltips.addAll(tooltipList)
|
||||||
|
tooltips.add(SPACE)
|
||||||
|
} else if (tooltip != null) {
|
||||||
|
tooltips.add(tooltip)
|
||||||
|
tooltips.add(SPACE)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tooltipActive != null) {
|
||||||
|
tooltips.add(tooltipActive.copy().withStyle(if (prop.get()) ChatFormatting.WHITE else ChatFormatting.GRAY))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tooltipInactive != null) {
|
||||||
|
tooltips.add(tooltipInactive.copy().withStyle(if (!prop.get()) ChatFormatting.WHITE else ChatFormatting.GRAY))
|
||||||
|
}
|
||||||
|
|
||||||
|
screen.renderComponentTooltip(stack, tooltips, mouseX.toInt(), mouseY.toInt(), font)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.innerRenderTooltips(stack, mouseX, mouseY, partialTick)
|
||||||
|
}
|
||||||
|
|
||||||
override var isDisabled: Boolean
|
override var isDisabled: Boolean
|
||||||
get() {
|
get() {
|
||||||
if (prop is IPlayerInputWithFeedback<Boolean>) {
|
if (prop is IPlayerInputWithFeedback<Boolean>) {
|
||||||
@ -46,4 +84,8 @@ abstract class BooleanRectangleButtonPanel<out S : Screen>(
|
|||||||
skinElementInactive?.render(stack, width = width, height = height)
|
skinElementInactive?.render(stack, width = width, height = height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val SPACE = TextComponent("")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
|||||||
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
|
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
|
||||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||||
import ru.dbotthepony.mc.otm.client.minecraft
|
import ru.dbotthepony.mc.otm.client.minecraft
|
||||||
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
|
|
||||||
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
||||||
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
|
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||||
@ -192,61 +191,93 @@ private fun <S : MatteryScreen<*>> makeEnergyConfigPanel(
|
|||||||
return frame
|
return frame
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <S : MatteryScreen<*>> makeDeviceControls(
|
class DeviceControls<out S : MatteryScreen<*>>(
|
||||||
screen: S,
|
screen: S,
|
||||||
parent: FramePanel<S>,
|
parent: FramePanel<S>,
|
||||||
redstone: IPlayerInputWithFeedback<RedstoneSetting>? = null,
|
extra: Iterable<EditablePanel<S>> = listOf(),
|
||||||
itemConfig: ItemHandlerPlayerInput? = null,
|
val redstoneConfig: IPlayerInputWithFeedback<RedstoneSetting>? = null,
|
||||||
energyConfig: EnergyPlayerInput? = null,
|
val itemConfig: ItemHandlerPlayerInput? = null,
|
||||||
): EditablePanel<S> {
|
val energyConfig: EnergyPlayerInput? = null,
|
||||||
val panel = object : EditablePanel<S>(screen, parent, width = LargeEnumRectangleButtonPanel.SIZE, height = 0f, x = parent.width + 3f) {
|
) : EditablePanel<S>(screen, parent, x = parent.width + 3f, height = 0f, width = 0f) {
|
||||||
override fun tickInner() {
|
val itemConfigButton: LargeRectangleButtonPanel<S>?
|
||||||
super.tickInner()
|
val energyConfigButton: LargeRectangleButtonPanel<S>?
|
||||||
x = parent.width + 3f
|
val redstoneControlsButton: LargeEnumRectangleButtonPanel<S, RedstoneSetting>?
|
||||||
y = 0f
|
private var nextY = 0f
|
||||||
|
|
||||||
|
fun <P : EditablePanel<@UnsafeVariance S>> addButton(button: P): P {
|
||||||
|
button.parent = this
|
||||||
|
button.x = 0f
|
||||||
|
button.y = nextY
|
||||||
|
nextY += button.height + 2f
|
||||||
|
height = nextY - 2f
|
||||||
|
width = button.width.coerceAtLeast(width)
|
||||||
|
return button
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
for (button in extra) {
|
||||||
|
addButton(button)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (redstoneConfig != null) {
|
||||||
|
redstoneControlsButton = addButton(makeRedstoneSettingButton(screen, this, control = redstoneConfig))
|
||||||
|
} else {
|
||||||
|
redstoneControlsButton = null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemConfig != null) {
|
||||||
|
itemConfigButton = addButton(object : LargeRectangleButtonPanel<S>(screen, this@DeviceControls, skinElement = Widgets18.ITEMS_CONFIGURATION) {
|
||||||
|
init {
|
||||||
|
tooltip = TranslatableComponent("otm.gui.sides.item_config")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(mouseButton: Int) {
|
||||||
|
if (mouseButton == InputConstants.MOUSE_BUTTON_LEFT) {
|
||||||
|
val frame = makeItemHandlerControlPanel(screen, itemConfig)
|
||||||
|
|
||||||
|
frame.x = absoluteX + width / 2f - frame.width / 2f
|
||||||
|
frame.y = absoluteY + height + 8f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
itemConfigButton = null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (energyConfig != null) {
|
||||||
|
energyConfigButton = addButton(object : LargeRectangleButtonPanel<S>(screen, this@DeviceControls, y = nextY, skinElement = Widgets18.ENERGY_CONFIGURATION) {
|
||||||
|
init {
|
||||||
|
tooltip = TranslatableComponent("otm.gui.sides.energy_config")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(mouseButton: Int) {
|
||||||
|
if (mouseButton == InputConstants.MOUSE_BUTTON_LEFT) {
|
||||||
|
val frame = makeEnergyConfigPanel(screen, energyConfig)
|
||||||
|
|
||||||
|
frame.x = absoluteX + width / 2f - frame.width / 2f
|
||||||
|
frame.y = absoluteY + height + 8f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
energyConfigButton = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var y = 0f
|
override fun tickInner() {
|
||||||
|
super.tickInner()
|
||||||
if (redstone != null) {
|
x = (parent?.width ?: 0f) + 3f
|
||||||
y += makeRedstoneSettingButton(screen, panel, y = y, control = redstone).height + 2f
|
y = 0f
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (itemConfig != null) {
|
|
||||||
y += object : LargeRectangleButtonPanel<S>(screen, panel, y = y, skinElement = Widgets18.ITEMS_CONFIGURATION) {
|
fun <S : MatteryScreen<*>> makeDeviceControls(
|
||||||
init {
|
screen: S,
|
||||||
tooltip = TranslatableComponent("otm.gui.sides.item_config")
|
parent: FramePanel<S>,
|
||||||
}
|
extra: Iterable<EditablePanel<S>> = listOf(),
|
||||||
|
redstone: IPlayerInputWithFeedback<RedstoneSetting>? = null,
|
||||||
override fun onClick(mouseButton: Int) {
|
itemConfig: ItemHandlerPlayerInput? = null,
|
||||||
if (mouseButton == InputConstants.MOUSE_BUTTON_LEFT) {
|
energyConfig: EnergyPlayerInput? = null,
|
||||||
val frame = makeItemHandlerControlPanel(screen, itemConfig)
|
): DeviceControls<S> {
|
||||||
|
return DeviceControls(screen, parent, extra = extra, redstoneConfig = redstone, itemConfig = itemConfig, energyConfig = energyConfig)
|
||||||
frame.x = absoluteX + width / 2f - frame.width / 2f
|
|
||||||
frame.y = absoluteY + height + 8f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.height + 2f
|
|
||||||
}
|
|
||||||
|
|
||||||
if (energyConfig != null) {
|
|
||||||
y += object : LargeRectangleButtonPanel<S>(screen, panel, y = y, skinElement = Widgets18.ENERGY_CONFIGURATION) {
|
|
||||||
init {
|
|
||||||
tooltip = TranslatableComponent("otm.gui.sides.energy_config")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onClick(mouseButton: Int) {
|
|
||||||
if (mouseButton == InputConstants.MOUSE_BUTTON_LEFT) {
|
|
||||||
val frame = makeEnergyConfigPanel(screen, energyConfig)
|
|
||||||
|
|
||||||
frame.x = absoluteX + width / 2f - frame.width / 2f
|
|
||||||
frame.y = absoluteY + height + 8f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.height + 2f
|
|
||||||
}
|
|
||||||
|
|
||||||
panel.height = (y - 2f).coerceAtLeast(0f)
|
|
||||||
return panel
|
|
||||||
}
|
}
|
||||||
|
@ -158,12 +158,14 @@ abstract class EnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val listing = ArrayList<Component>()
|
val listing = ArrayList<Component>()
|
||||||
|
val tooltipList = tooltipList
|
||||||
|
val tooltip = tooltip
|
||||||
|
|
||||||
if (tooltipList != null) {
|
if (tooltipList != null) {
|
||||||
listing.addAll(tooltipList!!)
|
listing.addAll(tooltipList)
|
||||||
listing.add(SPACE)
|
listing.add(SPACE)
|
||||||
} else if (tooltip != null) {
|
} else if (tooltip != null) {
|
||||||
listing.add(tooltip!!)
|
listing.add(tooltip)
|
||||||
listing.add(SPACE)
|
listing.add(SPACE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package ru.dbotthepony.mc.otm.client.screen.panels.button
|
package ru.dbotthepony.mc.otm.client.screen.panels.button
|
||||||
|
|
||||||
import net.minecraft.client.gui.screens.Screen
|
import net.minecraft.client.gui.screens.Screen
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
import ru.dbotthepony.mc.otm.client.minecraft
|
import ru.dbotthepony.mc.otm.client.minecraft
|
||||||
import ru.dbotthepony.mc.otm.client.render.AbstractMatterySprite
|
import ru.dbotthepony.mc.otm.client.render.AbstractMatterySprite
|
||||||
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
||||||
@ -19,7 +20,9 @@ open class LargeBooleanRectangleButtonPanel<out S : Screen>(
|
|||||||
skinElementActive: AbstractMatterySprite? = null,
|
skinElementActive: AbstractMatterySprite? = null,
|
||||||
skinElementInactive: AbstractMatterySprite? = null,
|
skinElementInactive: AbstractMatterySprite? = null,
|
||||||
onChange: ((newValue: Boolean) -> Unit)? = null,
|
onChange: ((newValue: Boolean) -> Unit)? = null,
|
||||||
) : BooleanRectangleButtonPanel<S>(screen, parent, x, y, width, height, prop, skinElementActive, skinElementInactive, onChange) {
|
tooltipActive: Component? = null,
|
||||||
|
tooltipInactive: Component? = null,
|
||||||
|
) : BooleanRectangleButtonPanel<S>(screen, parent, x, y, width, height, prop, skinElementActive, skinElementInactive, onChange, tooltipActive, tooltipInactive) {
|
||||||
final override val IDLE = Widgets18.BUTTON_IDLE
|
final override val IDLE = Widgets18.BUTTON_IDLE
|
||||||
final override val HOVERED = Widgets18.BUTTON_HOVERED
|
final override val HOVERED = Widgets18.BUTTON_HOVERED
|
||||||
final override val PRESSED = Widgets18.BUTTON_PRESSED
|
final override val PRESSED = Widgets18.BUTTON_PRESSED
|
||||||
|
@ -11,7 +11,7 @@ import net.minecraftforge.common.util.INBTSerializable
|
|||||||
import net.minecraftforge.network.NetworkEvent
|
import net.minecraftforge.network.NetworkEvent
|
||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
import ru.dbotthepony.mc.otm.client.minecraft
|
import ru.dbotthepony.mc.otm.client.minecraft
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.ifHas
|
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
import ru.dbotthepony.mc.otm.network.MatteryPacket
|
import ru.dbotthepony.mc.otm.network.MatteryPacket
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
@ -266,7 +266,7 @@ class ItemFilter(
|
|||||||
if (nbt == null)
|
if (nbt == null)
|
||||||
return
|
return
|
||||||
|
|
||||||
nbt.ifHas("items", ListTag::class.java) {
|
nbt.map("items") { it: ListTag ->
|
||||||
for ((i, value) in it.withIndex()) {
|
for ((i, value) in it.withIndex()) {
|
||||||
if (value is CompoundTag) {
|
if (value is CompoundTag) {
|
||||||
filter[i] = ItemStack.of(value)
|
filter[i] = ItemStack.of(value)
|
||||||
|
@ -10,7 +10,7 @@ import kotlin.jvm.JvmOverloads
|
|||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity
|
import net.minecraft.world.level.block.entity.BlockEntity
|
||||||
import net.minecraftforge.common.util.INBTSerializable
|
import net.minecraftforge.common.util.INBTSerializable
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.ifHas
|
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ open class MatteryContainer(val watcher: Runnable, private val size: Int) : Cont
|
|||||||
}
|
}
|
||||||
|
|
||||||
// нам не интересен размер
|
// нам не интересен размер
|
||||||
tag.ifHas("items", ListTag::class.java) {
|
tag.map("items") { it: ListTag ->
|
||||||
for (i in 0 until it.size.coerceAtMost(size)) {
|
for (i in 0 until it.size.coerceAtMost(size)) {
|
||||||
slots[i] = ItemStack.of(it[i] as CompoundTag)
|
slots[i] = ItemStack.of(it[i] as CompoundTag)
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,6 @@ import net.minecraftforge.registries.IForgeRegistry
|
|||||||
import ru.dbotthepony.mc.otm.core.math.Vector
|
import ru.dbotthepony.mc.otm.core.math.Vector
|
||||||
import ru.dbotthepony.mc.otm.core.util.readInt
|
import ru.dbotthepony.mc.otm.core.util.readInt
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.OutputStream
|
|
||||||
import java.lang.ref.Reference
|
import java.lang.ref.Reference
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.util.Arrays
|
import java.util.Arrays
|
||||||
@ -313,3 +312,72 @@ fun <T> Stream<T>.asIterable(): Iterable<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Kotlin type safety:
|
||||||
|
// since Java generics are invariant,
|
||||||
|
// and can not distinguish between null and non-null type parameters
|
||||||
|
// we need to tell compiler that Comparator.nullsFirst actually has next signature:
|
||||||
|
// fun <T> Comparator.nullsFirst(original: Comparator<in T>): Comparator<in T?>
|
||||||
|
fun <T> Comparator<in T>.nullsFirst(): Comparator<T?> {
|
||||||
|
return Comparator.nullsFirst(this as Comparator<in T?>)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> Comparator<in T>.nullsLast(): Comparator<T?> {
|
||||||
|
return Comparator.nullsLast(this as Comparator<in T?>)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns applicable index to put [element] into [List] determined by [comparator], optionally specifying ranges as [fromIndex] and [toIndex]
|
||||||
|
*
|
||||||
|
* If [List] is not sorted, result of this function is undefined
|
||||||
|
*/
|
||||||
|
fun <E> List<E>.searchInsertionIndex(element: E, comparator: Comparator<E>, fromIndex: Int = 0, toIndex: Int = size): Int {
|
||||||
|
require(toIndex >= fromIndex) { "Invalid range: to $toIndex >= from $fromIndex" }
|
||||||
|
require(fromIndex >= 0) { "Invalid from index: $fromIndex" }
|
||||||
|
require(toIndex >= 0) { "Invalid to index: $toIndex" }
|
||||||
|
require(fromIndex <= size) { "Invalid from index: $fromIndex (list size $size)" }
|
||||||
|
require(toIndex <= size) { "Invalid to index: $toIndex (list size $size)" }
|
||||||
|
|
||||||
|
if (fromIndex == size || fromIndex == toIndex || comparator.compare(element, this[fromIndex]) <= 0) {
|
||||||
|
return fromIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toIndex - fromIndex <= 10) {
|
||||||
|
for (i in fromIndex + 1 until toIndex) {
|
||||||
|
val compare = comparator.compare(element, this[i])
|
||||||
|
|
||||||
|
if (compare <= 0) {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return size
|
||||||
|
} else {
|
||||||
|
var lower = fromIndex
|
||||||
|
var upper = toIndex - 1
|
||||||
|
|
||||||
|
while (upper - lower >= 10) {
|
||||||
|
val middle = (upper + lower) / 2
|
||||||
|
val compare = comparator.compare(element, this[middle])
|
||||||
|
|
||||||
|
if (compare == 0) {
|
||||||
|
return middle
|
||||||
|
} else if (compare < 0) {
|
||||||
|
upper = middle
|
||||||
|
} else {
|
||||||
|
lower = middle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return searchInsertionIndex(element, comparator, lower, upper + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts [element] into [MutableList] at index determined by [comparator]
|
||||||
|
*
|
||||||
|
* If [MutableList] is not sorted, result of this function is undefined
|
||||||
|
*/
|
||||||
|
fun <E> MutableList<E>.addSorted(element: E, comparator: Comparator<E>) {
|
||||||
|
add(searchInsertionIndex(element, comparator), element)
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@ import net.minecraft.nbt.LongArrayTag
|
|||||||
import net.minecraft.nbt.LongTag
|
import net.minecraft.nbt.LongTag
|
||||||
import net.minecraft.nbt.NbtAccounter
|
import net.minecraft.nbt.NbtAccounter
|
||||||
import net.minecraft.nbt.NbtUtils
|
import net.minecraft.nbt.NbtUtils
|
||||||
|
import net.minecraft.nbt.NumericTag
|
||||||
import net.minecraft.nbt.ShortTag
|
import net.minecraft.nbt.ShortTag
|
||||||
import net.minecraft.nbt.StringTag
|
import net.minecraft.nbt.StringTag
|
||||||
import net.minecraft.nbt.Tag
|
import net.minecraft.nbt.Tag
|
||||||
@ -58,57 +59,13 @@ inline fun <R, reified T : Tag?> CompoundTag.map(key: String, consumer: (T) -> R
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <R, reified T : Tag> CompoundTag.mapIf(key: String, consumer: (T) -> R): R? {
|
fun <T> CompoundTag.mapString(index: String, mapper: (String) -> T, orElse: T): T {
|
||||||
val tag = get(key)
|
val tag = this[index] as? StringTag ?: return orElse
|
||||||
|
return mapper.invoke(tag.asString)
|
||||||
if (tag is T) {
|
|
||||||
return consumer(tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified R : Enum<R>> CompoundTag.getEnum(key: String, ifNothing: () -> R = { R::class.java.enumConstants[0] }): R {
|
|
||||||
val tag = get(key)
|
|
||||||
|
|
||||||
if (tag is StringTag) {
|
|
||||||
val str = tag.asString
|
|
||||||
return R::class.java.enumConstants.first { it.name == str }
|
|
||||||
}
|
|
||||||
|
|
||||||
return ifNothing.invoke()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CompoundTag.getItemStack(key: String): ItemStack = map(key, ItemStack::of) ?: ItemStack.EMPTY
|
fun CompoundTag.getItemStack(key: String): ItemStack = map(key, ItemStack::of) ?: ItemStack.EMPTY
|
||||||
|
|
||||||
inline fun CompoundTag.ifHas(s: String, consumer: (Tag) -> Unit) {
|
|
||||||
val tag = get(s)
|
|
||||||
|
|
||||||
if (tag != null) {
|
|
||||||
consumer(tag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun CompoundTag.ifHas(s: String, type: Byte, consumer: (Tag) -> Unit) {
|
|
||||||
val tag = get(s)
|
|
||||||
|
|
||||||
if (tag != null && tag.id == type) {
|
|
||||||
consumer(tag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified T : Tag> CompoundTag.ifHas(s: String, type: Class<T>, consumer: (T) -> Unit) {
|
|
||||||
val tag = get(s)
|
|
||||||
|
|
||||||
if (tag != null && tag::class.java === type) {
|
|
||||||
consumer(tag as T)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun CompoundTag.getList(key: String): ListTag {
|
|
||||||
return this[key] as? ListTag ?: ListTag()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("unchecked_cast") // type is checked inside getList
|
@Suppress("unchecked_cast") // type is checked inside getList
|
||||||
fun CompoundTag.getByteList(key: String): MutableList<ByteTag> = getList(key, Tag.TAG_BYTE.toInt()) as MutableList<ByteTag>
|
fun CompoundTag.getByteList(key: String): MutableList<ByteTag> = getList(key, Tag.TAG_BYTE.toInt()) as MutableList<ByteTag>
|
||||||
@Suppress("unchecked_cast") // type is checked inside getList
|
@Suppress("unchecked_cast") // type is checked inside getList
|
||||||
@ -153,3 +110,7 @@ fun CompoundTag.getJson(key: String, sizeLimit: NbtAccounter = NbtAccounter.UNLI
|
|||||||
|
|
||||||
return FastByteArrayInputStream(bytes).readJson(sizeLimit)
|
return FastByteArrayInputStream(bytes).readJson(sizeLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun CompoundTag.getBoolean(index: String, orElse: Boolean): Boolean {
|
||||||
|
return (this[index] as? NumericTag)?.asInt?.let { it > 0 } ?: orElse
|
||||||
|
}
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.core.util
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.objects.Reference2IntFunction
|
||||||
|
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
|
import net.minecraft.world.item.Item
|
||||||
|
import net.minecraftforge.common.CreativeModeTabRegistry
|
||||||
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
|
import ru.dbotthepony.mc.otm.core.nullsFirst
|
||||||
|
import ru.dbotthepony.mc.otm.core.nullsLast
|
||||||
|
import ru.dbotthepony.mc.otm.core.registryName
|
||||||
|
|
||||||
|
object CreativeMenuComparator : Comparator<Item> {
|
||||||
|
override fun compare(o1: Item, o2: Item): Int {
|
||||||
|
rebuild()
|
||||||
|
return item2index.getInt(o1).compareTo(item2index.getInt(o2))
|
||||||
|
}
|
||||||
|
|
||||||
|
private val item2index = Reference2IntOpenHashMap<Item>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
item2index.defaultReturnValue(Int.MAX_VALUE)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rebuild() {
|
||||||
|
if (item2index.isEmpty()) {
|
||||||
|
var i = 0
|
||||||
|
|
||||||
|
for (tab in CreativeModeTabRegistry.getSortedCreativeModeTabs()) {
|
||||||
|
for (item in tab.displayItems) {
|
||||||
|
item2index.computeIfAbsent(item.item, Reference2IntFunction { i++ })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun invalidate() {
|
||||||
|
item2index.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
val NullsFirst = nullsFirst()
|
||||||
|
val NullsLast = nullsLast()
|
||||||
|
}
|
||||||
|
|
||||||
|
object ItemLocalizedNameComparator : Comparator<Item> {
|
||||||
|
override fun compare(o1: Item, o2: Item): Int {
|
||||||
|
return o1.description.string.compareTo(o2.description.string)
|
||||||
|
}
|
||||||
|
|
||||||
|
val NullsFirst = nullsFirst()
|
||||||
|
val NullsLast = nullsLast()
|
||||||
|
}
|
||||||
|
|
||||||
|
object ItemModComparator : Comparator<Item> {
|
||||||
|
override fun compare(o1: Item, o2: Item): Int {
|
||||||
|
val a = o1.registryName?.namespace ?: return 0
|
||||||
|
val b = o2.registryName?.namespace ?: return 0
|
||||||
|
return a.compareTo(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
val NullsFirst = nullsFirst()
|
||||||
|
val NullsLast = nullsLast()
|
||||||
|
}
|
||||||
|
|
||||||
|
object ItemIDComparator : Comparator<Item> {
|
||||||
|
override fun compare(o1: Item, o2: Item): Int {
|
||||||
|
val a = o1.registryName ?: return 0
|
||||||
|
val b = o2.registryName ?: return 0
|
||||||
|
return a.compareTo(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
val NullsFirst = nullsFirst()
|
||||||
|
val NullsLast = nullsLast()
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ItemSorter(val comparator: Comparator<Item?>, private val sTitle: Component) {
|
||||||
|
DEFAULT(CreativeMenuComparator.NullsFirst, TranslatableComponent("otm.gui.sorting.default")),
|
||||||
|
NAME(ItemLocalizedNameComparator.NullsFirst.thenComparing(CreativeMenuComparator.NullsFirst), TranslatableComponent("otm.gui.sorting.name")),
|
||||||
|
ID(ItemIDComparator.NullsFirst.thenComparing(CreativeMenuComparator.NullsFirst), TranslatableComponent("otm.gui.sorting.id")),
|
||||||
|
MOD(ItemModComparator.NullsFirst.thenComparing(CreativeMenuComparator.NullsFirst), TranslatableComponent("otm.gui.sorting.modid"));
|
||||||
|
|
||||||
|
val title: Component get() = sTitle.copy()
|
||||||
|
}
|
@ -16,7 +16,7 @@ import net.minecraft.world.level.Level
|
|||||||
import net.minecraftforge.common.capabilities.Capability
|
import net.minecraftforge.common.capabilities.Capability
|
||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
import ru.dbotthepony.mc.otm.capability.matter.*
|
import ru.dbotthepony.mc.otm.capability.matter.*
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.ifHas
|
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
|
|
||||||
@ -99,11 +99,9 @@ class PatternStorageItem : Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override val storedPatterns: Int get() {
|
override val storedPatterns: Int get() {
|
||||||
stack.tag?.ifHas("otm_patterns", ListTag::class.java) {
|
return stack.tag?.map("otm_patterns") { it: ListTag ->
|
||||||
return it.size
|
it.size
|
||||||
}
|
} ?: 0
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||||
@ -111,11 +109,9 @@ class PatternStorageItem : Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override val patterns: Stream<out IPatternState> get() {
|
override val patterns: Stream<out IPatternState> get() {
|
||||||
stack.tag?.ifHas("otm_patterns", ListTag::class.java) {
|
return stack.tag?.map("otm_patterns") { it: ListTag ->
|
||||||
return it.stream().map { PatternState.deserializeNBT(it) }.filter { it != null } as Stream<out IPatternState>
|
it.stream().map { PatternState.deserializeNBT(it) }.filter { it != null } as Stream<out IPatternState>
|
||||||
}
|
} ?: Stream.empty()
|
||||||
|
|
||||||
return Stream.empty()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun insertPattern(
|
override fun insertPattern(
|
||||||
|
@ -21,7 +21,7 @@ import net.minecraftforge.event.entity.player.EntityItemPickupEvent
|
|||||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||||
import ru.dbotthepony.mc.otm.capability.drive.DrivePool
|
import ru.dbotthepony.mc.otm.capability.drive.DrivePool
|
||||||
import ru.dbotthepony.mc.otm.container.ItemFilter
|
import ru.dbotthepony.mc.otm.container.ItemFilter
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.ifHas
|
import ru.dbotthepony.mc.otm.core.nbt.map
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ class PortableCondensationDriveItem(capacity: Int) :
|
|||||||
fun getFilterSettings(drive: ItemStack): ItemFilter {
|
fun getFilterSettings(drive: ItemStack): ItemFilter {
|
||||||
val filter = ItemFilter(MAX_FILTERS)
|
val filter = ItemFilter(MAX_FILTERS)
|
||||||
filter.isWhitelist = true
|
filter.isWhitelist = true
|
||||||
drive.tag?.ifHas(FILTER_PATH, CompoundTag::class.java, filter::deserializeNBT)
|
drive.tag?.map(FILTER_PATH, filter::deserializeNBT)
|
||||||
return filter
|
return filter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,21 +4,26 @@ import net.minecraft.network.FriendlyByteBuf
|
|||||||
import net.minecraft.server.level.ServerPlayer
|
import net.minecraft.server.level.ServerPlayer
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.inventory.Slot
|
|
||||||
import net.minecraftforge.network.NetworkEvent
|
import net.minecraftforge.network.NetworkEvent
|
||||||
import net.minecraftforge.network.PacketDistributor
|
import net.minecraftforge.network.PacketDistributor
|
||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
import ru.dbotthepony.mc.otm.block.entity.matter.MatterPanelBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.matter.MatterPanelBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.capability.matter.*
|
import ru.dbotthepony.mc.otm.capability.matter.*
|
||||||
import ru.dbotthepony.mc.otm.client.minecraft
|
import ru.dbotthepony.mc.otm.client.minecraft
|
||||||
|
import ru.dbotthepony.mc.otm.core.GetterSetter
|
||||||
|
import ru.dbotthepony.mc.otm.core.addSorted
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.BooleanValueCodec
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.EnumValueCodec
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.ItemSorter
|
||||||
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphListener
|
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphListener
|
||||||
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
|
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
import ru.dbotthepony.mc.otm.network.*
|
import ru.dbotthepony.mc.otm.network.*
|
||||||
import ru.dbotthepony.mc.otm.registry.MMenus
|
import ru.dbotthepony.mc.otm.registry.MMenus
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.function.Consumer
|
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
|
import kotlin.Comparator
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class CancelTaskPacket(val id: UUID) : MatteryPacket {
|
class CancelTaskPacket(val id: UUID) : MatteryPacket {
|
||||||
override fun write(buff: FriendlyByteBuf) {
|
override fun write(buff: FriendlyByteBuf) {
|
||||||
@ -146,66 +151,70 @@ class MatterPanelMenu @JvmOverloads constructor(
|
|||||||
sendNetwork(TasksChangePacket(false, listOf(task)))
|
sendNetwork(TasksChangePacket(false, listOf(task)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// client code
|
val sorting: ItemSorter by mSynchronizer.ComputedField(
|
||||||
|
getter = { tile?.getPlayerSettings(ply)?.sorter ?: ItemSorter.DEFAULT },
|
||||||
|
codec = EnumValueCodec(ItemSorter::class.java),
|
||||||
|
observer = {
|
||||||
|
patterns.sortWith(actualComparator)
|
||||||
|
tasks.sortWith(actualTaskComparator)
|
||||||
|
})
|
||||||
|
|
||||||
|
val isAscending: Boolean by mSynchronizer.ComputedField(
|
||||||
|
getter = { tile?.getPlayerSettings(ply)?.ascending ?: true },
|
||||||
|
codec = BooleanValueCodec,
|
||||||
|
observer = {
|
||||||
|
patterns.sortWith(actualComparator)
|
||||||
|
tasks.sortWith(actualTaskComparator)
|
||||||
|
})
|
||||||
|
|
||||||
|
val changeIsAscending = booleanInput(allowSpectators = true) { tile?.getPlayerSettings(ply)?.ascending = it }
|
||||||
|
val changeSorting = PlayerInput(EnumValueCodec(ItemSorter::class.java), allowSpectators = true) { tile?.getPlayerSettings(ply)?.sorter = it }
|
||||||
|
|
||||||
|
val sortingGS = GetterSetter.of(::sorting, changeSorting::input)
|
||||||
|
val isAscendingGS = GetterSetter.of(::isAscending, changeIsAscending::input)
|
||||||
|
|
||||||
|
private val actualComparator = Comparator<IPatternState> { o1, o2 -> sorting.comparator.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) }
|
||||||
|
private val actualTaskComparator = Comparator<IReplicationTask<*>> { o1, o2 -> sorting.comparator.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) }
|
||||||
|
|
||||||
val patterns = ArrayList<IPatternState>()
|
val patterns = ArrayList<IPatternState>()
|
||||||
val tasks = ArrayList<IReplicationTask<*>>()
|
val tasks = ArrayList<IReplicationTask<*>>()
|
||||||
var changeset = 0
|
|
||||||
|
|
||||||
fun networkPatternsUpdated(patterns: Collection<IPatternState>) {
|
fun networkPatternsUpdated(patterns: Collection<IPatternState>) {
|
||||||
changeset++
|
|
||||||
|
|
||||||
for (pattern in patterns) {
|
for (pattern in patterns) {
|
||||||
val index = this.patterns.indexOfFirst(pattern::matchId)
|
val index = this.patterns.indexOfFirst(pattern::matchId)
|
||||||
|
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
this.patterns[index] = pattern
|
this.patterns[index] = pattern
|
||||||
} else {
|
} else {
|
||||||
this.patterns.add(pattern)
|
this.patterns.addSorted(pattern, actualComparator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun networkPatternsRemoved(patterns: Collection<IPatternState>) {
|
fun networkPatternsRemoved(patterns: Collection<IPatternState>) {
|
||||||
changeset++
|
|
||||||
|
|
||||||
for (pattern in patterns) {
|
for (pattern in patterns) {
|
||||||
this.patterns.remove(pattern)
|
this.patterns.remove(pattern)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun networkTasksUpdated(tasks: Collection<IReplicationTask<*>>) {
|
fun networkTasksUpdated(tasks: Collection<IReplicationTask<*>>) {
|
||||||
changeset++
|
|
||||||
|
|
||||||
for (task in tasks) {
|
for (task in tasks) {
|
||||||
val index = this.tasks.indexOfFirst(task::matchId)
|
val index = this.tasks.indexOfFirst(task::matchId)
|
||||||
|
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
this.tasks[index] = task
|
this.tasks[index] = task
|
||||||
} else {
|
} else {
|
||||||
this.tasks.add(task)
|
this.tasks.addSorted(task, actualTaskComparator)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateWatcher?.accept(task)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun networkTasksRemoved(tasks: Collection<IReplicationTask<*>>) {
|
fun networkTasksRemoved(tasks: Collection<IReplicationTask<*>>) {
|
||||||
changeset++
|
|
||||||
|
|
||||||
for (task in tasks) {
|
for (task in tasks) {
|
||||||
this.tasks.remove(task)
|
this.tasks.remove(task)
|
||||||
deleteWatcher?.accept(task)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var deleteWatcher: Consumer<IReplicationTask<*>>? = null
|
|
||||||
private var updateWatcher: Consumer<IReplicationTask<*>>? = null
|
|
||||||
|
|
||||||
fun networkTaskWatcher(updateWatcher: Consumer<IReplicationTask<*>>, deleteWatcher: Consumer<IReplicationTask<*>>) {
|
|
||||||
this.deleteWatcher = deleteWatcher
|
|
||||||
this.updateWatcher = updateWatcher
|
|
||||||
}
|
|
||||||
|
|
||||||
// server code
|
// server code
|
||||||
fun requestReplication(ply: ServerPlayer, id: UUID, count: Int) {
|
fun requestReplication(ply: ServerPlayer, id: UUID, count: Int) {
|
||||||
if (ply.isSpectator) {
|
if (ply.isSpectator) {
|
||||||
|
@ -688,6 +688,7 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa
|
|||||||
private val getter: () -> V,
|
private val getter: () -> V,
|
||||||
private val codec: IStreamCodec<V>,
|
private val codec: IStreamCodec<V>,
|
||||||
name: String = nextFieldName(),
|
name: String = nextFieldName(),
|
||||||
|
private val observer: (new: V) -> Unit = {}
|
||||||
) : AbstractField<V>(name), IField<V> {
|
) : AbstractField<V>(name), IField<V> {
|
||||||
private var remote: V? = null
|
private var remote: V? = null
|
||||||
private var clientValue: V? = null
|
private var clientValue: V? = null
|
||||||
@ -726,7 +727,9 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun read(stream: DataInputStream) {
|
override fun read(stream: DataInputStream) {
|
||||||
clientValue = codec.read(stream)
|
val newValue = codec.read(stream)
|
||||||
|
clientValue = newValue
|
||||||
|
observer.invoke(newValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import net.minecraft.world.item.CreativeModeTab
|
|||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraftforge.event.CreativeModeTabEvent
|
import net.minecraftforge.event.CreativeModeTabEvent
|
||||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.CreativeMenuComparator
|
||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
import ru.dbotthepony.mc.otm.core.util.WriteOnce
|
import ru.dbotthepony.mc.otm.core.util.WriteOnce
|
||||||
import ru.dbotthepony.mc.otm.registry.MItems.BATTERY_CREATIVE
|
import ru.dbotthepony.mc.otm.registry.MItems.BATTERY_CREATIVE
|
||||||
@ -16,6 +17,8 @@ object MCreativeTabs {
|
|||||||
private set
|
private set
|
||||||
|
|
||||||
fun register(event: CreativeModeTabEvent.Register) {
|
fun register(event: CreativeModeTabEvent.Register) {
|
||||||
|
CreativeMenuComparator.invalidate()
|
||||||
|
|
||||||
MAIN = event.registerCreativeModeTab(ResourceLocation(OverdriveThatMatters.MOD_ID, "main")) {
|
MAIN = event.registerCreativeModeTab(ResourceLocation(OverdriveThatMatters.MOD_ID, "main")) {
|
||||||
it.icon { ItemStack(BATTERY_CREATIVE, 1) }
|
it.icon { ItemStack(BATTERY_CREATIVE, 1) }
|
||||||
it.title(TranslatableComponent("itemGroup.otm"))
|
it.title(TranslatableComponent("itemGroup.otm"))
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 711 B After Width: | Height: | Size: 803 B |
Binary file not shown.
@ -0,0 +1,34 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.tests
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntComparators
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import ru.dbotthepony.mc.otm.core.addSorted
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
|
object ComparatorTests {
|
||||||
|
@Test
|
||||||
|
@DisplayName("Comparator tests")
|
||||||
|
fun test() {
|
||||||
|
val sortedList = mutableListOf(1, 4, 6)
|
||||||
|
sortedList.addSorted(2, IntComparators.NATURAL_COMPARATOR)
|
||||||
|
sortedList.addSorted(3, IntComparators.NATURAL_COMPARATOR)
|
||||||
|
sortedList.addSorted(7, IntComparators.NATURAL_COMPARATOR)
|
||||||
|
sortedList.addSorted(-1, IntComparators.NATURAL_COMPARATOR)
|
||||||
|
|
||||||
|
assertEquals(mutableListOf(-1, 1, 2, 3, 4, 6, 7), sortedList)
|
||||||
|
|
||||||
|
val rand = Random()
|
||||||
|
val sorted2 = ArrayList<Int>()
|
||||||
|
|
||||||
|
for (i in 0 .. 100) {
|
||||||
|
sorted2.addSorted(rand.nextInt(-100, 100), IntComparators.NATURAL_COMPARATOR)
|
||||||
|
}
|
||||||
|
|
||||||
|
val sorted22 = ArrayList(sorted2)
|
||||||
|
sorted22.sort()
|
||||||
|
|
||||||
|
assertEquals(sorted22, sorted2)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user