конфигуратор для копирования настроек #341

This commit is contained in:
YuRaNnNzZZ 2025-03-04 14:15:04 +03:00
parent 440b7fff2b
commit 5ea0b64982
Signed by: YuRaNnNzZZ
GPG Key ID: 5F71738C85A6006D
24 changed files with 244 additions and 31 deletions

View File

@ -114,6 +114,17 @@ fun addItemModels(provider: MatteryItemModelProvider) {
provider.handheld(MItems.CHEST_UPGRADER)
provider.exec {
val path = MItems.CONFIGURATOR.registryName!!.path
val ready = provider.withExistingParent("${path}_ready", MatteryItemModelProvider.HANDHELD)
.texture("layer0", modLocation("item/${path}_ready"))
provider.withExistingParent(path, MatteryItemModelProvider.HANDHELD)
.texture("layer0", modLocation("item/$path"))
.override().predicate(modLocation("has_configuration_saved"), 1f).model(ready).end()
}
provider.generated(MItems.BREAD_MONSTER_SPAWN_EGG, modLocation("item/egg/bread_monster"))
provider.generated(MItems.LOADER_SPAWN_EGG, modLocation("item/egg/loader"))

View File

@ -924,6 +924,12 @@ private fun items(provider: MatteryLanguageProvider) {
add(MItems.CHEST_UPGRADER, "desc", "Replaces placed chests and barrels with cargo crates while keeping storage contents")
add(MItems.CHEST_UPGRADER, "desc2", "Hold desired crates in the opposite hand")
add(MItems.CONFIGURATOR, "Configurator")
add(MItems.CONFIGURATOR, "desc", "Copies configuration from one block to another")
add(MItems.CONFIGURATOR, "desc2", "Sneak-use on block to copy, use to paste")
add(MItems.CONFIGURATOR, "desc3", "Use on air while sneaking to clear saved configuration")
add(MItems.CONFIGURATOR, "desc_saved", "Saved configuration for: %s")
add(MItems.BREAD_MONSTER_SPAWN_EGG, "Bread Monster Spawn Egg")
add(MEntityTypes.BREAD_MONSTER, "Bread Monster")
@ -981,6 +987,11 @@ private fun gui(provider: MatteryLanguageProvider) {
gui("flow_direction_set", "Flow direction set to %s")
gui("tick_timer_set", "Timer set to %s ticks")
gui("config_copied", "Copied configuration for %s")
gui("config_pasted", "Applied saved configuration")
gui("config_cleared", "Configuration cleared")
gui("config_missing", "No configuration to apply")
gui("black_hole_generator.help0", "Generates energy using angular momentum of Singularities")
gui("black_hole_generator.help1", "The stronger gravity Singularity has, the more power is generated!")
gui("black_hole_generator.help2", "Using Spacetime Normalizers will reduce gravitation strength of Singularity, which will reduce power output.")

View File

@ -917,6 +917,12 @@ private fun items(provider: MatteryLanguageProvider) {
add(MItems.CHEST_UPGRADER, "desc", "Заменяет установленные сундуки и бочки грузовыми ящиками с сохранением содержимого")
add(MItems.CHEST_UPGRADER, "desc2", "Удерживайте необходимые ящики в противоположной руке")
add(MItems.CONFIGURATOR, "Конфигуратор")
add(MItems.CONFIGURATOR, "desc", "Копирует настройки между блоками")
add(MItems.CONFIGURATOR, "desc2", "Использование крадясь на блоке копирует настройки, простое использование применяет")
add(MItems.CONFIGURATOR, "desc3", "Используйте крадясь на воздухе для очистки")
add(MItems.CONFIGURATOR, "desc_saved", "Сохранены настройки для: %s")
add(MItems.BREAD_MONSTER_SPAWN_EGG, "Яйцо призыва хлебного монстра")
add(MEntityTypes.BREAD_MONSTER, "Хлебный монстр")
@ -974,6 +980,11 @@ private fun gui(provider: MatteryLanguageProvider) {
gui("flow_direction_set", "Направление потока установлено на %s")
gui("tick_timer_set", "Таймер установлен на %s тиков")
gui("config_copied", "Скопированы настройки для %s")
gui("config_pasted", "Настройки применены")
gui("config_cleared", "Настройки очищены")
gui("config_missing", "Нет настроек для применения")
gui("black_hole_generator.help0", "Генерирует электричество используя угловое ускорение сингулярностей")
gui("black_hole_generator.help1", "Чем сильнее гравитационное поле сингулярности, тем больше генерация!")
gui("black_hole_generator.help2", "Использование стабилизаторов пространства-времени ослабляет гравитационное поле, снижая генерацию")

View File

@ -96,6 +96,11 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
*/
protected val savetablesLevel = Savetables()
/**
* Savetables for things configured from user input
*/
protected val savetablesConfig = Savetables()
/**
* "shortcut" for getting [BlockRotation]
*
@ -269,6 +274,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
*/
open fun saveShared(nbt: CompoundTag, registry: Provider) {
savetables.serializeNBT(nbt, registry)
saveConfiguration(nbt, registry)
}
/**
@ -282,6 +288,15 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
super.loadAdditional(nbt, registry)
savetables.deserializeNBT(registry, nbt)
savetablesLevel.deserializeNBT(registry, nbt)
loadConfiguration(nbt, registry)
}
fun saveConfiguration(nbt: CompoundTag, registry: Provider) {
savetablesConfig.serializeNBT(nbt, registry)
}
fun loadConfiguration(nbt: CompoundTag, registry: Provider) {
savetablesConfig.deserializeNBT(registry, nbt)
}
@Suppress("OVERRIDE_DEPRECATION")

View File

@ -56,7 +56,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
}
init {
savetables.stateful(::redstoneControl, REDSTONE_CONTROL_KEY)
savetablesConfig.stateful(::redstoneControl, REDSTONE_CONTROL_KEY)
}
protected open val defaultDisplayName: Component
@ -146,9 +146,9 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
init {
// https://tenor.com/view/simp-metal-gear-liquid-snake-running-gif-16717852
savetables.enum(::flow, "fluid_${side}_flow", FlowDirection::valueOf)
savetables.bool(::automatePull, "fluid_${side}_pull")
savetables.bool(::automatePush, "fluid_${side}_push")
savetablesConfig.enum(::flow, "fluid_${side}_flow", FlowDirection::valueOf)
savetablesConfig.bool(::automatePull, "fluid_${side}_pull")
savetablesConfig.bool(::automatePush, "fluid_${side}_push")
}
var flow by syncher.enum(possibleModes, setter = { access, value ->
@ -375,9 +375,9 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
}
init {
savetables.enum(::energyFlow, "energy_${side}_flow", FlowDirection::valueOf)
savetables.bool(::automatePull, "energy_${side}_pull")
savetables.bool(::automatePush, "energy_${side}_push")
savetablesConfig.enum(::energyFlow, "energy_${side}_flow", FlowDirection::valueOf)
savetablesConfig.bool(::automatePull, "energy_${side}_pull")
savetablesConfig.bool(::automatePush, "energy_${side}_push")
dirtyListeners.addListener(Runnable {
updateTickerState()
@ -626,9 +626,9 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
}
init {
savetables.bool(::automatePull, "itemhandler_${side}_automatePull")
savetables.bool(::automatePush, "itemhandler_${side}_automatePush")
savetables.enum(::mode, "itemhandler_${side}_mode", ItemHandlerMode::valueOf)
savetablesConfig.bool(::automatePull, "itemhandler_${side}_automatePull")
savetablesConfig.bool(::automatePush, "itemhandler_${side}_automatePush")
savetablesConfig.enum(::mode, "itemhandler_${side}_mode", ItemHandlerMode::valueOf)
waitForServerLevel {
redstoneControl.addListener(::updateTickerState)

View File

@ -73,7 +73,7 @@ abstract class MatteryWorkerBlockEntity<JobType : IJob>(
var balanceInputs = false
init {
savetables.bool(::balanceInputs)
savetablesConfig.bool(::balanceInputs)
}
protected open fun jobUpdated(new: JobType?, old: JobType?, id: Int) {}

View File

@ -118,9 +118,9 @@ class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
exposeSideless(MatteryCapability.BLOCK_ENERGY, energy)
exposeSideless(Capabilities.EnergyStorage.BLOCK, energy)
savetables.enum(::mode, map = Mode::valueOf)
savetables.decimal(::injectionRate)
savetables.decimal(::targetMass)
savetablesConfig.enum(::mode, map = Mode::valueOf)
savetablesConfig.decimal(::injectionRate)
savetablesConfig.decimal(::targetMass)
}
private fun findBlackHoleRange(): Int {

View File

@ -64,16 +64,16 @@ class HoloSignBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryB
var isLocked = false
init {
savetables.string(::signText)
savetablesConfig.string(::signText)
savetablesLevel.bool(::isLocked)
savetables.stateful(::redstoneControl)
savetablesConfig.stateful(::redstoneControl)
savetables.float(::textRed)
savetables.float(::textGreen)
savetables.float(::textBlue)
savetables.float(::textAlpha)
savetablesConfig.float(::textRed)
savetablesConfig.float(::textGreen)
savetablesConfig.float(::textBlue)
savetablesConfig.float(::textAlpha)
savetables.bool(::textAutoScale)
savetablesConfig.bool(::textAutoScale)
}
override fun createMenu(p_39954_: Int, p_39955_: Inventory, p_39956_: Player): AbstractContainerMenu {

View File

@ -82,7 +82,7 @@ class PainterBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDe
init {
addDroppableContainer(dyeInput)
savetables.stateful(dyeInput, INVENTORY_KEY)
savetables.bool(::isBulk)
savetablesConfig.bool(::isBulk)
exposeGlobally(Capabilities.FluidHandler.BLOCK, this)
}

View File

@ -112,8 +112,8 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
exposeGlobally(MatteryCapability.MATTER_BLOCK, matter)
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
savetables.bool(::isBottling)
savetables.bool(::spitItemsWhenCantWork)
savetablesConfig.bool(::isBottling)
savetablesConfig.bool(::spitItemsWhenCantWork)
savetables.stateful(::energy, ENERGY_KEY)
savetables.stateful(::matter, MATTER_STORAGE_KEY)
savetables.stateful(::bottling)

View File

@ -84,7 +84,7 @@ class MatterPanelBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matte
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
exposeGlobally(MatteryCapability.REPLICATION_TASK, this)
savetables.bool(::isProvidingTasks)
savetablesConfig.bool(::isProvidingTasks)
}
override fun setLevel(level: Level) {

View File

@ -63,9 +63,9 @@ class DriveRackBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
savetables.stateful(::energy, ENERGY_KEY)
savetables.stateful(::container, INVENTORY_KEY)
exposeGlobally(MatteryCapability.STORAGE_NODE, cell)
savetables.int(::insertPriority)
savetables.int(::extractPriority)
savetables.enum(::mode, map = FlowDirection::valueOf)
savetablesConfig.int(::insertPriority)
savetablesConfig.int(::extractPriority)
savetablesConfig.enum(::mode, map = FlowDirection::valueOf)
redstoneControl.addListener(Consumer {
cell.isDetached = it

View File

@ -131,7 +131,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
}
init {
savetables.codec(::filter, ItemFilter.CODEC, FILTER_KEY, Supplier { ItemFilter(MAX_FILTERS) })
savetablesConfig.codec(::filter, ItemFilter.CODEC, FILTER_KEY, Supplier { ItemFilter(MAX_FILTERS) })
}
override fun setLevel(level: Level) {

View File

@ -112,7 +112,7 @@ abstract class AbstractStorageImportExport(
}
init {
savetables.codec(::filter, ItemFilter.CODEC, FILTER_KEY, Supplier { ItemFilter(MAX_FILTERS) })
savetablesConfig.codec(::filter, ItemFilter.CODEC, FILTER_KEY, Supplier { ItemFilter(MAX_FILTERS) })
}
companion object {

View File

@ -78,7 +78,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
}
init {
savetables.int(::displayChartOnBlock)
savetablesConfig.int(::displayChartOnBlock)
savetables.stateful(::history5s)
savetables.stateful(::history15s)
savetables.stateful(::history1m)

View File

@ -0,0 +1,111 @@
package ru.dbotthepony.mc.otm.item
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResult
import net.minecraft.world.InteractionResultHolder
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.item.context.UseOnContext
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Blocks
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.registry.game.MDataComponentTypes
import ru.dbotthepony.mc.otm.server.sendActionBarMessage
class ConfiguratorItem : MatteryItem(Properties().stacksTo(1)) {
init {
addSimpleDescription()
addSimpleDescription("2")
addSimpleDescription("3")
}
override fun appendHoverText(
stack: ItemStack,
context: TooltipContext,
components: MutableList<Component>,
tooltipType: TooltipFlag
) {
super.appendHoverText(stack, context, components, tooltipType)
val tag = getConfiguration(stack)
val block = stack.getOrDefault(MDataComponentTypes.Configurator.BLOCK, Blocks.AIR.defaultBlockState())
if (!tag.isEmpty && !block.isAir) {
components.add(TranslatableComponent("$descriptionId.desc_saved", block.block.name))
}
}
override fun use(level: Level, player: Player, hand: InteractionHand): InteractionResultHolder<ItemStack?> {
if (player is ServerPlayer && player.isCrouching) {
val stack = player.getItemInHand(hand)
setConfiguration(stack, CompoundTag())
stack.set(MDataComponentTypes.Configurator.BLOCK, Blocks.AIR.defaultBlockState())
player.sendActionBarMessage(TranslatableComponent("otm.gui.config_cleared"))
return InteractionResultHolder.success(stack)
}
return super.use(level, player, hand)
}
override fun onItemUseFirst(stack: ItemStack, context: UseOnContext): InteractionResult {
val player = context.player
if (player == null) return super.useOn(context)
val level = context.level
val tile = level.getBlockEntity(context.clickedPos)
if (tile == null || tile !is MatteryBlockEntity) return super.useOn(context)
if (player.isCrouching == true) {
if (player is ServerPlayer) {
val tag = CompoundTag()
tile.saveConfiguration(tag, level.registryAccess())
if (tag.isEmpty) return super.onItemUseFirst(stack, context)
setConfiguration(stack, tag)
val block = level.getBlockState(context.clickedPos)
stack.set(MDataComponentTypes.Configurator.BLOCK, block)
player.sendActionBarMessage(TranslatableComponent("otm.gui.config_copied", block.block.name))
}
return InteractionResult.SUCCESS
}
val tag = getConfiguration(stack)
if (!tag.isEmpty) {
if (player is ServerPlayer) {
tile.loadConfiguration(tag, level.registryAccess())
player.sendActionBarMessage(TranslatableComponent("otm.gui.config_pasted"))
}
return InteractionResult.SUCCESS
} else {
if (player is ServerPlayer) {
player.sendActionBarMessage(TranslatableComponent("otm.gui.config_missing"))
}
return InteractionResult.FAIL
}
return super.useOn(context)
}
fun getConfiguration(stack: ItemStack): CompoundTag {
return stack.getOrDefault(MDataComponentTypes.Configurator.CONFIGURATION, CompoundTag())
}
fun setConfiguration(stack: ItemStack, tag: CompoundTag) {
stack.set(MDataComponentTypes.Configurator.CONFIGURATION, tag)
}
}

View File

@ -199,6 +199,7 @@ object MNames {
const val PLASMA_RIFLE = "plasma_rifle"
const val CHEST_UPGRADER = "chest_upgrader"
const val CONFIGURATOR = "configurator"
const val WITHERED_STEEL_SWORD = "withered_steel_sword"

View File

@ -6,6 +6,7 @@ import net.minecraft.core.BlockPos
import net.minecraft.core.cauldron.CauldronInteraction
import net.minecraft.core.component.DataComponents
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.nbt.CompoundTag
import net.minecraft.world.entity.EntityType
import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.Item
@ -43,6 +44,7 @@ import ru.dbotthepony.mc.otm.isClient
import ru.dbotthepony.mc.otm.item.armor.TritaniumArmorItem
import ru.dbotthepony.mc.otm.item.weapon.EnergySwordItem
import ru.dbotthepony.mc.otm.item.weapon.FallingSunItem
import ru.dbotthepony.mc.otm.registry.game.MDataComponentTypes
import ru.dbotthepony.mc.otm.registry.game.MItems
import ru.dbotthepony.mc.otm.registry.game.MStats
import ru.dbotthepony.mc.otm.registry.objects.ColoredDecorativeBlock
@ -316,6 +318,11 @@ object MRegistry : IBlockItemRegistryAcceptor {
}
}
}
ItemProperties.register(MItems.CONFIGURATOR, ResourceLocation(OverdriveThatMatters.MOD_ID, "has_configuration_saved")) { stack, _, _, _ ->
val tag = stack.getOrDefault(MDataComponentTypes.Configurator.CONFIGURATION, CompoundTag())
if (tag.isEmpty) 0f else 1f
}
}
}

View File

@ -263,6 +263,7 @@ private fun addMainCreativeTabItems(consumer: CreativeModeTab.Output) {
accept(MItems.GRAVITATIONAL_DISRUPTOR)
accept(MItems.CHEST_UPGRADER)
accept(MItems.CONFIGURATOR)
accept(MItems.ESSENCE_SERVO)

View File

@ -5,9 +5,11 @@ import com.mojang.serialization.Codec
import net.minecraft.core.UUIDUtil
import net.minecraft.core.component.DataComponentType
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.network.codec.StreamCodec
import net.minecraft.util.StringRepresentable
import net.minecraft.world.level.block.state.BlockState
import net.neoforged.bus.api.IEventBus
import net.neoforged.neoforge.fluids.SimpleFluidContent
import ru.dbotthepony.mc.otm.capability.FlowDirection
@ -17,6 +19,7 @@ import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.data.codec.DecimalCodec
import ru.dbotthepony.mc.otm.item.tool.RedstoneInteractorItem
import ru.dbotthepony.mc.otm.network.StreamCodecs
import ru.dbotthepony.mc.otm.network.streamCodec
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
import java.util.UUID
@ -34,6 +37,16 @@ object MDataComponentTypes {
}
}
private class CompoundTagComponent : DataComponentType<CompoundTag> {
override fun codec(): Codec<CompoundTag> {
return CompoundTag.CODEC
}
override fun streamCodec(): StreamCodec<in RegistryFriendlyByteBuf, CompoundTag> {
return CompoundTag.CODEC.streamCodec()
}
}
val FLUID_STACK by registry.register("fluid_stack") {
object : DataComponentType<SimpleFluidContent> {
override fun codec(): Codec<SimpleFluidContent> {
@ -81,6 +94,26 @@ object MDataComponentTypes {
}
}
object Configurator {
val BLOCK: DataComponentType<BlockState> by registry.register("configurator_block") {
object : DataComponentType<BlockState> {
override fun codec(): Codec<BlockState?>? {
return BlockState.CODEC
}
override fun streamCodec(): StreamCodec<in RegistryFriendlyByteBuf, BlockState?> {
return BlockState.CODEC.streamCodec()
}
}
}
val CONFIGURATION: DataComponentType<CompoundTag> by registry.register("configurator_configuration") { CompoundTagComponent() }
}
init {
Configurator
}
fun register(bus: IEventBus) {
registry.register(bus)
}

View File

@ -43,6 +43,7 @@ import ru.dbotthepony.mc.otm.core.collect.SupplierMap
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.item.BatteryItem
import ru.dbotthepony.mc.otm.item.ChestUpgraderItem
import ru.dbotthepony.mc.otm.item.ConfiguratorItem
import ru.dbotthepony.mc.otm.item.CrudeBatteryItem
import ru.dbotthepony.mc.otm.item.EssenceServoItem
import ru.dbotthepony.mc.otm.item.FluidCapsuleItem
@ -674,6 +675,8 @@ object MItems {
val ROFLITE_ALLOY_INGOT: Item by registry.register(MNames.ROFLITE_ALLOY_INGOT) { Item(DEFAULT_PROPERTIES) }
val ROFLITE_ALLOY_BLOCK: BlockItem by registry.register(MNames.ROFLITE_ALLOY_BLOCK) { BlockItem(MBlocks.ROFLITE_ALLOY_BLOCK, DEFAULT_PROPERTIES) }
val CONFIGURATOR: Item by registry.register(MNames.CONFIGURATOR) { ConfiguratorItem() }
init {
MRegistry.registerItems(registry)
}

View File

@ -0,0 +1,9 @@
package ru.dbotthepony.mc.otm.server
import net.minecraft.network.chat.Component
import net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket
import net.minecraft.server.level.ServerPlayer
fun ServerPlayer.sendActionBarMessage(component: Component) {
this.connection.send(ClientboundSetActionBarTextPacket(component))
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB