Wasn't the best idea to write immutable list helper with uppercase I
This commit is contained in:
parent
dd4be8b961
commit
c671d2e13d
@ -14,7 +14,7 @@ import ru.dbotthepony.mc.otm.capability.FlowDirection
|
|||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage
|
import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage
|
||||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||||
import ru.dbotthepony.mc.otm.core.ImmutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||||
import ru.dbotthepony.mc.otm.graph.Graph6Node
|
import ru.dbotthepony.mc.otm.graph.Graph6Node
|
||||||
@ -130,7 +130,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
|
|||||||
}
|
}
|
||||||
}.also(::addDroppableContainer)
|
}.also(::addDroppableContainer)
|
||||||
|
|
||||||
val capacitorStatus = ImmutableList(BatteryBankBlockEntity.CAPACITY) {
|
val capacitorStatus = immutableList(BatteryBankBlockEntity.CAPACITY) {
|
||||||
synchronizer.bool(false, name = "capacitor$it")
|
synchronizer.bool(false, name = "capacitor$it")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import ru.dbotthepony.mc.otm.capability.maxEnergyStoredMattery
|
|||||||
import ru.dbotthepony.mc.otm.capability.receiveEnergy
|
import ru.dbotthepony.mc.otm.capability.receiveEnergy
|
||||||
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.ImmutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.core.getValue
|
import ru.dbotthepony.mc.otm.core.getValue
|
||||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
@ -38,7 +38,7 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
|
|||||||
}
|
}
|
||||||
}.also(::addDroppableContainer)
|
}.also(::addDroppableContainer)
|
||||||
|
|
||||||
val batteryStatus = ImmutableList(CAPACITY) {
|
val batteryStatus = immutableList(CAPACITY) {
|
||||||
synchronizer.bool(false, name = "battery$it")
|
synchronizer.bool(false, name = "battery$it")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import ru.dbotthepony.mc.otm.client.render.AbstractMatterySprite
|
|||||||
import ru.dbotthepony.mc.otm.client.render.DynamicBufferSource
|
import ru.dbotthepony.mc.otm.client.render.DynamicBufferSource
|
||||||
import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel
|
import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel
|
||||||
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
|
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
|
||||||
import ru.dbotthepony.mc.otm.core.ImmutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.core.get
|
import ru.dbotthepony.mc.otm.core.get
|
||||||
import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
|
import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
|
||||||
import ru.dbotthepony.mc.otm.core.math.facingOne
|
import ru.dbotthepony.mc.otm.core.math.facingOne
|
||||||
@ -117,7 +117,7 @@ abstract class BankRenderer<T : MatteryDeviceBlockEntity>(private val context: B
|
|||||||
|
|
||||||
class BatteryBankRenderer(context: BlockEntityRendererProvider.Context) : BankRenderer<BatteryBankBlockEntity>(context) {
|
class BatteryBankRenderer(context: BlockEntityRendererProvider.Context) : BankRenderer<BatteryBankBlockEntity>(context) {
|
||||||
override val models: List<BakedModel> by lazy {
|
override val models: List<BakedModel> by lazy {
|
||||||
ImmutableList(12) {
|
immutableList(12) {
|
||||||
minecraft.modelManager.modelBakery.bakedTopLevelModels[ResourceLocation(OverdriveThatMatters.MOD_ID, "block/battery/battery$it")]!!
|
minecraft.modelManager.modelBakery.bakedTopLevelModels[ResourceLocation(OverdriveThatMatters.MOD_ID, "block/battery/battery$it")]!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ class BatteryBankRenderer(context: BlockEntityRendererProvider.Context) : BankRe
|
|||||||
|
|
||||||
class MatterBatteryBankRenderer(context: BlockEntityRendererProvider.Context) : BankRenderer<MatterCapacitorBankBlockEntity>(context) {
|
class MatterBatteryBankRenderer(context: BlockEntityRendererProvider.Context) : BankRenderer<MatterCapacitorBankBlockEntity>(context) {
|
||||||
override val models: List<BakedModel> by lazy {
|
override val models: List<BakedModel> by lazy {
|
||||||
ImmutableList(12) {
|
immutableList(12) {
|
||||||
minecraft.modelManager.modelBakery.bakedTopLevelModels[ResourceLocation(OverdriveThatMatters.MOD_ID, "block/battery/matter_capacitor$it")]!!
|
minecraft.modelManager.modelBakery.bakedTopLevelModels[ResourceLocation(OverdriveThatMatters.MOD_ID, "block/battery/matter_capacitor$it")]!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ fun <T : Enum<T>> T.prev(values: Array<out T>): T {
|
|||||||
return values[next]
|
return values[next]
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <T : Any> ImmutableList(size: Int, initializer: (index: Int) -> T): ImmutableList<T> {
|
inline fun <T : Any> immutableList(size: Int, initializer: (index: Int) -> T): ImmutableList<T> {
|
||||||
require(size >= 0) { "Invalid list size $size" }
|
require(size >= 0) { "Invalid list size $size" }
|
||||||
|
|
||||||
return when (size) {
|
return when (size) {
|
||||||
|
@ -3,7 +3,7 @@ package ru.dbotthepony.mc.otm.menu.decorative
|
|||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
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 ru.dbotthepony.mc.otm.core.ImmutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
||||||
@ -21,7 +21,7 @@ class CargoCrateMenu @JvmOverloads constructor(
|
|||||||
init {
|
init {
|
||||||
val container = tile?.container ?: SimpleContainer(CargoCrateBlockEntity.CAPACITY)
|
val container = tile?.container ?: SimpleContainer(CargoCrateBlockEntity.CAPACITY)
|
||||||
|
|
||||||
storageSlots = ImmutableList(CargoCrateBlockEntity.CAPACITY) {
|
storageSlots = immutableList(CargoCrateBlockEntity.CAPACITY) {
|
||||||
addStorageSlot(MatterySlot(container, it))
|
addStorageSlot(MatterySlot(container, it))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import net.minecraft.world.Container
|
|||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
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 ru.dbotthepony.mc.otm.core.ImmutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.entity.MinecartCargoCrate
|
import ru.dbotthepony.mc.otm.entity.MinecartCargoCrate
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
@ -23,7 +23,7 @@ class MinecartCargoCrateMenu @JvmOverloads constructor(
|
|||||||
init {
|
init {
|
||||||
val container = cart as Container? ?: SimpleContainer(CargoCrateBlockEntity.CAPACITY)
|
val container = cart as Container? ?: SimpleContainer(CargoCrateBlockEntity.CAPACITY)
|
||||||
|
|
||||||
storageSlots = ImmutableList(CargoCrateBlockEntity.CAPACITY) {
|
storageSlots = immutableList(CargoCrateBlockEntity.CAPACITY) {
|
||||||
addStorageSlot(MatterySlot(container, it))
|
addStorageSlot(MatterySlot(container, it))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ package ru.dbotthepony.mc.otm.menu.matter
|
|||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import ru.dbotthepony.mc.otm.core.ImmutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.block.entity.matter.MatterBottlerBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.matter.MatterBottlerBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
import ru.dbotthepony.mc.otm.capability.matter.canExtractMatter
|
import ru.dbotthepony.mc.otm.capability.matter.canExtractMatter
|
||||||
@ -43,7 +43,7 @@ class MatterBottlerMenu @JvmOverloads constructor(
|
|||||||
workFlow = BooleanInputWithFeedback(this, tile::isBottling)
|
workFlow = BooleanInputWithFeedback(this, tile::isBottling)
|
||||||
}
|
}
|
||||||
|
|
||||||
storageSlots = ImmutableList(6) { index ->
|
storageSlots = immutableList(6) { index ->
|
||||||
object : MatterySlot(container, index) {
|
object : MatterySlot(container, index) {
|
||||||
override fun mayPlace(p_40231_: ItemStack): Boolean {
|
override fun mayPlace(p_40231_: ItemStack): Boolean {
|
||||||
val cap = p_40231_.getCapability(MatteryCapability.MATTER).orNull() ?: return false
|
val cap = p_40231_.getCapability(MatteryCapability.MATTER).orNull() ?: return false
|
||||||
|
@ -2,7 +2,7 @@ package ru.dbotthepony.mc.otm.menu.matter
|
|||||||
|
|
||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import ru.dbotthepony.mc.otm.core.ImmutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.block.entity.matter.MatterCapacitorBankBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.matter.MatterCapacitorBankBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.menu.MatterContainerInputSlot
|
import ru.dbotthepony.mc.otm.menu.MatterContainerInputSlot
|
||||||
@ -37,7 +37,7 @@ class MatterCapacitorBankMenu @JvmOverloads constructor(
|
|||||||
|
|
||||||
val container = tile?.container ?: SimpleContainer(2 * 6)
|
val container = tile?.container ?: SimpleContainer(2 * 6)
|
||||||
|
|
||||||
storageSlots = ImmutableList(2 * 6) {
|
storageSlots = immutableList(2 * 6) {
|
||||||
addStorageSlot(MatterContainerInputSlot(container, it))
|
addStorageSlot(MatterContainerInputSlot(container, it))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import ru.dbotthepony.mc.otm.block.entity.matter.MatterReplicatorBlockEntity
|
|||||||
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
|
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
|
||||||
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
|
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
|
||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
import ru.dbotthepony.mc.otm.core.ImmutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.menu.MachineOutputSlot
|
import ru.dbotthepony.mc.otm.menu.MachineOutputSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
||||||
import ru.dbotthepony.mc.otm.registry.MMenus
|
import ru.dbotthepony.mc.otm.registry.MMenus
|
||||||
@ -25,7 +25,7 @@ class MatterReplicatorMenu @JvmOverloads constructor(
|
|||||||
init {
|
init {
|
||||||
val container = tile?.container ?: SimpleContainer(5)
|
val container = tile?.container ?: SimpleContainer(5)
|
||||||
|
|
||||||
storageSlots = ImmutableList(5) {
|
storageSlots = immutableList(5) {
|
||||||
addStorageSlot(MachineOutputSlot(container, it))
|
addStorageSlot(MachineOutputSlot(container, it))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ package ru.dbotthepony.mc.otm.menu.matter
|
|||||||
|
|
||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import ru.dbotthepony.mc.otm.core.ImmutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.block.entity.matter.PatternStorageBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.matter.PatternStorageBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
@ -37,7 +37,7 @@ class PatternStorageMenu @JvmOverloads constructor(
|
|||||||
|
|
||||||
val patterns = tile?.container ?: SimpleContainer(2 * 4)
|
val patterns = tile?.container ?: SimpleContainer(2 * 4)
|
||||||
|
|
||||||
storageSlots = ImmutableList(2 * 4) {
|
storageSlots = immutableList(2 * 4) {
|
||||||
addStorageSlot(PatternSlot(patterns, it))
|
addStorageSlot(PatternSlot(patterns, it))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ package ru.dbotthepony.mc.otm.menu.storage
|
|||||||
|
|
||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import ru.dbotthepony.mc.otm.core.ImmutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.block.entity.storage.DriveRackBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.storage.DriveRackBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.menu.DriveSlot
|
import ru.dbotthepony.mc.otm.menu.DriveSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
||||||
@ -19,7 +19,7 @@ class DriveRackMenu @JvmOverloads constructor(
|
|||||||
init {
|
init {
|
||||||
val container = tile?.container ?: SimpleContainer(4)
|
val container = tile?.container ?: SimpleContainer(4)
|
||||||
|
|
||||||
storageSlots = ImmutableList(4) {
|
storageSlots = immutableList(4) {
|
||||||
addStorageSlot(DriveSlot(container, it))
|
addStorageSlot(DriveSlot(container, it))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import net.minecraft.world.entity.player.Inventory
|
|||||||
import ru.dbotthepony.mc.otm.block.entity.tech.BatteryBankBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.tech.BatteryBankBlockEntity
|
||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
|
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
|
||||||
import ru.dbotthepony.mc.otm.core.ImmutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
|
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
import ru.dbotthepony.mc.otm.core.orNull
|
import ru.dbotthepony.mc.otm.core.orNull
|
||||||
@ -33,7 +33,7 @@ class BatteryBankMenu @JvmOverloads constructor(
|
|||||||
val container: Container = tile?.container ?: SimpleContainer(BatteryBankBlockEntity.CAPACITY)
|
val container: Container = tile?.container ?: SimpleContainer(BatteryBankBlockEntity.CAPACITY)
|
||||||
powerLevel = LevelGaugeWidget(this, tile?.getCapability(MatteryCapability.ENERGY)?.orNull())
|
powerLevel = LevelGaugeWidget(this, tile?.getCapability(MatteryCapability.ENERGY)?.orNull())
|
||||||
|
|
||||||
storageSlots = ImmutableList(BatteryBankBlockEntity.CAPACITY) {
|
storageSlots = immutableList(BatteryBankBlockEntity.CAPACITY) {
|
||||||
addStorageSlot(BatterySlot(container, it))
|
addStorageSlot(BatterySlot(container, it))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import net.minecraft.world.SimpleContainer
|
|||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
|
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
|
||||||
import ru.dbotthepony.mc.otm.block.entity.tech.CobblerBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.tech.CobblerBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.core.ImmutableList
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.menu.MachineOutputSlot
|
import ru.dbotthepony.mc.otm.menu.MachineOutputSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
|
||||||
@ -17,7 +17,7 @@ class CobblerMenu @JvmOverloads constructor(
|
|||||||
inventory: Inventory,
|
inventory: Inventory,
|
||||||
tile: CobblerBlockEntity? = null
|
tile: CobblerBlockEntity? = null
|
||||||
) : MatteryMenu(MMenus.COBBLESTONE_GENERATOR, p_38852_, inventory, tile) {
|
) : MatteryMenu(MMenus.COBBLESTONE_GENERATOR, p_38852_, inventory, tile) {
|
||||||
val storageSlots = (tile?.container ?: SimpleContainer(CobblerBlockEntity.CONTAINER_SIZE)).let { c -> ImmutableList(c.containerSize) { addStorageSlot(MachineOutputSlot(c, it)) } }
|
val storageSlots = (tile?.container ?: SimpleContainer(CobblerBlockEntity.CONTAINER_SIZE)).let { c -> immutableList(c.containerSize) { addStorageSlot(MachineOutputSlot(c, it)) } }
|
||||||
val redstone = EnumInputWithFeedback<RedstoneSetting>(this)
|
val redstone = EnumInputWithFeedback<RedstoneSetting>(this)
|
||||||
val itemConfig = ItemHandlerPlayerInput(this, false, false)
|
val itemConfig = ItemHandlerPlayerInput(this, false, false)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user