Fluid capsules test
This commit is contained in:
parent
6c4c40073e
commit
516de507e4
@ -261,39 +261,41 @@ private fun misc(provider: MatteryLanguageProvider) {
|
||||
misc("pill.message", "Nothing happened, but you feel... exhausted?.. Maybe get rest.")
|
||||
misc("pill.message_finish", "§kONE OF US ONE OF US ONE OF US")
|
||||
|
||||
misc("gui.power.percentage_level", "Energy level: %s%%")
|
||||
misc("gui.level", "%s / %s")
|
||||
misc("gui.power.name", "MtJ")
|
||||
gui("power.percentage_level", "Energy level: %s%%")
|
||||
gui("level", "%s / %s")
|
||||
gui("power.name", "MtJ")
|
||||
gui("fluid.name", "mB")
|
||||
gui("fluid.level", "%s / %s of %s")
|
||||
|
||||
misc("gui.power.burn_time", "Burn time left: %s ticks")
|
||||
gui("power.burn_time", "Burn time left: %s ticks")
|
||||
|
||||
misc("gui.progress_widget", "Progress: %s%%")
|
||||
misc("gui.progress_widget_stuck", "The machine can not work, check configuration")
|
||||
gui("progress_widget", "Progress: %s%%")
|
||||
gui("progress_widget_stuck", "The machine can not work, check configuration")
|
||||
|
||||
misc("gui.total_raw", "Total:")
|
||||
gui("total_raw", "Total:")
|
||||
|
||||
misc("gui.matter.percentage_level", "Matter level: %s%%")
|
||||
misc("gui.matter.format", "Matter: %s")
|
||||
misc("gui.matter.format_and_complexity", "%s / Complexity: %s")
|
||||
misc("gui.matter.format_and_complexity2", "%s (%s) / Complexity: %s (%s)")
|
||||
misc("gui.matter.name", "MtU")
|
||||
gui("matter.percentage_level", "Matter level: %s%%")
|
||||
gui("matter.format", "Matter: %s")
|
||||
gui("matter.format_and_complexity", "%s / Complexity: %s")
|
||||
gui("matter.format_and_complexity2", "%s (%s) / Complexity: %s (%s)")
|
||||
gui("matter.name", "MtU")
|
||||
|
||||
misc("gui.filter.is_whitelist", "Is Whitelist")
|
||||
misc("gui.filter.match_nbt", "Match NBT")
|
||||
misc("gui.filter.match_tag", "Match Tag")
|
||||
gui("filter.is_whitelist", "Is Whitelist")
|
||||
gui("filter.match_nbt", "Match NBT")
|
||||
gui("filter.match_tag", "Match Tag")
|
||||
|
||||
misc("gui.android_research", "Research Tree")
|
||||
gui("android_research", "Research Tree")
|
||||
|
||||
misc("gui.pattern.percentage_level", "Fill level: %s%%")
|
||||
misc("gui.pattern.format", "Stored patterns: %s / %s")
|
||||
gui("pattern.percentage_level", "Fill level: %s%%")
|
||||
gui("pattern.format", "Stored patterns: %s / %s")
|
||||
|
||||
misc("gui.redstone.ignored", "Redstone mode: Ignored")
|
||||
misc("gui.redstone.low", "Redstone mode: Low")
|
||||
misc("gui.redstone.high", "Redstone mode: High")
|
||||
gui("redstone.ignored", "Redstone mode: Ignored")
|
||||
gui("redstone.low", "Redstone mode: Low")
|
||||
gui("redstone.high", "Redstone mode: High")
|
||||
|
||||
misc("gui.redstone.ignored.description", "Redstone signal does not affect machine's function")
|
||||
misc("gui.redstone.low.description", "Machine work if no redstone signal is present")
|
||||
misc("gui.redstone.high.description", "Machine work only if any redstone signal is present")
|
||||
gui("redstone.ignored.description", "Redstone signal does not affect machine's function")
|
||||
gui("redstone.low.description", "Machine work if no redstone signal is present")
|
||||
gui("redstone.high.description", "Machine work only if any redstone signal is present")
|
||||
|
||||
misc("3d2d.gravitation_stabilizer.mass", "Singularity mass: %s")
|
||||
misc("3d2d.gravitation_stabilizer.strength", "Gravitation strength: %s")
|
||||
@ -458,6 +460,9 @@ private fun items(provider: MatteryLanguageProvider) {
|
||||
|
||||
add(MItems.NUTRIENT_PASTE, "Nutrient Paste")
|
||||
|
||||
add(MItems.FLUID_CAPSULE, "Fluid Capsule")
|
||||
add(MItems.FLUID_CAPSULE, "named", "Fluid Capsule (%s)")
|
||||
|
||||
add(MItems.BLACK_HOLE_SCANNER, "Singularity Scanner")
|
||||
add(MItems.BLACK_HOLE_SCANNER, "desc", "Scans singularities for their properties")
|
||||
add(MItems.BLACK_HOLE_SCANNER, "desc2", "Hold in hand to determine mass of singularities")
|
||||
|
@ -268,39 +268,41 @@ private fun misc(provider: MatteryLanguageProvider) {
|
||||
misc("pill.message", "Ничего не произошло, но вы чувствуете... себя уставшим?.. Возможно надо отдохнуть.")
|
||||
misc("pill.message_finish", "§kОДИН ИЗ НАС ОДИН ИЗ НАС ОДИН ИЗ НАС ОДИН ИЗ НАС ОДИН ИЗ НАС")
|
||||
|
||||
misc("gui.power.percentage_level", "Уровень энергии: %s%%")
|
||||
misc("gui.level", "%s / %s")
|
||||
misc("gui.power.name", "МтДж")
|
||||
gui("power.percentage_level", "Уровень энергии: %s%%")
|
||||
gui("level", "%s / %s")
|
||||
gui("power.name", "МтДж")
|
||||
gui("fluid.name", "мВ")
|
||||
gui("fluid.level", "%s / %s с %s")
|
||||
|
||||
misc("gui.power.burn_time", "Оставшееся время горения: %s тиков")
|
||||
gui("power.burn_time", "Оставшееся время горения: %s тиков")
|
||||
|
||||
misc("gui.progress_widget", "Прогресс: %s%%")
|
||||
misc("gui.progress_widget_stuck", "Это устройство не может продолжить работу, проверьте конфигурацию")
|
||||
gui("progress_widget", "Прогресс: %s%%")
|
||||
gui("progress_widget_stuck", "Это устройство не может продолжить работу, проверьте конфигурацию")
|
||||
|
||||
misc("gui.total_raw", "Всего:")
|
||||
gui("total_raw", "Всего:")
|
||||
|
||||
misc("gui.matter.percentage_level", "Уровень материи: %s%%")
|
||||
misc("gui.matter.format", "Материя: %s")
|
||||
misc("gui.matter.format_and_complexity", "%s / Сложность: %s")
|
||||
misc("gui.matter.format_and_complexity2", "%s (%s) / Сложность: %s (%s)")
|
||||
misc("gui.matter.name", "МтЕд")
|
||||
gui("matter.percentage_level", "Уровень материи: %s%%")
|
||||
gui("matter.format", "Материя: %s")
|
||||
gui("matter.format_and_complexity", "%s / Сложность: %s")
|
||||
gui("matter.format_and_complexity2", "%s (%s) / Сложность: %s (%s)")
|
||||
gui("matter.name", "МтЕд")
|
||||
|
||||
misc("gui.filter.is_whitelist", "Белый список")
|
||||
misc("gui.filter.match_nbt", "Сравнивать NBT")
|
||||
misc("gui.filter.match_tag", "Сравнить Теги")
|
||||
gui("filter.is_whitelist", "Белый список")
|
||||
gui("filter.match_nbt", "Сравнивать NBT")
|
||||
gui("filter.match_tag", "Сравнить Теги")
|
||||
|
||||
misc("gui.android_research", "Дерево Исследований")
|
||||
gui("android_research", "Дерево Исследований")
|
||||
|
||||
misc("gui.pattern.percentage_level", "Уровень заполнения: %s%%")
|
||||
misc("gui.pattern.format", "Хранимые шаблоны: %s / %s")
|
||||
gui("pattern.percentage_level", "Уровень заполнения: %s%%")
|
||||
gui("pattern.format", "Хранимые шаблоны: %s / %s")
|
||||
|
||||
misc("gui.redstone.ignored", "Режим красного камня: Игнорирование")
|
||||
misc("gui.redstone.low", "Режим красного камня: Нет сигнала")
|
||||
misc("gui.redstone.high", "Режим красного камня: Есть сигнал")
|
||||
gui("redstone.ignored", "Режим красного камня: Игнорирование")
|
||||
gui("redstone.low", "Режим красного камня: Нет сигнала")
|
||||
gui("redstone.high", "Режим красного камня: Есть сигнал")
|
||||
|
||||
misc("gui.redstone.ignored.description", "Сигнал красного камня не влияет на работу устройства")
|
||||
misc("gui.redstone.low.description", "Устройство работает если нет сигнала красного камня")
|
||||
misc("gui.redstone.high.description", "Устройство работает если есть сигнал красного камня")
|
||||
gui("redstone.ignored.description", "Сигнал красного камня не влияет на работу устройства")
|
||||
gui("redstone.low.description", "Устройство работает если нет сигнала красного камня")
|
||||
gui("redstone.high.description", "Устройство работает если есть сигнал красного камня")
|
||||
|
||||
misc("3d2d.gravitation_stabilizer.mass", "Масса сингулярности: %s")
|
||||
misc("3d2d.gravitation_stabilizer.strength", "Гравитационная сила: %s")
|
||||
@ -465,6 +467,9 @@ private fun items(provider: MatteryLanguageProvider) {
|
||||
|
||||
add(MItems.NUTRIENT_PASTE, "Питательная паста")
|
||||
|
||||
add(MItems.FLUID_CAPSULE, "Жидкостная капсула")
|
||||
add(MItems.FLUID_CAPSULE, "named", "Жидкостная капсула (%s)")
|
||||
|
||||
add(MItems.BLACK_HOLE_SCANNER, "Сканер сингулярностей")
|
||||
add(MItems.BLACK_HOLE_SCANNER, "desc", "Сканирует сингулярности и считывает их свойства")
|
||||
add(MItems.BLACK_HOLE_SCANNER, "desc2", "Держите в любой их рук для считывания массы сингулярностей")
|
||||
|
@ -15,6 +15,7 @@ import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import ru.dbotthepony.mc.otm.android.AndroidResearchManager;
|
||||
import ru.dbotthepony.mc.otm.android.feature.EnderTeleporterFeature;
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity;
|
||||
@ -46,6 +47,7 @@ import ru.dbotthepony.mc.otm.config.ServerConfig;
|
||||
import ru.dbotthepony.mc.otm.config.ToolsConfig;
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal;
|
||||
import ru.dbotthepony.mc.otm.item.ItemTritaniumArmor;
|
||||
import ru.dbotthepony.mc.otm.item.PriorityUseItemKt;
|
||||
import ru.dbotthepony.mc.otm.item.QuantumBatteryItem;
|
||||
import ru.dbotthepony.mc.otm.item.weapon.AbstractWeaponItem;
|
||||
import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem;
|
||||
@ -59,6 +61,7 @@ import top.theillusivec4.curios.api.CuriosApi;
|
||||
import static net.minecraftforge.common.MinecraftForge.EVENT_BUS;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import java.util.Objects;
|
||||
|
||||
// The value here should match an entry in the META-INF/mods.toml file
|
||||
@Mod(OverdriveThatMatters.MOD_ID)
|
||||
@ -72,8 +75,9 @@ public final class OverdriveThatMatters {
|
||||
public static OverdriveThatMatters INSTANCE;
|
||||
private StorageStackType<ItemStackWrapper> ITEM_STORAGE;
|
||||
|
||||
@NotNull
|
||||
public StorageStackType<ItemStackWrapper> ITEM_STORAGE() {
|
||||
return ITEM_STORAGE;
|
||||
return Objects.requireNonNull(ITEM_STORAGE);
|
||||
}
|
||||
|
||||
public static ResourceLocation loc(String path) {
|
||||
@ -183,6 +187,8 @@ public final class OverdriveThatMatters {
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryBlockEntity.Companion::playerDisconnected);
|
||||
EVENT_BUS.addListener(EventPriority.LOWEST, MatteryBlockEntity.Companion::postLevelTick);
|
||||
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, PriorityUseItemKt::onItemRightClick);
|
||||
|
||||
EVENT_BUS.addListener(EventPriority.LOWEST, KillAsAndroidTrigger.INSTANCE::onKill);
|
||||
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, EnderTeleporterFeature.Companion::onEntityDeath);
|
||||
|
@ -1,15 +1,23 @@
|
||||
package ru.dbotthepony.mc.otm.capability
|
||||
|
||||
import com.google.common.collect.Streams
|
||||
import earth.terrarium.botarium.common.registry.fluid.FluidSounds
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider
|
||||
import net.minecraftforge.common.util.LazyOptional
|
||||
import net.minecraftforge.energy.IEnergyStorage
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||
import net.minecraftforge.fml.ModList
|
||||
import net.minecraftforge.items.IItemHandler
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
|
||||
import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorAwareStream
|
||||
import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorStream
|
||||
import ru.dbotthepony.mc.otm.compat.cos.isCosmeticArmorLoaded
|
||||
@ -24,10 +32,13 @@ import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
|
||||
import ru.dbotthepony.mc.otm.core.collect.ContainerItemStackEntry
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.orNull
|
||||
import ru.dbotthepony.mc.otm.core.util.formatFluidLevel
|
||||
import java.util.IdentityHashMap
|
||||
import java.util.LinkedList
|
||||
import java.util.stream.Stream
|
||||
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
|
||||
val ICapabilityProvider.matteryPlayer: MatteryPlayerCapability? get() = getCapability(MatteryCapability.MATTERY_PLAYER).orNull()
|
||||
|
||||
/**
|
||||
@ -297,3 +308,119 @@ fun Player.awareAllItemsStream(includeCosmetics: Boolean = false): Stream<out Aw
|
||||
seen.stream())
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to safely exchange/move item between slots of two handlers
|
||||
*
|
||||
* @return pair of new (advanced) [sourceSlot] and [destinationSlot]
|
||||
*/
|
||||
internal fun moveBetweenSlots(source: IItemHandler, sourceSlot: Int, destination: IItemHandler, destinationSlot: Int): Pair<Int, Int> {
|
||||
val getItem = source.extractItem(sourceSlot, Int.MAX_VALUE, true)
|
||||
|
||||
if (getItem.isEmpty) {
|
||||
return sourceSlot + 1 to destinationSlot
|
||||
} else {
|
||||
val leftover = destination.insertItem(destinationSlot, getItem, true)
|
||||
|
||||
if (leftover.count == getItem.count) {
|
||||
return sourceSlot to destinationSlot + 1
|
||||
} else {
|
||||
val getItem2 = source.extractItem(sourceSlot, getItem.count - leftover.count, true)
|
||||
|
||||
if (getItem2.isEmpty) {
|
||||
return sourceSlot + 1 to destinationSlot
|
||||
} else {
|
||||
val leftover2 = destination.insertItem(destinationSlot, getItem2, true)
|
||||
|
||||
if (leftover2.isEmpty) {
|
||||
source.extractItem(sourceSlot, getItem2.count, false)
|
||||
destination.insertItem(destinationSlot, getItem2, false)
|
||||
|
||||
if (getItem2.count == getItem.count) {
|
||||
return sourceSlot + 1 to destinationSlot
|
||||
} else {
|
||||
return sourceSlot to destinationSlot
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sourceSlot to destinationSlot
|
||||
}
|
||||
|
||||
@Suppress("name_shadowing")
|
||||
internal fun moveEnergy(source: IEnergyStorage, destination: IEnergyStorage, amount: Decimal = Decimal.LONG_MAX_VALUE, simulate: Boolean, ignoreFlowRestrictions: Boolean = false): Decimal {
|
||||
val extracted = if (ignoreFlowRestrictions && source is IMatteryEnergyStorage) source.extractEnergy(amount, true) else source.extractEnergy(amount, true)
|
||||
|
||||
if (extracted.isPositive) {
|
||||
val received = destination.receiveEnergy(extracted, true)
|
||||
|
||||
if (received.isPositive) {
|
||||
val extracted = if (ignoreFlowRestrictions && source is IMatteryEnergyStorage) source.extractEnergy(received, true) else source.extractEnergy(received, true)
|
||||
|
||||
if (extracted.isPositive) {
|
||||
if (simulate) {
|
||||
return extracted
|
||||
}
|
||||
|
||||
val received = destination.receiveEnergy(extracted, false)
|
||||
return if (ignoreFlowRestrictions && source is IMatteryEnergyStorage) source.extractEnergy(received, false) else source.extractEnergy(received, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Decimal.ZERO
|
||||
}
|
||||
|
||||
internal fun fluidLevel(it: IFluidHandler, tooltips: MutableList<Component>) {
|
||||
val fluid = it.getFluidInTank(0)
|
||||
|
||||
if (fluid.isEmpty) {
|
||||
tooltips.add(formatFluidLevel(0, it.getTankCapacity(0), formatAsReadable = ShiftPressedCond).withStyle(ChatFormatting.GRAY))
|
||||
} else {
|
||||
tooltips.add(formatFluidLevel(fluid.amount, it.getTankCapacity(0), fluid.displayName, formatAsReadable = ShiftPressedCond).withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
}
|
||||
|
||||
internal fun moveFluid(source: IFluidHandler, sourceTank: Int? = null, destination: IFluidHandler, limit: Int = Int.MAX_VALUE, simulate: Boolean = false, actuallyDrain: Boolean = true): FluidStack {
|
||||
val drained: FluidStack
|
||||
|
||||
if (sourceTank == null) {
|
||||
drained = source.drain(limit, IFluidHandler.FluidAction.SIMULATE)
|
||||
} else {
|
||||
drained = source.drain(source.getFluidInTank(sourceTank), IFluidHandler.FluidAction.SIMULATE)
|
||||
}
|
||||
|
||||
if (drained.isEmpty) return FluidStack.EMPTY
|
||||
|
||||
val filled = destination.fill(drained, IFluidHandler.FluidAction.SIMULATE)
|
||||
if (filled == 0) return FluidStack.EMPTY
|
||||
|
||||
val drained2 = source.drain(FluidStack(drained, filled), IFluidHandler.FluidAction.SIMULATE)
|
||||
if (drained2.amount != filled) return FluidStack.EMPTY
|
||||
|
||||
val filled2 = destination.fill(drained2, IFluidHandler.FluidAction.SIMULATE)
|
||||
if (filled2 != drained2.amount) return FluidStack.EMPTY
|
||||
|
||||
if (simulate) return FluidStack(drained2, filled2)
|
||||
|
||||
val drained3: FluidStack
|
||||
|
||||
if (actuallyDrain) {
|
||||
drained3 = source.drain(FluidStack(drained2, filled2), IFluidHandler.FluidAction.EXECUTE)
|
||||
|
||||
if (drained3.amount != filled2) {
|
||||
LOGGER.warn("Inconsistency of fluid extraction from $source between simulate and execute modes (simulated $drained2; extracted $drained3); This can lead to duping!!!")
|
||||
}
|
||||
} else {
|
||||
drained3 = drained2
|
||||
}
|
||||
|
||||
val filled3 = destination.fill(drained3, IFluidHandler.FluidAction.EXECUTE)
|
||||
|
||||
if (filled3 != drained3.amount) {
|
||||
LOGGER.warn("Inconsistency of fluid insertion to $destination between simulate and execute modes (simulated $filled2; inserted $filled3); This can lead to duping!!!")
|
||||
}
|
||||
|
||||
return FluidStack(drained3, filled3)
|
||||
}
|
||||
|
@ -1,70 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.capability
|
||||
|
||||
import net.minecraftforge.energy.IEnergyStorage
|
||||
import net.minecraftforge.items.IItemHandler
|
||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
|
||||
/**
|
||||
* Attempts to safely exchange/move item between slots of two handlers
|
||||
*
|
||||
* @return pair of new (advanced) [sourceSlot] and [destinationSlot]
|
||||
*/
|
||||
fun moveBetweenSlots(source: IItemHandler, sourceSlot: Int, destination: IItemHandler, destinationSlot: Int): Pair<Int, Int> {
|
||||
val getItem = source.extractItem(sourceSlot, Int.MAX_VALUE, true)
|
||||
|
||||
if (getItem.isEmpty) {
|
||||
return sourceSlot + 1 to destinationSlot
|
||||
} else {
|
||||
val leftover = destination.insertItem(destinationSlot, getItem, true)
|
||||
|
||||
if (leftover.count == getItem.count) {
|
||||
return sourceSlot to destinationSlot + 1
|
||||
} else {
|
||||
val getItem2 = source.extractItem(sourceSlot, getItem.count - leftover.count, true)
|
||||
|
||||
if (getItem2.isEmpty) {
|
||||
return sourceSlot + 1 to destinationSlot
|
||||
} else {
|
||||
val leftover2 = destination.insertItem(destinationSlot, getItem2, true)
|
||||
|
||||
if (leftover2.isEmpty) {
|
||||
source.extractItem(sourceSlot, getItem2.count, false)
|
||||
destination.insertItem(destinationSlot, getItem2, false)
|
||||
|
||||
if (getItem2.count == getItem.count) {
|
||||
return sourceSlot + 1 to destinationSlot
|
||||
} else {
|
||||
return sourceSlot to destinationSlot
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sourceSlot to destinationSlot
|
||||
}
|
||||
|
||||
@Suppress("name_shadowing")
|
||||
fun moveEnergy(source: IEnergyStorage, destination: IEnergyStorage, amount: Decimal = Decimal.LONG_MAX_VALUE, simulate: Boolean, ignoreFlowRestrictions: Boolean = false): Decimal {
|
||||
val extracted = if (ignoreFlowRestrictions && source is IMatteryEnergyStorage) source.extractEnergy(amount, true) else source.extractEnergy(amount, true)
|
||||
|
||||
if (extracted.isPositive) {
|
||||
val received = destination.receiveEnergy(extracted, true)
|
||||
|
||||
if (received.isPositive) {
|
||||
val extracted = if (ignoreFlowRestrictions && source is IMatteryEnergyStorage) source.extractEnergy(received, true) else source.extractEnergy(received, true)
|
||||
|
||||
if (extracted.isPositive) {
|
||||
if (simulate) {
|
||||
return extracted
|
||||
}
|
||||
|
||||
val received = destination.receiveEnergy(extracted, false)
|
||||
return if (ignoreFlowRestrictions && source is IMatteryEnergyStorage) source.extractEnergy(received, false) else source.extractEnergy(received, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Decimal.ZERO
|
||||
}
|
@ -91,6 +91,10 @@ object ItemsConfig : AbstractConfig("items") {
|
||||
}
|
||||
|
||||
init {
|
||||
builder.push("PatternDrives")
|
||||
PatternDrives
|
||||
builder.pop()
|
||||
}
|
||||
|
||||
val FLUID_CAPSULE_CAPACITY: Int by builder.defineInRange("LIQUID_CAPSULE_CAPACITY", 1000, 1, Int.MAX_VALUE)
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ class AwareContainerSpliterator(private val container: Container, offset: Int =
|
||||
}
|
||||
}
|
||||
|
||||
fun Container.spliterator() = ContainerSpliterator(this)
|
||||
fun Container.awareSpliterator() = AwareContainerSpliterator(this)
|
||||
fun Container.stream(): Stream<out ItemStack> = StreamSupport.stream(spliterator(), false)
|
||||
fun Container.awareStream(): Stream<out AwareItemStack> = StreamSupport.stream(awareSpliterator(), false)
|
||||
fun Container.spliterator(offset: Int = 0) = ContainerSpliterator(this, offset)
|
||||
fun Container.awareSpliterator(offset: Int = 0) = AwareContainerSpliterator(this, offset)
|
||||
fun Container.stream(offset: Int = 0): Stream<out ItemStack> = StreamSupport.stream(spliterator(offset), false)
|
||||
fun Container.awareStream(offset: Int = 0): Stream<out AwareItemStack> = StreamSupport.stream(awareSpliterator(offset), false)
|
||||
|
@ -3,12 +3,15 @@ package ru.dbotthepony.mc.otm.container
|
||||
import net.minecraft.world.Container
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraftforge.common.capabilities.Capability
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||
import ru.dbotthepony.mc.otm.core.collect.iterator
|
||||
import ru.dbotthepony.mc.otm.core.collect.nonEmpty
|
||||
|
||||
operator fun Container.set(index: Int, value: ItemStack) = setItem(index, value)
|
||||
operator fun Container.get(index: Int): ItemStack = getItem(index)
|
||||
|
||||
operator fun IFluidHandler.get(index: Int) = getFluidInTank(index)
|
||||
|
||||
fun Container.addItem(stack: ItemStack, range: IntRange, simulate: Boolean = false): ItemStack {
|
||||
if (this is MatteryContainer) {
|
||||
return this.addItem(stack, range, simulate)
|
||||
|
@ -0,0 +1,25 @@
|
||||
package ru.dbotthepony.mc.otm.container
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectIterators.AbstractIndexBasedIterator
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||
|
||||
class FluidHandlerIterator(private val handler: IFluidHandler, initialPosition: Int = 0) : AbstractIndexBasedIterator<FluidStack>(0, initialPosition) {
|
||||
init {
|
||||
require(initialPosition in 0 .. handler.tanks) { "Invalid initial position: $initialPosition" }
|
||||
}
|
||||
|
||||
override fun remove(location: Int) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun get(location: Int): FluidStack {
|
||||
return handler[location]
|
||||
}
|
||||
|
||||
override fun getMaxPos(): Int {
|
||||
return handler.tanks
|
||||
}
|
||||
}
|
||||
|
||||
fun IFluidHandler.iterator(position: Int = 0) = FluidHandlerIterator(this, position)
|
@ -0,0 +1,31 @@
|
||||
package ru.dbotthepony.mc.otm.container
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectSpliterator
|
||||
import it.unimi.dsi.fastutil.objects.ObjectSpliterators.AbstractIndexBasedSpliterator
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||
import java.util.Spliterator
|
||||
import java.util.stream.Stream
|
||||
import java.util.stream.StreamSupport
|
||||
|
||||
class FluidHandlerSpliterator(private val handler: IFluidHandler, offset: Int = 0, private val maxPos: Int = handler.tanks) : AbstractIndexBasedSpliterator<FluidStack>(offset) {
|
||||
init {
|
||||
require(offset in 0 until handler.tanks) { "Invalid offset $offset" }
|
||||
require(maxPos >= offset && maxPos in 0 until handler.tanks) { "Invalid spliterator configuration: maxPos $maxPos offset $offset max tanks ${handler.tanks}" }
|
||||
}
|
||||
|
||||
override fun get(location: Int): FluidStack {
|
||||
return handler[location]
|
||||
}
|
||||
|
||||
override fun getMaxPos(): Int {
|
||||
return maxPos
|
||||
}
|
||||
|
||||
override fun makeForSplit(pos: Int, maxPos: Int): ObjectSpliterator<FluidStack> {
|
||||
return FluidHandlerSpliterator(handler, pos, maxPos)
|
||||
}
|
||||
}
|
||||
|
||||
fun IFluidHandler.spliterator(offset: Int = 0): Spliterator<FluidStack> = FluidHandlerSpliterator(this, offset)
|
||||
fun IFluidHandler.stream(offset: Int = 0): Stream<FluidStack> = StreamSupport.stream(spliterator(offset), false)
|
@ -14,6 +14,7 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.material.Fluid
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import net.minecraftforge.registries.IForgeRegistry
|
||||
|
||||
@ -65,6 +66,7 @@ fun <T> IForgeRegistry<T>.getKeyNullable(value: T): ResourceLocation? {
|
||||
}
|
||||
|
||||
val Item.registryName get() = ForgeRegistries.ITEMS.getKeyNullable(this)
|
||||
val Fluid.registryName get() = ForgeRegistries.FLUIDS.getKeyNullable(this)
|
||||
val Block.registryName get() = ForgeRegistries.BLOCKS.getKeyNullable(this)
|
||||
|
||||
fun FriendlyByteBuf.writeRegistryId(value: Item) = writeRegistryId(ForgeRegistries.ITEMS, value)
|
||||
|
@ -1,26 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.core.collect
|
||||
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.inventory.Slot
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
private class SlotIterator(private val parent: Iterator<Slot>) : MutableIterator<ItemStack> {
|
||||
private var last: Slot? = null
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
return parent.hasNext()
|
||||
}
|
||||
|
||||
override fun next(): ItemStack {
|
||||
return parent.next().also { last = it }.item
|
||||
}
|
||||
|
||||
override fun remove() {
|
||||
val last = last ?: throw IllegalStateException("Never called next()")
|
||||
last.set(ItemStack.EMPTY)
|
||||
}
|
||||
}
|
||||
|
||||
fun AbstractContainerMenu.itemStackIterator() : MutableIterator<ItemStack> = SlotIterator(slots.iterator())
|
||||
fun Iterable<Slot>.itemStackIterator() : MutableIterator<ItemStack> = SlotIterator(iterator())
|
||||
fun Iterator<Slot>.asItemStackIterator() : MutableIterator<ItemStack> = SlotIterator(this)
|
@ -209,6 +209,7 @@ fun Decimal.formatSiComponent(suffix: Any = "", decimalPlaces: Int = 2, formatAs
|
||||
}
|
||||
|
||||
fun Int.formatPower(decimalPlaces: Int = 2, formatAsReadable: BooleanSupplier = never) = formatSiComponent(TranslatableComponent("otm.gui.power.name"), decimalPlaces, formatAsReadable = formatAsReadable)
|
||||
fun Int.formatFluid(decimalPlaces: Int = 2, formatAsReadable: BooleanSupplier = never) = formatSiComponent(TranslatableComponent("otm.gui.fluid.name"), decimalPlaces, formatAsReadable = formatAsReadable)
|
||||
fun Decimal.formatPower(decimalPlaces: Int = 2, formatAsReadable: BooleanSupplier = never) = formatSiComponent(TranslatableComponent("otm.gui.power.name"), decimalPlaces, formatAsReadable = formatAsReadable)
|
||||
fun Decimal.formatMatter(decimalPlaces: Int = 2, formatAsReadable: BooleanSupplier = never) = formatSiComponent(TranslatableComponent("otm.gui.matter.name"), decimalPlaces, formatAsReadable = formatAsReadable)
|
||||
fun Decimal.formatMatterFull(decimalPlaces: Int = 2, formatAsReadable: BooleanSupplier = never) = TranslatableComponent("otm.gui.matter.format", formatSiComponent(TranslatableComponent("otm.gui.matter.name"), decimalPlaces, formatAsReadable = formatAsReadable))
|
||||
@ -219,6 +220,8 @@ fun BigInteger.formatMatterFull(decimalPlaces: Int = 2, formatAsReadable: Boolea
|
||||
|
||||
fun formatPowerLevel(a: Decimal, b: Decimal, decimalPlaces: Int = 2, formatAsReadable: BooleanSupplier = never) = TranslatableComponent("otm.gui.level", a.formatPower(decimalPlaces, formatAsReadable = formatAsReadable), b.formatPower(decimalPlaces, formatAsReadable = formatAsReadable))
|
||||
fun formatMatterLevel(a: Decimal, b: Decimal, decimalPlaces: Int = 2, formatAsReadable: BooleanSupplier = never) = TranslatableComponent("otm.gui.level", a.formatMatter(decimalPlaces, formatAsReadable = formatAsReadable), b.formatMatter(decimalPlaces, formatAsReadable = formatAsReadable))
|
||||
fun formatFluidLevel(a: Int, b: Int, decimalPlaces: Int = 2, formatAsReadable: BooleanSupplier = never) = TranslatableComponent("otm.gui.level", a.formatFluid(decimalPlaces, formatAsReadable = formatAsReadable), b.formatFluid(decimalPlaces, formatAsReadable = formatAsReadable))
|
||||
fun formatFluidLevel(a: Int, b: Int, name: Component, decimalPlaces: Int = 2, formatAsReadable: BooleanSupplier = never) = TranslatableComponent("otm.gui.fluid.level", a.formatFluid(decimalPlaces, formatAsReadable = formatAsReadable), b.formatFluid(decimalPlaces, formatAsReadable = formatAsReadable), name)
|
||||
|
||||
private fun padded(num: Int): String {
|
||||
if (num in 0 .. 9) {
|
||||
|
274
src/main/kotlin/ru/dbotthepony/mc/otm/item/FluidCapsuleItem.kt
Normal file
274
src/main/kotlin/ru/dbotthepony/mc/otm/item/FluidCapsuleItem.kt
Normal file
@ -0,0 +1,274 @@
|
||||
package ru.dbotthepony.mc.otm.item
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.Item
|
||||
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.Block
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.LayeredCauldronBlock
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.material.Fluid
|
||||
import net.minecraft.world.level.material.Fluids
|
||||
import net.minecraftforge.common.SoundActions
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||
import net.minecraftforge.fluids.capability.templates.FluidHandlerItemStack
|
||||
import ru.dbotthepony.mc.otm.capability.fluidLevel
|
||||
import ru.dbotthepony.mc.otm.capability.moveFluid
|
||||
import ru.dbotthepony.mc.otm.container.get
|
||||
import ru.dbotthepony.mc.otm.container.stream
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||
import ru.dbotthepony.mc.otm.core.immutableList
|
||||
import ru.dbotthepony.mc.otm.core.immutableMap
|
||||
import ru.dbotthepony.mc.otm.core.orNull
|
||||
|
||||
class FluidCapsuleItem(val capacity: () -> Int) : Item(Properties().stacksTo(64)), PriorityUseItem {
|
||||
private inner class Cap(itemStack: ItemStack) : FluidHandlerItemStack(itemStack, capacity.invoke()) {
|
||||
override fun fill(resource: FluidStack, doFill: IFluidHandler.FluidAction): Int {
|
||||
this.capacity = this@FluidCapsuleItem.capacity.invoke()
|
||||
return super.fill(resource, doFill)
|
||||
}
|
||||
|
||||
override fun getTankCapacity(tank: Int): Int {
|
||||
this.capacity = this@FluidCapsuleItem.capacity.invoke()
|
||||
return super.getTankCapacity(tank)
|
||||
}
|
||||
|
||||
override fun drain(resource: FluidStack?, action: IFluidHandler.FluidAction?): FluidStack {
|
||||
this.capacity = this@FluidCapsuleItem.capacity.invoke()
|
||||
return super.drain(resource, action)
|
||||
}
|
||||
|
||||
override fun drain(maxDrain: Int, action: IFluidHandler.FluidAction?): FluidStack {
|
||||
this.capacity = this@FluidCapsuleItem.capacity.invoke()
|
||||
return super.drain(maxDrain, action)
|
||||
}
|
||||
}
|
||||
|
||||
override fun isPriorityConsumer(event: PlayerInteractEvent.RightClickBlock): Boolean {
|
||||
return canInteract(event.itemStack, event.entity, Context(event.hitVec.blockPos, event.entity.level.getBlockState(event.hitVec.blockPos), event.hitVec.direction))
|
||||
}
|
||||
|
||||
override fun useOn(pContext: UseOnContext): InteractionResult {
|
||||
val context = Context(pContext.clickedPos, pContext.level.getBlockState(pContext.clickedPos), pContext.clickedFace)
|
||||
|
||||
if (canInteract(pContext.itemInHand, pContext.player ?: return InteractionResult.FAIL, context))
|
||||
return interact(pContext.itemInHand, pContext.player!!, context)
|
||||
|
||||
return InteractionResult.FAIL
|
||||
}
|
||||
|
||||
override fun getName(pStack: ItemStack): Component {
|
||||
pStack.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).ifPresentK {
|
||||
it.getFluidInTank(0).also {
|
||||
if (!it.isEmpty) {
|
||||
return TranslatableComponent("$descriptionId.named", it.displayName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.getName(pStack)
|
||||
}
|
||||
|
||||
override fun appendHoverText(pStack: ItemStack, pLevel: Level?, pTooltipComponents: MutableList<Component>, pIsAdvanced: TooltipFlag) {
|
||||
super.appendHoverText(pStack, pLevel, pTooltipComponents, pIsAdvanced)
|
||||
|
||||
pStack.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).ifPresentK {
|
||||
fluidLevel(it, pTooltipComponents)
|
||||
}
|
||||
}
|
||||
|
||||
override fun initCapabilities(stack: ItemStack, nbt: CompoundTag?): ICapabilityProvider {
|
||||
return Cap(stack)
|
||||
}
|
||||
|
||||
interface Interaction {
|
||||
fun canInteract(item: ItemStack, player: Player, context: Context): Boolean
|
||||
fun interact(item: ItemStack, player: Player, context: Context): InteractionResult
|
||||
}
|
||||
|
||||
private object FillCauldron : Interaction {
|
||||
private data class Mapping(val fluid: Fluid, val blockState: BlockState, val soundEvent: SoundEvent)
|
||||
|
||||
private val mapping = immutableList {
|
||||
accept(Mapping(Fluids.WATER, Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY))
|
||||
accept(Mapping(Fluids.LAVA, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA))
|
||||
}
|
||||
|
||||
override fun canInteract(item: ItemStack, player: Player, context: Context): Boolean {
|
||||
return player.level.getBlockState(context.blockPos).`is`(Blocks.CAULDRON)
|
||||
}
|
||||
|
||||
override fun interact(item: ItemStack, player: Player, context: Context): InteractionResult {
|
||||
if (item.isEmpty || !context.blockState.`is`(Blocks.CAULDRON)) return InteractionResult.FAIL
|
||||
|
||||
val targetItem = if (item.count == 1) item else item.copyWithCount(1)
|
||||
|
||||
val cap = targetItem.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).orNull() ?: return InteractionResult.FAIL
|
||||
|
||||
for ((fluid, newState, soundEvent) in mapping) {
|
||||
val toDrain = FluidStack(fluid, 1000)
|
||||
val drained = cap.drain(toDrain, IFluidHandler.FluidAction.SIMULATE)
|
||||
|
||||
if (!drained.isEmpty && drained.amount == 1000) {
|
||||
player.level.playSound(player, context.blockPos, soundEvent, SoundSource.BLOCKS)
|
||||
val level = player.level as? ServerLevel ?: return InteractionResult.SUCCESS
|
||||
level.setBlock(context.blockPos, newState, Block.UPDATE_ALL)
|
||||
cap.drain(toDrain, IFluidHandler.FluidAction.EXECUTE)
|
||||
|
||||
if (item.count != 1 && !player.level.isClientSide) {
|
||||
item.count--
|
||||
|
||||
if (!player.inventory.add(targetItem)) {
|
||||
player.spawnAtLocation(targetItem)
|
||||
}
|
||||
}
|
||||
|
||||
return InteractionResult.sidedSuccess(player.level.isClientSide)
|
||||
}
|
||||
}
|
||||
|
||||
return InteractionResult.FAIL
|
||||
}
|
||||
}
|
||||
|
||||
private object EmptyCauldron : Interaction {
|
||||
private val mapping = immutableMap {
|
||||
put(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), Fluids.WATER to SoundEvents.BUCKET_FILL)
|
||||
put(Blocks.LAVA_CAULDRON.defaultBlockState(), Fluids.LAVA to SoundEvents.BUCKET_FILL_LAVA)
|
||||
}
|
||||
|
||||
override fun canInteract(item: ItemStack, player: Player, context: Context): Boolean {
|
||||
return player.level.getBlockState(context.blockPos) in mapping
|
||||
}
|
||||
|
||||
override fun interact(item: ItemStack, player: Player, context: Context): InteractionResult {
|
||||
if (item.isEmpty) return InteractionResult.FAIL
|
||||
|
||||
val targetItem = if (item.count == 1) item else item.copyWithCount(1)
|
||||
|
||||
val cap = targetItem.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).orNull() ?: return InteractionResult.FAIL
|
||||
val mapped = mapping[context.blockState] ?: return InteractionResult.FAIL
|
||||
|
||||
val toFill = FluidStack(mapped.first, 1000)
|
||||
|
||||
val fill = cap.fill(toFill, IFluidHandler.FluidAction.SIMULATE)
|
||||
if (fill != 1000) return InteractionResult.FAIL
|
||||
|
||||
player.level.playSound(player, context.blockPos, mapped.second, SoundSource.BLOCKS)
|
||||
|
||||
val level = player.level as? ServerLevel ?: return InteractionResult.SUCCESS
|
||||
level.setBlock(context.blockPos, Blocks.CAULDRON.defaultBlockState(), Block.UPDATE_ALL)
|
||||
cap.fill(toFill, IFluidHandler.FluidAction.EXECUTE)
|
||||
|
||||
if (item.count != 1 && !player.level.isClientSide) {
|
||||
item.count--
|
||||
|
||||
if (!player.inventory.add(targetItem)) {
|
||||
player.spawnAtLocation(targetItem)
|
||||
}
|
||||
}
|
||||
|
||||
return InteractionResult.sidedSuccess(player.level.isClientSide)
|
||||
}
|
||||
}
|
||||
|
||||
private object FillEmptyCapability : Interaction {
|
||||
override fun canInteract(item: ItemStack, player: Player, context: Context): Boolean {
|
||||
val target = player.level.getBlockEntity(context.blockPos)?.getCapability(ForgeCapabilities.FLUID_HANDLER, context.side)?.orNull() ?: return false
|
||||
val cap = item.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).orNull() ?: return false
|
||||
return target.stream().anyMatch { !it.isEmpty } || cap.stream().anyMatch { !it.isEmpty }
|
||||
}
|
||||
|
||||
override fun interact(item: ItemStack, player: Player, context: Context): InteractionResult {
|
||||
if (item.isEmpty) return InteractionResult.FAIL
|
||||
|
||||
val targetItem = if (item.count == 1) item else item.copyWithCount(1)
|
||||
|
||||
val itemCap = targetItem.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).orNull() ?: return InteractionResult.FAIL
|
||||
val blockCap = player.level.getBlockEntity(context.blockPos)?.getCapability(ForgeCapabilities.FLUID_HANDLER, context.side)?.orNull() ?: return InteractionResult.FAIL
|
||||
val fluid = itemCap[0]
|
||||
|
||||
if (fluid.isEmpty || player.isCrouching) {
|
||||
// заполняем из блока
|
||||
val moveResult = moveFluid(source = blockCap, destination = itemCap, simulate = player.level.isClientSide)
|
||||
|
||||
if (!moveResult.isEmpty) {
|
||||
val sound = moveResult.fluid.fluidType.getSound(moveResult, SoundActions.BUCKET_FILL)
|
||||
|
||||
if (sound != null) {
|
||||
player.level.playSound(player, context.blockPos, sound, SoundSource.BLOCKS)
|
||||
}
|
||||
|
||||
if (item.count != 1 && !player.level.isClientSide) {
|
||||
item.count--
|
||||
|
||||
if (!player.inventory.add(targetItem)) {
|
||||
player.spawnAtLocation(targetItem)
|
||||
}
|
||||
}
|
||||
|
||||
return InteractionResult.sidedSuccess(player.level.isClientSide)
|
||||
} else {
|
||||
return InteractionResult.FAIL
|
||||
}
|
||||
} else {
|
||||
val moveResult = moveFluid(source = itemCap, destination = blockCap, simulate = player.level.isClientSide)
|
||||
|
||||
if (!moveResult.isEmpty) {
|
||||
val sound = moveResult.fluid.fluidType.getSound(moveResult, SoundActions.BUCKET_EMPTY)
|
||||
|
||||
if (sound != null) {
|
||||
player.level.playSound(player, context.blockPos, sound, SoundSource.BLOCKS)
|
||||
}
|
||||
|
||||
if (item.count != 1 && !player.level.isClientSide) {
|
||||
item.count--
|
||||
|
||||
if (!player.inventory.add(targetItem)) {
|
||||
player.spawnAtLocation(targetItem)
|
||||
}
|
||||
}
|
||||
|
||||
return InteractionResult.sidedSuccess(player.level.isClientSide)
|
||||
} else {
|
||||
return InteractionResult.FAIL
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class Context(val blockPos: BlockPos, val blockState: BlockState, val side: Direction)
|
||||
|
||||
companion object : Interaction {
|
||||
val interactions = immutableList {
|
||||
accept(FillCauldron)
|
||||
accept(EmptyCauldron)
|
||||
accept(FillEmptyCapability)
|
||||
}
|
||||
|
||||
override fun canInteract(item: ItemStack, player: Player, context: Context): Boolean {
|
||||
return interactions.any { it.canInteract(item, player, context) }
|
||||
}
|
||||
|
||||
override fun interact(item: ItemStack, player: Player, context: Context): InteractionResult {
|
||||
return interactions.firstOrNull { it.canInteract(item, player, context) }?.interact(item, player, context) ?: InteractionResult.PASS
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package ru.dbotthepony.mc.otm.item
|
||||
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent
|
||||
import net.minecraftforge.eventbus.api.Event
|
||||
|
||||
interface PriorityUseItem {
|
||||
fun isPriorityConsumer(event: PlayerInteractEvent.RightClickBlock): Boolean
|
||||
}
|
||||
|
||||
internal fun onItemRightClick(event: PlayerInteractEvent.RightClickBlock) {
|
||||
val item = event.itemStack.item
|
||||
|
||||
if (!event.itemStack.isEmpty && item is PriorityUseItem) {
|
||||
if (item.isPriorityConsumer(event)) {
|
||||
event.useBlock = Event.Result.DENY
|
||||
}
|
||||
}
|
||||
}
|
@ -4,8 +4,15 @@ import net.minecraft.world.item.CreativeModeTab
|
||||
import net.minecraft.world.item.DyeColor
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.material.FlowingFluid
|
||||
import net.minecraft.world.level.material.Fluids
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import ru.dbotthepony.mc.otm.capability.matter.matter
|
||||
import ru.dbotthepony.mc.otm.capability.matteryEnergy
|
||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||
import ru.dbotthepony.mc.otm.core.registryName
|
||||
|
||||
private fun CreativeModeTab.Output.accept(values: Collection<Item>) {
|
||||
@ -140,6 +147,18 @@ internal fun addMainCreativeTabItems(consumer: CreativeModeTab.Output) {
|
||||
accept(MItems.PATTERN_DRIVE_CREATIVE)
|
||||
accept(MItems.PATTERN_DRIVE_CREATIVE2)
|
||||
|
||||
accept(MItems.FLUID_CAPSULE)
|
||||
|
||||
for (fluid in ForgeRegistries.FLUIDS.values) {
|
||||
if (fluid != Fluids.EMPTY && fluid.isSource(fluid.defaultFluidState())) {
|
||||
accept(ItemStack(MItems.FLUID_CAPSULE, 1).also {
|
||||
it.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM).ifPresentK {
|
||||
it.fill(FluidStack(fluid, it.getTankCapacity(0)), IFluidHandler.FluidAction.EXECUTE)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
base(MItems.CARGO_CRATE_MINECARTS)
|
||||
|
||||
accept(MItems.NUTRIENT_PASTE)
|
||||
|
@ -155,6 +155,8 @@ object MItems {
|
||||
val ESSENCE_CAPSULE: EssenceCapsuleItem by registry.register("essence_capsule") { EssenceCapsuleItem() }
|
||||
val ESSENCE_DRIVE: EssenceCapsuleItem by registry.register("essence_drive") { EssenceCapsuleItem() }
|
||||
|
||||
val FLUID_CAPSULE: FluidCapsuleItem by registry.register("fluid_capsule") { FluidCapsuleItem(ItemsConfig::FLUID_CAPSULE_CAPACITY) }
|
||||
|
||||
val TRITANIUM_COMPONENT: ForgeTier = ForgeTier(
|
||||
Tiers.IRON.level,
|
||||
3072,
|
||||
|
Loading…
Reference in New Issue
Block a user