This commit is contained in:
DBotThePony 2024-05-31 12:12:22 +07:00
commit 0f355150a2
Signed by: DBot
GPG Key ID: DCC23B5715498507
212 changed files with 2600 additions and 4905 deletions

View File

@ -3,6 +3,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import java.util.Date
import java.text.SimpleDateFormat
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
import org.gradle.kotlin.dsl.accessors.runtime.addDependencyTo
val mod_version: String by project
val mc_version: String by project
@ -119,16 +120,26 @@ tasks.test {
useJUnitPlatform()
}
configurations {
create("embeddedLibs")
}
jarJar.enable()
dependencies {
val jupiter_version: String by project
val kotlin_for_forge_version: String by project
val mixin_version: String by project
val kommons_version: String by project
minecraft("net.minecraftforge:forge:$mc_version-$forge_version")
testImplementation("org.junit.jupiter:junit-jupiter:${jupiter_version}")
implementation("thedarkcolour:kotlinforforge:$kotlin_for_forge_version")
jarJar("ru.dbotthepony.kommons:kommons-mc:[$kommons_version,)") { setTransitive(false) }
implementation("ru.dbotthepony.kommons:kommons-mc:[$kommons_version,)") { setTransitive(false) }
compileOnly("yalter.mousetweaks:MouseTweaks:2.23:api")
annotationProcessor("org.spongepowered:mixin:${mixin_version}:processor")
@ -271,6 +282,7 @@ repositories {
includeGroup("at.ridgo8.moreoverlays")
includeGroup("ru.dbotthepony")
includeGroup("curse.maven")
includeGroup("ru.dbotthepony.kommons")
}
}
@ -324,6 +336,12 @@ fun org.gradle.jvm.tasks.Jar.attachManifest() {
tasks.jar.configure {
finalizedBy("reobfJar")
attachManifest()
archiveClassifier.set("slim")
archiveVersion.set(gitVersion.jarName)
}
tasks.jarJar.configure {
archiveClassifier.set("")
archiveVersion.set(gitVersion.jarName)
}

View File

@ -19,6 +19,8 @@ forge_version=44.1.23
mixingradle_version=0.7.33
mixin_version=0.8.5
kommons_version=3.0.1
jei_version=12.4.0.22
jupiter_version=5.9.2
curios_version=4440173

View File

@ -20,6 +20,7 @@ import net.minecraftforge.common.data.ForgeAdvancementProvider
import net.minecraftforge.eventbus.api.SubscribeEvent
import net.minecraftforge.fml.common.Mod
import net.minecraftforge.data.event.GatherDataEvent
import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidResearchDataProvider
import ru.dbotthepony.mc.otm.block.*
@ -530,6 +531,7 @@ object DataGen {
val registrySetBuilder = RegistrySetBuilder()
.add(Registries.CONFIGURED_FEATURE, ::registerConfiguredFeatures)
.add(Registries.PLACED_FEATURE, ::registerPlacedFeatures)
.add(ForgeRegistries.Keys.BIOME_MODIFIERS, ::registerBiomeModifiers)
event.generator.addProvider(event.includeServer(), DatapackBuiltinEntriesProvider(event.generator.packOutput, event.lookupProvider, registrySetBuilder, setOf(MOD_ID)))

View File

@ -1,10 +1,13 @@
package ru.dbotthepony.mc.otm.datagen
import net.minecraft.core.HolderSet
import net.minecraft.core.RegistrySetBuilder
import net.minecraft.core.registries.Registries
import net.minecraft.data.worldgen.BootstapContext
import net.minecraft.resources.ResourceKey
import net.minecraft.tags.BiomeTags
import net.minecraft.tags.BlockTags
import net.minecraft.world.level.levelgen.GenerationStep
import net.minecraft.world.level.levelgen.VerticalAnchor
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature
import net.minecraft.world.level.levelgen.feature.Feature
@ -15,10 +18,19 @@ import net.minecraft.world.level.levelgen.placement.InSquarePlacement
import net.minecraft.world.level.levelgen.placement.PlacedFeature
import net.minecraft.world.level.levelgen.structure.templatesystem.TagMatchTest
import net.minecraftforge.common.data.DatapackBuiltinEntriesProvider
import net.minecraftforge.common.world.BiomeModifier
import net.minecraftforge.common.world.ForgeBiomeModifiers
import net.minecraftforge.data.event.GatherDataEvent
import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.registry.MBlocks
private val oreKey by lazy { ResourceKey.create(Registries.CONFIGURED_FEATURE, modLocation("tritanium_ore")) }
private object ConfiguredFeatures {
val TRITANIUM_ORE = key("tritanium_ore")
private fun key(name: String): ResourceKey<ConfiguredFeature<*, *>> {
return ResourceKey.create(Registries.CONFIGURED_FEATURE, modLocation(name))
}
}
fun registerConfiguredFeatures(context: BootstapContext<ConfiguredFeature<*, *>>) {
val stone = TagMatchTest(BlockTags.STONE_ORE_REPLACEABLES)
@ -29,16 +41,23 @@ fun registerConfiguredFeatures(context: BootstapContext<ConfiguredFeature<*, *>>
OreConfiguration.target(deepslate, MBlocks.DEEPSLATE_TRITANIUM_ORE.defaultBlockState()),
)
context.register(oreKey, ConfiguredFeature(Feature.ORE, OreConfiguration(target, 9)))
context.register(ConfiguredFeatures.TRITANIUM_ORE, ConfiguredFeature(Feature.ORE, OreConfiguration(target, 9)))
}
private object PlacedFeatures {
val NORMAL_TRITANIUM = key("normal_tritanium")
val DEEP_TRITANIUM = key("deep_tritanium")
private fun key(name: String): ResourceKey<PlacedFeature> {
return ResourceKey.create(Registries.PLACED_FEATURE, modLocation(name))
}
}
fun registerPlacedFeatures(context: BootstapContext<PlacedFeature>) {
fun location(name: String) = ResourceKey.create(Registries.PLACED_FEATURE, modLocation(name))
val configured = context.lookup(Registries.CONFIGURED_FEATURE)
val ore = configured.getOrThrow(oreKey)
val ore = configured.getOrThrow(ConfiguredFeatures.TRITANIUM_ORE)
context.register(location("normal_tritanium"), PlacedFeature(
context.register(PlacedFeatures.NORMAL_TRITANIUM, PlacedFeature(
ore,
listOf(
CountPlacement.of(8),
@ -47,7 +66,7 @@ fun registerPlacedFeatures(context: BootstapContext<PlacedFeature>) {
)
))
context.register(location("deep_tritanium"), PlacedFeature(
context.register(PlacedFeatures.DEEP_TRITANIUM, PlacedFeature(
ore,
listOf(
CountPlacement.of(10),
@ -56,3 +75,28 @@ fun registerPlacedFeatures(context: BootstapContext<PlacedFeature>) {
)
))
}
private object BiomeModifiers {
val TRITANIUM_ORE = key("tritanium_ore")
private fun key(name: String): ResourceKey<BiomeModifier> {
return ResourceKey.create(ForgeRegistries.Keys.BIOME_MODIFIERS, modLocation(name))
}
}
fun registerBiomeModifiers(context: BootstapContext<BiomeModifier>) {
val placed = context.lookup(Registries.PLACED_FEATURE)
val biomes = context.lookup(Registries.BIOME)
context.register(
BiomeModifiers.TRITANIUM_ORE,
ForgeBiomeModifiers.AddFeaturesBiomeModifier(
biomes.getOrThrow(BiomeTags.IS_OVERWORLD),
HolderSet.direct(
placed.getOrThrow(PlacedFeatures.NORMAL_TRITANIUM),
placed.getOrThrow(PlacedFeatures.DEEP_TRITANIUM)
),
GenerationStep.Decoration.UNDERGROUND_ORES
)
)
}

View File

@ -114,6 +114,9 @@ fun addBlockStates(provider: MatteryBlockStateProvider) {
provider.block(MBlocks.ENERGY_SERVO.values)
provider.block(MBlocks.COBBLESTONE_GENERATOR.values)
provider.block(MBlocks.PAINTER)
provider.block(MBlocks.INFINITE_WATER_SOURCE)
provider.exec {
for (block in MBlocks.ESSENCE_STORAGE.values) {
provider.getVariantBuilder(block).forAllStates {

View File

@ -186,6 +186,9 @@ fun addItemModels(provider: MatteryItemModelProvider) {
provider.coloredWithBaseBlock(MItems.MATTER_RECYCLER, "matter_recycler", "_idle")
provider.coloredWithBaseBlock(MItems.COBBLESTONE_GENERATOR, "cobblestone_generator")
provider.block(MItems.PAINTER, "painter")
provider.block(MItems.INFINITE_WATER_SOURCE, "infinite_water_source")
provider.exec {
provider.withExistingParent("essence_storage", modLocation("block/essence_storage_empty"))
.override()

View File

@ -479,6 +479,14 @@ private fun blocks(provider: MatteryLanguageProvider) {
addBlock(MBlocks.DRIVE_VIEWER.values, "Drive Viewer")
add(MBlocks.BLACK_HOLE, "Local Anomalous Spacetime Dilation Singular Point")
add(MBlocks.BLACK_HOLE_GENERATOR, "Matter Acceleration Power Generator")
add(MBlocks.ENERGY_INPUT_HATCH, "Energy Input Hatch")
add(MBlocks.ITEM_INPUT_HATCH, "Item Input Hatch")
add(MBlocks.MATTER_INPUT_HATCH, "Matter Input Hatch")
add(MBlocks.ENERGY_OUTPUT_HATCH, "Energy Output Hatch")
add(MBlocks.ITEM_OUTPUT_HATCH, "Item Output Hatch")
add(MBlocks.MATTER_OUTPUT_HATCH, "Matter Output Hatch")
addBlock(MBlocks.COBBLESTONE_GENERATOR.values, "Cobblestone Generator")
add(MBlocks.INFINITE_WATER_SOURCE, "Infinite Water Source")
@ -810,6 +818,7 @@ private fun androidFeatures(provider: MatteryLanguageProvider) {
private fun gui(provider: MatteryLanguageProvider) {
with(provider.english) {
gui("part_of_multiblock", "Part of multiblock structure, useless on its own")
gui("quicksearch", "Quick search...")
gui("painter.is_bulk", "Bulk painting")

View File

@ -484,7 +484,16 @@ private fun blocks(provider: MatteryLanguageProvider) {
addBlock(MBlocks.COBBLESTONE_GENERATOR.values, "Генератор булыжника")
add(MBlocks.INFINITE_WATER_SOURCE, "Неиссякаемый источник воды")
add(MBlocks.INFINITE_WATER_SOURCE, "desc", "Выталкивает воду в соседние блоки автоматически")
add(MBlocks.BLACK_HOLE, "Локализированная сингулярная точка аномального искажения пространства-времени")
add(MBlocks.BLACK_HOLE_GENERATOR, "Генератор энергии ускорением материи")
add(MBlocks.ENERGY_INPUT_HATCH, "Входной энергетический клапан")
add(MBlocks.ITEM_INPUT_HATCH, "Входной предметный клапан")
add(MBlocks.MATTER_INPUT_HATCH, "Входной клапан материи")
add(MBlocks.ENERGY_OUTPUT_HATCH, "Выходной энергетический клапан")
add(MBlocks.ITEM_OUTPUT_HATCH, "Выходной предметный клапан")
add(MBlocks.MATTER_OUTPUT_HATCH, "Выходной клапан материи")
add(MBlocks.DEV_CHEST, "Сундук разработчика")
add(MBlocks.DEV_CHEST, "desc", "Хранит все предметы, которые есть в игре")
@ -814,6 +823,7 @@ private fun androidFeatures(provider: MatteryLanguageProvider) {
private fun gui(provider: MatteryLanguageProvider) {
with(provider.russian) {
gui("part_of_multiblock", "Часть мультиблока, бесполезен сам по себе")
gui("quicksearch", "Быстрый поиск...")
gui("painter.is_bulk", "Массовая покраска")

View File

@ -169,4 +169,8 @@ fun addLootTables(lootTables: LootTables) {
lootTables.tile(MBlocks.PATTERN_STORAGE)
lootTables.tile(MBlocks.MATTER_CAPACITOR_BANK.values)
lootTables.tile(MBlocks.MATTER_BOTTLER.values)
lootTables.tile(MBlocks.BLACK_HOLE_GENERATOR)
lootTables.tile(MBlocks.ITEM_INPUT_HATCH)
lootTables.tile(MBlocks.ITEM_OUTPUT_HATCH)
}

View File

@ -11,6 +11,7 @@ import net.minecraft.world.level.block.Blocks
import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.registry.MBlockTags
import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MFluids
import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry
@ -29,6 +30,9 @@ fun addTags(tagsProvider: TagsProvider) {
tagsProvider.plates.add("gold", MItems.GOLD_PLATE)
tagsProvider.plates.add("carbon", MItems.CARBON_MESH)
// tagsProvider.fluids.forge("experience").add(MFluids.LIQUID_XP).add(MFluids.LIQUID_XP_FLOWING)
// tagsProvider.fluidTypes.forge("experience").add(MFluids.LIQUID_XP_TYPE)
tagsProvider.items.forge("reinforced_tritanium").add(MItems.REINFORCED_TRITANIUM_PLATE)
tagsProvider.storageBlocksAsItem.add("tritanium", MItems.TRITANIUM_INGOT_BLOCK)
@ -219,6 +223,10 @@ fun addTags(tagsProvider: TagsProvider) {
*MBlocks.MATTER_RECONSTRUCTOR.values.toTypedArray(),
MBlocks.FLUID_TANK,
*MBlocks.ANDROID_CHARGER.values.toTypedArray(),
MBlocks.BLACK_HOLE_GENERATOR,
MBlocks.ITEM_INPUT_HATCH,
MBlocks.ITEM_OUTPUT_HATCH,
), Tiers.IRON)
tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_ANVIL, Tiers.IRON)

View File

@ -167,6 +167,9 @@ class TagsProvider(private val event: GatherDataEvent) {
val blocks = Delegate(ForgeRegistries.BLOCKS)
val items = Delegate(ForgeRegistries.ITEMS)
// not supported on 1.19.4 and earlier
// val fluids = Delegate(ForgeRegistries.FLUIDS)
// val fluidTypes = Delegate(ForgeRegistries.Keys.FLUID_TYPES)
val mobEffects = Delegate(ForgeRegistries.MOB_EFFECTS)
val androidImmuneEffects = mobEffects.Appender(MatteryPlayerCapability.ANDROID_IMMUNE_EFFECTS)

View File

@ -178,7 +178,6 @@ fun onServerTick(event: ServerTickEvent) {
// чтоб не плодить кучу подписчиков, вызовем напрямую отсюда
GraphNodeList.tick()
AbstractProfiledStorage.onServerPostTick()
MatteryNetworkChannel.onServerPostTick()
}
}
@ -290,14 +289,12 @@ fun onServerStarting(event: ServerAboutToStartEvent) {
_server = event.server
serverThreads.add(Thread.currentThread())
serverCounter.incrementAndGet()
MatteryNetworkChannel.onServerStarting()
}
fun onServerStopping(event: ServerStoppingEvent) {
clear()
SERVER_IS_LIVE = false
serverCounter.incrementAndGet()
MatteryNetworkChannel.onServerStopping()
}
fun onServerStopped(event: ServerStoppedEvent) {
@ -310,5 +307,4 @@ fun onServerStopped(event: ServerStoppedEvent) {
_server = null
serverCounter.incrementAndGet()
MatteryNetworkChannel.onServerStopped()
}

View File

@ -5,18 +5,21 @@ import net.minecraft.nbt.CompoundTag
import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.event.entity.living.LivingAttackEvent
import net.minecraftforge.event.entity.living.LivingHurtEvent
import ru.dbotthepony.kommons.io.DelegateSyncher
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
import java.io.InputStream
abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: MatteryPlayerCapability) : INBTSerializable<CompoundTag> {
val ply get() = android.ply
val synchronizer = FieldSynchronizer()
val syncher = DelegateSyncher()
val syncherRemote = syncher.Remote()
open var level by synchronizer.int(setter = setter@{ value, field, setByRemote ->
if (value != field.read()) {
field.write(value)
open var level by syncher.int(setter = setter@{ field, value ->
if (value != field.get()) {
field.accept(value)
applyModifiers()
}
})
@ -28,7 +31,7 @@ abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: Matt
* Called when it is required to network everything again
*/
open fun invalidateNetwork() {
synchronizer.invalidate()
syncherRemote.invalidate()
}
open fun applyModifiers() {}
@ -38,11 +41,12 @@ abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: Matt
open fun onAttack(event: LivingAttackEvent) {}
open fun collectNetworkPayload(): FastByteArrayOutputStream? {
return synchronizer.collectNetworkPayload()
syncher.observe()
return syncherRemote.write()
}
open fun applyNetworkPayload(stream: InputStream) {
synchronizer.read(stream)
syncher.read(stream)
}
override fun serializeNBT(): CompoundTag {

View File

@ -8,9 +8,11 @@ import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.player.Player
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.eventbus.api.Cancelable
import net.minecraftforge.eventbus.api.Event
import net.minecraftforge.eventbus.api.Event.HasResult
import ru.dbotthepony.kommons.io.DelegateSyncher
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.awareItemsStream
@ -19,7 +21,6 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.milliTime
import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
import ru.dbotthepony.mc.otm.triggers.AndroidResearchTrigger
import java.io.InputStream
import kotlin.math.absoluteValue
@ -53,9 +54,10 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
val ply: Player get() = capability.ply
val synchronizer = FieldSynchronizer()
val syncher = DelegateSyncher()
val syncherRemote = syncher.Remote()
var isResearched by synchronizer.bool().property
var isResearched by syncher.boolean()
private set
var tag = CompoundTag()
@ -65,7 +67,7 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
* Called when it is required to network everything again
*/
fun invalidateNetwork() {
synchronizer.invalidate()
syncherRemote.invalidate()
}
fun unResearch() {
@ -187,11 +189,12 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
}
fun collectNetworkPayload(): FastByteArrayOutputStream? {
return synchronizer.collectNetworkPayload()
syncher.observe()
return syncherRemote.write()
}
fun applyNetworkPayload(stream: InputStream) {
synchronizer.read(stream)
syncher.read(stream)
}
val canResearch: Boolean get() {

View File

@ -7,6 +7,7 @@ import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component
import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.registries.DeferredRegister
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
import ru.dbotthepony.mc.otm.config.AndroidConfig

View File

@ -7,6 +7,7 @@ import net.minecraft.resources.ResourceLocation
import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.registries.DeferredRegister
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.core.getValue
import ru.dbotthepony.mc.otm.data.SingletonCodec

View File

@ -2,18 +2,21 @@ package ru.dbotthepony.mc.otm.android
import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.nbt.CompoundTag
import net.minecraft.server.level.ServerPlayer
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.core.nbt.set
abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: MatteryPlayerCapability) : AndroidFeature(type, android) {
var isActive by synchronizer.bool(setter = setter@{ value, access, setByRemote ->
if (value != access.readBoolean()) {
access.write(value)
var isActive by syncher.boolean(setter = setter@{ access, value ->
if (value != access.get()) {
access.accept(value)
if (!setByRemote) {
if (ply is ServerPlayer) {
if (value) {
applyModifiers()
} else {
@ -21,13 +24,13 @@ abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: Ma
}
}
}
}).property
})
open val allowToSwitchByPlayer: Boolean get() = true
open val allowToSwitchByPlayerWhileSpectator: Boolean get() = true
open val maxCooldown: Int get() = 0
open var cooldown by synchronizer.int().property
open var cooldown by syncher.int()
val isOnCooldown: Boolean
get() = maxCooldown > 0 && cooldown > 0

View File

@ -23,6 +23,7 @@ import net.minecraft.world.phys.shapes.Shapes
import net.minecraftforge.client.event.RenderLevelStageEvent
import net.minecraftforge.event.ForgeEventFactory
import net.minecraftforge.event.entity.living.LivingDeathEvent
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.AndroidActiveFeature
@ -37,6 +38,7 @@ import ru.dbotthepony.mc.otm.client.render.sprites.sprite
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.core.genericPositions
import ru.dbotthepony.mc.otm.core.holder
import ru.dbotthepony.mc.otm.core.isFall
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.Vector
import ru.dbotthepony.mc.otm.core.math.asVector

View File

@ -4,6 +4,7 @@ import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.item.ItemEntity
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
@ -13,7 +14,6 @@ import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.core.math.Vector
import ru.dbotthepony.mc.otm.core.getEntitiesInEllipsoid
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.minus
import ru.dbotthepony.mc.otm.core.math.plus
import ru.dbotthepony.mc.otm.core.position

View File

@ -3,6 +3,9 @@ package ru.dbotthepony.mc.otm.android.feature
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.server.level.ServerPlayer
import net.minecraft.sounds.SoundSource
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
@ -11,7 +14,6 @@ import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.config.ClientConfig
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.Vector
import ru.dbotthepony.mc.otm.core.math.plus
import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
@ -55,13 +57,13 @@ class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
override val maxCooldown: Int
get() = (AndroidConfig.JumpBoost.BASE_COOLDOWN - AndroidConfig.JumpBoost.COOLDOWN_REDUCTION * level).coerceAtLeast(0)
override var cooldown by synchronizer.int(setter = setter@{ value, access, setByRemote ->
access.write(value)
override var cooldown by syncher.int(setter = setter@{ access, value ->
access.accept(value)
if (setByRemote) {
if (ply !is ServerPlayer) {
tickCooldownClient = false
}
}).property
})
private var lastGround = false

View File

@ -1,9 +1,10 @@
package ru.dbotthepony.mc.otm.android.feature
import net.minecraft.nbt.CompoundTag
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraftforge.event.entity.living.LivingHurtEvent
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
@ -16,17 +17,15 @@ import ru.dbotthepony.mc.otm.triggers.NanobotsArmorTrigger
import kotlin.math.roundToInt
class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.NANOBOTS_ARMOR, android) {
var strength by synchronizer.int(
setter = setter@{
value, access, _ -> access.write(value.coerceIn(0 .. 3))
}
).property
var strength by syncher.int(
setter = setter@{ access, value -> access.accept(value.coerceIn(0 .. 3)) }
)
var speed: Int = 0
set(value) { field = value.coerceIn(0 .. 3) }
private var ticksPassed = 0
var layers by synchronizer.int().property
var layers by syncher.int()
override fun tickServer() {
if (layers < strength + 1 && android.androidEnergy.extractEnergyExact(ENERGY_PER_LAYER, true)) {
@ -62,7 +61,7 @@ class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(An
}
}
event.amount = event.amount - realAbsorbed
event.amount -= realAbsorbed
(ply as ServerPlayer?)?.awardStat(StatNames.DAMAGE_ABSORBED, (realAbsorbed * 10f).roundToInt())
layers--
}

View File

@ -2,13 +2,13 @@ package ru.dbotthepony.mc.otm.android.feature
import net.minecraft.world.effect.MobEffectInstance
import net.minecraft.world.effect.MobEffects
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
class NightVisionFeature(android: MatteryPlayerCapability) : AndroidSwitchableFeature(AndroidFeatures.NIGHT_VISION, android) {

View File

@ -16,7 +16,7 @@ import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.core.getEntitiesInEllipsoid
import ru.dbotthepony.mc.otm.core.getExplosionResistance
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.Vector
import ru.dbotthepony.mc.otm.core.math.getEllipsoidBlockPositions
import ru.dbotthepony.mc.otm.core.math.minus

View File

@ -6,7 +6,7 @@ import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import java.util.*

View File

@ -7,7 +7,7 @@ import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import java.util.*

View File

@ -1,12 +1,17 @@
package ru.dbotthepony.mc.otm.block.decorative
import net.minecraft.core.BlockPos
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResult
import net.minecraft.world.entity.player.Player
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.EntityBlock
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityTicker
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.BlockHitResult
import net.minecraftforge.fluids.FluidUtil
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.decorative.PainterBlockEntity
@ -15,6 +20,15 @@ class PainterBlock : RotatableMatteryBlock(DEFAULT_MACHINE_PROPERTIES), EntityBl
return PainterBlockEntity(p_153215_, p_153216_)
}
@Suppress("OVERRIDE_DEPRECATION")
override fun use(blockState: BlockState, level: Level, blockPos: BlockPos, ply: Player, hand: InteractionHand, blockHitResult: BlockHitResult): InteractionResult {
if (FluidUtil.interactWithFluidHandler(ply, hand, level, blockPos, blockHitResult.direction)) {
return InteractionResult.sidedSuccess(level.isClientSide)
}
return super.use(blockState, level, blockPos, ply, hand, blockHitResult)
}
override fun <T : BlockEntity?> getTicker(p_153212_: Level, p_153213_: BlockState, p_153214_: BlockEntityType<T>): BlockEntityTicker<T>? {
if (p_153212_.isClientSide) return null
return BlockEntityTicker { p_155253_, p_155254_, p_155255_, p_155256_ -> if (p_155256_ is PainterBlockEntity) p_155256_.tick() }

View File

@ -25,7 +25,7 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.collect.iteratorOf
import ru.dbotthepony.mc.otm.core.get
class TritaniumPressurePlate(color: DyeColor?) : BasePressurePlateBlock(Properties.of(Material.METAL, color ?: DyeColor.LIGHT_BLUE).sound(SoundType.METAL).explosionResistance(80f).noOcclusion().destroyTime(3f).requiresCorrectToolForDrops()) {
class TritaniumPressurePlate(color: DyeColor?) : BasePressurePlateBlock(Properties.of(Material.METAL, color ?: DyeColor.LIGHT_BLUE).sound(SoundType.METAL).explosionResistance(80f).noOcclusion().destroyTime(3f).requiresCorrectToolForDrops().noCollission(), BlockSetType.IRON) {
val tooltips = TooltipList()
override fun appendHoverText(
itemStack: ItemStack,

View File

@ -4,9 +4,8 @@ import com.google.common.collect.ImmutableList
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import it.unimi.dsi.fastutil.longs.Long2ObjectFunction
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import it.unimi.dsi.fastutil.objects.ObjectArraySet
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
import it.unimi.dsi.fastutil.objects.Reference2IntArrayMap
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
import net.minecraft.core.BlockPos
@ -37,12 +36,13 @@ import net.minecraftforge.event.level.ChunkWatchEvent
import net.minecraftforge.event.level.LevelEvent
import net.minecraftforge.event.server.ServerStoppingEvent
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kommons.io.DelegateSyncher
import ru.dbotthepony.kommons.util.Listenable
import ru.dbotthepony.mc.otm.SERVER_IS_LIVE
import ru.dbotthepony.mc.otm.block.INeighbourChangeListener
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.core.ISubscriptable
import ru.dbotthepony.mc.otm.core.collect.WeakHashSet
import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.immutableList
@ -56,9 +56,7 @@ import ru.dbotthepony.mc.otm.core.util.TickList
import ru.dbotthepony.mc.otm.core.util.countingLazy
import ru.dbotthepony.mc.otm.network.BlockEntitySyncPacket
import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
import ru.dbotthepony.mc.otm.once
import ru.dbotthepony.mc.otm.onceServer
import ru.dbotthepony.mc.otm.sometimeServer
import java.lang.ref.WeakReference
import java.util.*
@ -79,7 +77,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
private val sidelessCaps = Reference2ObjectOpenHashMap<Capability<*>, SidelessCap<*>>()
protected val tickList = TickList()
protected val blockStateChangesCounter = IntCounter()
protected val dirtyListeners = ISubscriptable.Impl<Unit>()
protected val dirtyListeners = Listenable.Impl<Unit>()
private val waitForServerLevel = ArrayList<() -> Unit>()
private val _droppableContainers = ObjectArraySet<Container>()
@ -129,9 +127,6 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
open fun tick() {
tickList.tick()
if (synchronizer.isNotEmpty)
synchronizeToPlayers(false)
}
/**
@ -181,7 +176,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
}
}
interface SideListener<T> : Supplier<LazyOptional<T>>, ISubscriptable<LazyOptional<T>>
interface SideListener<T> : Supplier<LazyOptional<T>>, Listenable<LazyOptional<T>>
inner class Side(val side: RelativeSide) {
init {
@ -202,9 +197,9 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
}
}
private val listeners = ISubscriptable.Impl<LazyOptional<T>>()
private val listeners = Listenable.Impl<LazyOptional<T>>()
override fun addListener(listener: Consumer<LazyOptional<T>>): ISubscriptable.L {
override fun addListener(listener: Consumer<LazyOptional<T>>): Listenable.L {
val l = listeners.addListener(listener)
if (level is ServerLevel) listener.accept(value)
return l
@ -488,30 +483,8 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
dirtyListeners.accept(Unit)
}
val synchronizer = FieldSynchronizer {
if (isSynchronizing || tickList.ticks != 0)
return@FieldSynchronizer
if (isRemoved) markSynchronizerClean()
if (level?.isClientSide == false && (_subCache == null || (_subCache ?: throw ConcurrentModificationException()).players.isNotEmpty())) {
onceServer {
if (!isRemoved) {
synchronizeToPlayers(true)
}
}
} else {
markSynchronizerClean()
}
}
private fun markSynchronizerClean() {
synchronizer.markClean()
}
init {
synchronizer.defaultEndpoint.markUnused()
}
val syncher = DelegateSyncher()
private val synchers = Object2ObjectArrayMap<ServerPlayer, DelegateSyncher.Remote>()
override fun setLevel(level: Level) {
val old = this.level
@ -595,59 +568,37 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
return subs
}
private fun synchronizeToPlayers(calledBySynchronizer: Boolean) {
isSynchronizing = true
try {
check(level is ServerLevel) { "Invalid realm or Level is null" }
synchronizer.observe()
val subscription = subscription
if (subscription.players.isNotEmpty() && (playerListUpdated || synchronizer.isDirty)) {
playerListUpdated = false
for (player in subscription.players) {
if (player !in subscription.veto) {
val payload = synchronizer.computeEndpointFor(player).collectNetworkPayload()
if (payload != null) {
GenericNetworkChannel.send(player, BlockEntitySyncPacket(blockPos, payload.array, payload.length))
}
}
}
synchronizer.markClean()
} else if (calledBySynchronizer) {
synchronizer.markClean()
}
} finally {
isSynchronizing = false
}
}
private class ChunkSubscribers(level: ServerLevel, val chunkPos: Long) {
val level = WeakReference(level)
val blockEntities = WeakHashSet<MatteryBlockEntity>(linked = true, initialCapacity = 0)
val players = ObjectArraySet<ServerPlayer>(0)
val veto = ObjectArraySet<ServerPlayer>(0)
val blockEntitiesWithObservers = WeakHashSet<MatteryBlockEntity>(linked = true, initialCapacity = 0)
private val player2ResubCount = Reference2IntArrayMap<ServerPlayer>()
private var isTicking = false
private fun checkShouldTick() {
val shouldTick = blockEntities.isNotEmpty() && players.isNotEmpty()
if (!shouldTick && isTicking) {
isTicking = false
tickingMap[level.get()]?.remove(this)
} else if (shouldTick && !isTicking) {
isTicking = true
tickingMap.computeIfAbsent(level.get()) { ArrayList() }.add(this)
}
}
operator fun component1() = blockEntities
operator fun component2() = players
val hasObservers: Boolean get() {
return blockEntities.any { it.synchronizer.hasObservers }
}
private fun recheckPlayer(player: ServerPlayer) {
sometimeServer {
if (player in players && !player.hasDisconnected()) {
veto.remove(player)
blockEntities.forEach {
it.playerListUpdated = true
it.synchronizeToPlayers(false)
it.synchers[player] =
it.syncher.Remote()
}
} else if (player in players && player.hasDisconnected()) {
unsubscribe(player)
@ -659,6 +610,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
if (players.add(player)) {
veto.add(player)
recheckPlayer(player)
checkShouldTick()
} else if (player !in veto) {
player2ResubCount[player] = player2ResubCount.getInt(player) + 1
LOGGER.debug("{} got subscribed to {} without prior unsubscribing, forcefully resubscribing (this happened {} times)", player, ChunkPos(chunkPos), player2ResubCount.getInt(player))
@ -670,15 +622,13 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
fun unsubscribe(player: ServerPlayer, normal: Boolean = true): Boolean {
if (players.remove(player)) {
veto.remove(player)
if (normal) player2ResubCount.removeInt(player)
blockEntities.forEach {
it.synchronizer.removeEndpointFor(player)
}
if (normal) {
player2ResubCount.removeInt(player)
it.synchers.remove(player)
}
checkShouldTick()
return true
}
@ -686,27 +636,18 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
}
fun subscribe(blockEntity: MatteryBlockEntity) {
if (!blockEntities.add(blockEntity)) return
onceServer {
if (!blockEntity.isRemoved && blockEntity in blockEntities) {
blockEntity.synchronizeToPlayers(false)
if (blockEntities.add(blockEntity)) {
players.forEach {
if (it !in veto) {
blockEntity.synchers[it] = blockEntity.syncher.Remote()
}
}
}
if (blockEntity.synchronizer.hasObservers && blockEntity.tickList.ticks == 0) {
blockEntitiesWithObservers.add(blockEntity)
tickingMap
.computeIfAbsent(level.get() ?: throw NullPointerException("Level got GCd!")) { WeakHashSet(linked = true, initialCapacity = 2) }
.add(this)
}
}
fun unsubscribe(blockEntity: MatteryBlockEntity): Boolean {
blockEntities.remove(blockEntity)
blockEntitiesWithObservers.remove(blockEntity)
checkShouldTick()
return players.isEmpty() && blockEntities.isEmpty()
}
@ -739,7 +680,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
const val LOOT_TABLE_SEED_KEY = RandomizableContainerBlockEntity.LOOT_TABLE_SEED_TAG
private val playerMap = WeakHashMap<ServerLevel, Long2ObjectOpenHashMap<ChunkSubscribers>>()
private val tickingMap = WeakHashMap<ServerLevel, WeakHashSet<ChunkSubscribers>>()
private val tickingMap = WeakHashMap<ServerLevel, ArrayList<ChunkSubscribers>>()
private val vec2Dir = Int2ObjectOpenHashMap<Direction>()
private val LOGGER = LogManager.getLogger()
@ -805,22 +746,20 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
fun postLevelTick(event: LevelTickEvent) {
val level = event.level as? ServerLevel ?: return
val ticking = tickingMap[level] ?: return
ticking.removeIf {
val shouldRemove = it.blockEntitiesWithObservers.isEmpty()
tickingMap[level]?.forEach {
it.blockEntities.forEach { be ->
be.syncher.observe()
if (!shouldRemove && it.players.isNotEmpty()) {
it.blockEntitiesWithObservers.forEach {
it.synchronizeToPlayers(false)
be.synchers.entries.forEach { e ->
val (player, data) = e
val payload = data.write()
if (payload != null) {
GenericNetworkChannel.send(player, BlockEntitySyncPacket(be.blockPos, payload.array, payload.length))
}
}
}
shouldRemove
}
if (ticking.isEmpty()) {
tickingMap.remove(level)
}
}

View File

@ -16,6 +16,8 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.fluids.FluidStack
import net.minecraftforge.fluids.capability.IFluidHandler
import net.minecraftforge.items.IItemHandler
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.capability.item.CombinedItemHandler
import ru.dbotthepony.mc.otm.capability.item.EmptyItemHandler
import ru.dbotthepony.mc.otm.capability.FlowDirection
@ -144,11 +146,11 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
savetables.bool(::automatePush, "fluid_${side}_push")
}
var flow by synchronizer.enum(possibleModes, setter = { value, access, setByRemote ->
var flow by syncher.enum(possibleModes, setter = { access, value ->
require(possibleModes.isSupertype(value)) { "Energy mode $value is not allowed (allowed modes: ${possibleModes.family})" }
if (access.read() != value) {
access.write(value)
if (access.get() != value) {
access.accept(value)
markDirtyFast()
if (value == FlowDirection.NONE) {
@ -180,13 +182,8 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
init {
waitForServerLevel {
redstoneControl.addListener {
updateTickerState()
}
neighbour.addListener {
updateTickerState()
}
redstoneControl.addListener(::updateTickerState)
neighbour.addListener(::updateTickerState)
updateTickerState()
}
@ -384,18 +381,13 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
savetables.bool(::automatePull, "energy_${side}_pull")
savetables.bool(::automatePush, "energy_${side}_push")
dirtyListeners.addListener {
dirtyListeners.addListener(Runnable {
updateTickerState()
}
})
waitForServerLevel {
redstoneControl.addListener {
updateTickerState()
}
neighbour.addListener {
updateTickerState()
}
redstoneControl.addListener(::updateTickerState)
neighbour.addListener(::updateTickerState)
updateTickerState()
}
@ -443,11 +435,11 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
}
}
override var energyFlow by synchronizer.enum(possibleModes, setter = { value, access, setByRemote ->
override var energyFlow by syncher.enum(possibleModes, setter = { access, value ->
require(possibleModes.isSupertype(value)) { "Energy mode $value is not allowed (allowed modes: ${possibleModes.family})" }
if (access.read() != value) {
access.write(value)
if (access.get() != value) {
access.accept(value)
markDirtyFast()
if (value == FlowDirection.NONE) {
@ -462,7 +454,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
updateTickerState()
}
})
}).delegate
fun invalidate(force: Boolean = false) {
if (force) {
@ -611,11 +603,11 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
capController.close()
}
var mode by synchronizer.enum(ItemHandlerMode.DISABLED, setter = { value, access, setByRemote ->
var mode by syncher.enum(ItemHandlerMode.DISABLED, setter = { access, value ->
require(value in possibleViews) { "View type $value is not allowed (allowed views: $possibleViews)" }
if (access.read() != value) {
access.write(value)
if (access.get() != value) {
access.accept(value)
markDirtyFast()
if (value == ItemHandlerMode.DISABLED) {
@ -633,7 +625,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
ItemHandlerMode.BATTERY -> battery!!
}
}
})
}).delegate
var automatePull = false
set(value) {
@ -671,13 +663,8 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
savetables.enum(::mode, "itemhandler_${side}_mode", ItemHandlerMode::valueOf)
waitForServerLevel {
redstoneControl.addListener {
updateTickerState()
}
neighbour.addListener {
updateTickerState()
}
redstoneControl.addListener(::updateTickerState)
neighbour.addListener(::updateTickerState)
updateTickerState()
}

View File

@ -1,26 +1,27 @@
package ru.dbotthepony.mc.otm.block.entity
import it.unimi.dsi.fastutil.booleans.BooleanConsumer
import net.minecraft.nbt.CompoundTag
import net.minecraftforge.common.util.INBTSerializable
import ru.dbotthepony.mc.otm.core.IBooleanSubscriptable
import ru.dbotthepony.mc.otm.core.ISubscriptable
import ru.dbotthepony.kommons.io.DelegateSyncher
import ru.dbotthepony.kommons.util.Listenable
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.core.nbt.mapString
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
import java.util.function.Consumer
interface IRedstoneControlled {
val redstoneControl: AbstractRedstoneControl
}
abstract class AbstractRedstoneControl : INBTSerializable<CompoundTag?>, IBooleanSubscriptable {
abstract class AbstractRedstoneControl : INBTSerializable<CompoundTag?>, Listenable<Boolean> {
abstract var redstoneSetting: RedstoneSetting
abstract var redstoneSignal: Int
protected val listeners = IBooleanSubscriptable.Impl()
protected val listeners = Listenable.Impl<Boolean>()
val isBlockedByRedstone: Boolean get() = !redstoneSetting.test(redstoneSignal)
final override fun addListener(listener: BooleanConsumer): ISubscriptable.L {
final override fun addListener(listener: Consumer<Boolean>): Listenable.L {
return listeners.addListener(listener)
}
@ -77,38 +78,32 @@ class RedstoneControl(private val valueChanges: (new: Boolean, old: Boolean) ->
}
class SynchronizedRedstoneControl(
synchronizer: FieldSynchronizer,
synchronizer: DelegateSyncher,
private val valueChanges: (new: Boolean, old: Boolean) -> Unit,
) : AbstractRedstoneControl() {
override var redstoneSetting: RedstoneSetting by synchronizer.enum(RedstoneSetting.LOW, setter = { value, access, setByRemote ->
if (access.read() == value) return@enum
if (setByRemote) {
access.write(value)
} else {
val old = isBlockedByRedstone
access.write(value)
val state = isBlockedByRedstone
override var redstoneSetting: RedstoneSetting by synchronizer.enum(RedstoneSetting.LOW, setter = { access, value ->
if (access.get() == value) return@enum
if (state != old) {
valueChanges.invoke(state, old)
listeners.accept(state)
}
val old = isBlockedByRedstone
access.accept(value)
val state = isBlockedByRedstone
if (state != old) {
valueChanges.invoke(state, old)
listeners.accept(state)
}
})
}).delegate
override var redstoneSignal: Int by synchronizer.int(0, setter = { value, access, setByRemote ->
if (access.readInt() == value) return@int
if (setByRemote) {
access.write(value)
} else {
val old = isBlockedByRedstone
access.write(value)
val state = isBlockedByRedstone
override var redstoneSignal: Int by synchronizer.int(0, setter = { access, value ->
if (access.get() == value) return@int
if (state != old) {
valueChanges.invoke(state, old)
listeners.accept(state)
}
val old = isBlockedByRedstone
access.accept(value)
val state = isBlockedByRedstone
if (state != old) {
valueChanges.invoke(state, old)
listeners.accept(state)
}
}).property
}).delegate
}

View File

@ -19,6 +19,8 @@ import net.minecraft.world.level.levelgen.structure.BoundingBox
import net.minecraft.world.phys.AABB
import net.minecraft.world.phys.Vec3
import net.minecraftforge.common.Tags
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.block.BlackHoleBlock
import ru.dbotthepony.mc.otm.block.entity.tech.GravitationStabilizerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
@ -34,6 +36,7 @@ import ru.dbotthepony.mc.otm.core.math.getSphericalBlockPositions
import ru.dbotthepony.mc.otm.core.math.times
import ru.dbotthepony.mc.otm.core.nbt.map
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.decimal
import ru.dbotthepony.mc.otm.matter.MatterManager
import ru.dbotthepony.mc.otm.registry.MDamageTypes
import ru.dbotthepony.mc.otm.triggers.BlackHoleTrigger
@ -42,9 +45,9 @@ import kotlin.math.roundToInt
import kotlin.math.sqrt
class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryBlockEntity(MBlockEntities.BLACK_HOLE, p_155229_, p_155230_) {
var mass by synchronizer.decimal(BASELINE_MASS, setter = setter@{ mass, field, setByRemote ->
if (setByRemote) {
field.write(mass)
var mass by syncher.decimal(BASELINE_MASS, setter = setter@{ field, mass ->
if (level !is ServerLevel) {
field.accept(mass)
return@setter
}
@ -53,19 +56,19 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mattery
return@setter
}
field.write(mass)
field.accept(mass)
setChanged()
updateGravStrength()
})
var gravitationStrength by synchronizer.double(1.0).property
var gravitationStrength by syncher.double(1.0).delegate
private set
var affectedBounds = BoundingBox(0, 0, 0, 1, 1, 1)
private set
var affectedBoundsAABB: AABB = AABB.of(affectedBounds)
private set
var spinDirection by synchronizer.bool().property
var spinDirection by syncher.boolean().delegate
private var sphereIterator: Iterator<BlockPos>? = null
private var sleepTicks = 4

View File

@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.block.entity.cable
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.entity.BlockEntityType
@ -23,6 +22,7 @@ import ru.dbotthepony.mc.otm.once
import ru.dbotthepony.mc.otm.onceServer
import java.util.Collections
import java.util.EnumMap
import java.util.function.Consumer
// after some thinking, team decided to settle with IC2's side (techreborn, gregtech, integrated dynamics*, pipez*, p2p tunnels, ...) of implementation,
// where cables have no residue capacitance, and never pull/push energy by themselves
@ -50,7 +50,7 @@ abstract class EnergyCableBlockEntity(type: BlockEntityType<*>, blockPos: BlockP
init {
waitForServerLevel {
neighbour.addListener {
neighbour.addListener(Consumer {
if (isEnabled) {
if (it.isPresent) {
if (it.resolve().get() !is CableSide) {
@ -62,7 +62,7 @@ abstract class EnergyCableBlockEntity(type: BlockEntityType<*>, blockPos: BlockP
updateBlockState(blockRotation.side2Dir(side), it.isPresent || node.neighboursView[GraphNode.link(blockRotation.side2Dir(side))] != null)
}
}
}
})
}
}

View File

@ -12,6 +12,7 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.fluids.FluidStack
import net.minecraftforge.fluids.capability.IFluidHandler
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kommons.util.ListenableDelegate
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.capability.item.CombinedItemHandler
import ru.dbotthepony.mc.otm.capability.fluid.BlockMatteryFluidHandler
@ -27,15 +28,14 @@ import ru.dbotthepony.mc.otm.menu.decorative.FluidTankMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.FLUID_TANK, blockPos, blockState) {
val fluid = BlockMatteryFluidHandler(ItemsConfig::FLUID_TANK_CAPACITY, synchronizer.Field(FluidStack.EMPTY, FluidStackValueCodec, setter = { value, access, remote ->
access.write(value)
val fluid = BlockMatteryFluidHandler(ItemsConfig::FLUID_TANK_CAPACITY, syncher.Slot(ListenableDelegate.SmartBox(FluidStack.EMPTY, setter = { access, value ->
access.accept(value)
level?.lightEngine?.checkBlock(blockPos)
if (!remote) {
if (level is ServerLevel) {
markDirtyFast()
}
}))
}), FluidStackValueCodec))
val fillInput = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer)
val drainInput = MatteryContainer(::markDirtyFast, 1).also(::addDroppableContainer)

View File

@ -3,12 +3,16 @@ package ru.dbotthepony.mc.otm.block.entity.decorative
import net.minecraft.core.BlockPos
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.MenuProvider
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.block.entity.IRedstoneControlled
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.block.entity.SynchronizedRedstoneControl
@ -17,24 +21,23 @@ import ru.dbotthepony.mc.otm.core.math.component1
import ru.dbotthepony.mc.otm.core.math.component2
import ru.dbotthepony.mc.otm.core.math.component3
import ru.dbotthepony.mc.otm.menu.decorative.HoloSignMenu
import ru.dbotthepony.mc.otm.network.synchronizer.FloatFieldAccess
import ru.dbotthepony.mc.otm.once
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MBlocks
class HoloSignBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryBlockEntity(MBlockEntities.HOLO_SIGN, blockPos, blockState), MenuProvider, IRedstoneControlled {
override val redstoneControl = SynchronizedRedstoneControl(synchronizer) { _, _ -> setChanged() }
override val redstoneControl = SynchronizedRedstoneControl(syncher) { _, _ -> setChanged() }
var signText by synchronizer.string("", setter = { value, access, remote ->
var signText by syncher.string("", setter = { access, value ->
setChanged()
access.write(value)
})
access.accept(value)
}).delegate
private fun colorSetter(value: Float, access: FloatFieldAccess, setByRemote: Boolean) {
if (access.readFloat() != value) {
access.write(value)
private fun colorSetter(access: Delegate<Float>, value: Float) {
if (access.get() != value) {
access.accept(value)
if (setByRemote) {
if (level !is ServerLevel) {
markDirtyClientside()
} else {
markDirtyFast()
@ -47,10 +50,10 @@ class HoloSignBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryB
minecraft.levelRenderer.setBlocksDirty(x, y, z, x, y, z)
}
var textRed by synchronizer.float(1f, setter = ::colorSetter).property
var textGreen by synchronizer.float(1f, setter = ::colorSetter).property
var textBlue by synchronizer.float(85f / 255f, setter = ::colorSetter).property
var textAlpha by synchronizer.float(1f).property
var textRed by syncher.float(1f, setter = ::colorSetter).delegate
var textGreen by syncher.float(1f, setter = ::colorSetter).delegate
var textBlue by syncher.float(85f / 255f, setter = ::colorSetter).delegate
var textAlpha by syncher.float(1f).delegate
var isLocked = false

View File

@ -9,6 +9,7 @@ import net.minecraftforge.fluids.capability.IFluidHandler
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import java.util.function.Consumer
class InfiniteWaterSourceBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryBlockEntity(MBlockEntities.INFINITE_WATER_SOURCE, blockPos, blockState), IFluidHandler {
override fun getTanks(): Int {
@ -55,7 +56,7 @@ class InfiniteWaterSourceBlockEntity(blockPos: BlockPos, blockState: BlockState)
}
}
tracker.addListener { ticker.isEnabled = it.isPresent }
tracker.addListener(Consumer { ticker.isEnabled = it.isPresent })
}
}
}

View File

@ -7,6 +7,9 @@ import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.kommons.util.value
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.block.entity.tech.BatteryBankBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
@ -22,7 +25,7 @@ import ru.dbotthepony.mc.otm.menu.matter.MatterCapacitorBankMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.MATTER_CAPACITOR_BANK, p_155229_, p_155230_), IMatterStorage {
var gaugeLevel by synchronizer.float().property
var gaugeLevel by syncher.float()
private set
val matterNode = SimpleMatterNode(matter = this)
@ -123,7 +126,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
val container = object : MatteryContainer(this::markDirtyFast, BatteryBankBlockEntity.CAPACITY) {
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
super.setChanged(slot, new, old)
capacitorStatus[slot].boolean = new.getCapability(MatteryCapability.MATTER).isPresent
capacitorStatus[slot].value = new.getCapability(MatteryCapability.MATTER).isPresent
gaugeLevel = storedMatter.percentage(maxStoredMatter)
}
@ -147,7 +150,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
}))
val capacitorStatus = immutableList(BatteryBankBlockEntity.CAPACITY) {
synchronizer.bool(false)
syncher.boolean(false)
}
init {

View File

@ -11,6 +11,8 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.MatteryCapability
@ -27,6 +29,7 @@ import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.UpgradeContainer
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.util.item
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
import ru.dbotthepony.mc.otm.matter.IMatterValue
import ru.dbotthepony.mc.otm.matter.MatterManager
@ -43,7 +46,7 @@ class MatterReconstructorBlockEntity(blockPos: BlockPos, blockState: BlockState)
private var lastItem: Item? = null
private var initialDamage = 0.0
var visualItemStack by synchronizer.item(observe = false)
var visualItemStack by syncher.item()
private set
var visualProgress = 0f

View File

@ -9,6 +9,8 @@ import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.block.entity.JobContainer
import ru.dbotthepony.mc.otm.block.entity.JobStatus
import ru.dbotthepony.mc.otm.block.entity.ItemJob
@ -26,6 +28,7 @@ import ru.dbotthepony.mc.otm.container.HandlerFilter
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.UpgradeContainer
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.util.item
import ru.dbotthepony.mc.otm.data.DecimalCodec
import ru.dbotthepony.mc.otm.data.UUIDCodec
import ru.dbotthepony.mc.otm.data.minRange
@ -142,10 +145,10 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
visualProgress = 0f
}
var visualItemStack by synchronizer.item(observe = false)
var visualItemStack by syncher.item()
private set
var visualProgress by synchronizer.float().property
var visualProgress by syncher.float()
private set
var renderRotation = 0f

View File

@ -7,6 +7,8 @@ import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.block.entity.JobContainer
import ru.dbotthepony.mc.otm.block.entity.JobStatus
import ru.dbotthepony.mc.otm.block.entity.ItemJob
@ -21,6 +23,7 @@ import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.HandlerFilter
import ru.dbotthepony.mc.otm.container.UpgradeContainer
import ru.dbotthepony.mc.otm.core.util.item
import ru.dbotthepony.mc.otm.menu.matter.MatterScannerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
@ -162,10 +165,10 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
visualProgress = 0f
}
var visualItemStack by synchronizer.item(observe = false)
var visualItemStack by syncher.item()
private set
var visualProgress by synchronizer.float().property
var visualProgress by syncher.float()
private set
override fun onJobTick(status: JobStatus<ItemJob>, id: Int) {

View File

@ -21,6 +21,7 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.storage.optics.priority
import ru.dbotthepony.mc.otm.storage.optics.powered
import ru.dbotthepony.mc.otm.storage.optics.flow
import java.util.function.Consumer
class DriveRackBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.DRIVE_RACK, blockPos, blockState) {
override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, MachinesConfig.DRIVE_RACK))
@ -67,9 +68,9 @@ class DriveRackBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
savetables.int(::extractPriority)
savetables.enum(::mode, map = FlowDirection::valueOf)
redstoneControl.addListener {
redstoneControl.addListener(Consumer {
cell.isDetached = it
}
})
}
override fun setLevel(level: Level) {

View File

@ -34,6 +34,7 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.storage.*
import java.math.BigInteger
import java.util.*
import java.util.function.Consumer
import java.util.stream.Stream
private data class SlotTuple(val slot: Int, val stack: ItemStack)
@ -101,24 +102,24 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
savetables.int(::extractPriority)
exposeGlobally(MatteryCapability.STORAGE_NODE, cell) { it != RelativeSide.FRONT }
side(RelativeSide.FRONT).track(ForgeCapabilities.ITEM_HANDLER).addListener {
side(RelativeSide.FRONT).track(ForgeCapabilities.ITEM_HANDLER).addListener(Consumer {
component?.let(cell::removeStorageComponent)
component = if (it.isPresent) {
ItemHandlerComponent(it.orThrow()).also { if (!redstoneControl.isBlockedByRedstone) cell.addStorageComponent(it) }
} else {
null
}
}
})
redstoneControl.addListener {
val component = component ?: return@addListener
redstoneControl.addListener(Consumer {
val component = component ?: return@Consumer
if (it) {
cell.removeStorageComponent(component)
} else {
cell.addStorageComponent(component)
}
}
})
}
val filter = ItemFilter(MAX_FILTERS) {

View File

@ -14,6 +14,8 @@ import net.minecraft.world.item.crafting.SmokingRecipe
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.ForgeCapabilities
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.block.entity.ExperienceStorage
import ru.dbotthepony.mc.otm.block.entity.JobContainer
import ru.dbotthepony.mc.otm.block.entity.JobStatus
@ -32,8 +34,10 @@ import ru.dbotthepony.mc.otm.container.UpgradeContainer
import ru.dbotthepony.mc.otm.container.balance
import ru.dbotthepony.mc.otm.core.collect.filter
import ru.dbotthepony.mc.otm.core.collect.maybe
import ru.dbotthepony.mc.otm.core.getValue
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.value
import ru.dbotthepony.mc.otm.core.util.item
import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu
import ru.dbotthepony.mc.otm.recipe.MatteryCookingRecipe
import ru.dbotthepony.mc.otm.recipe.MicrowaveRecipe
@ -61,9 +65,9 @@ sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : Ma
}
inner class SyncSlot {
var inputItem by synchronizer.item(observe = false)
var outputItem by synchronizer.item(observe = false)
var progress by synchronizer.float().property
var inputItem by syncher.item()
var outputItem by syncher.item()
var progress by syncher.float()
var visualRotation = 0f
}

View File

@ -7,6 +7,9 @@ import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.ForgeCapabilities
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.kommons.util.value
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.energy
@ -25,14 +28,14 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities
import java.util.function.Supplier
class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.BATTERY_BANK, p_155229_, p_155230_), IMatteryEnergyStorage {
var gaugeLevel by synchronizer.float().property
var gaugeLevel by syncher.float()
private set
// 6 на 2
val container: MatteryContainer = object : MatteryContainer(::setChanged, CAPACITY) {
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
super.setChanged(slot, new, old)
batteryStatus[slot].boolean = new.getCapability(ForgeCapabilities.ENERGY).isPresent
batteryStatus[slot].value = new.getCapability(ForgeCapabilities.ENERGY).isPresent
gaugeLevel = batteryLevel.percentage(maxBatteryLevel)
}
@ -40,7 +43,7 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
}.also(::addDroppableContainer)
val batteryStatus = immutableList(CAPACITY) {
synchronizer.bool(false)
syncher.boolean(false)
}
val itemConfig = ConfigurableItemHandler(inputOutput = container.handler(HandlerFilter.Dischargeable))

View File

@ -0,0 +1,239 @@
package ru.dbotthepony.mc.otm.block.entity.tech
import it.unimi.dsi.fastutil.objects.ObjectArrayList
import it.unimi.dsi.fastutil.objects.ObjectArraySet
import net.minecraft.core.BlockPos
import net.minecraft.core.SectionPos
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.core.Multiblock
import ru.dbotthepony.mc.otm.core.MultiblockBuilder
import ru.dbotthepony.mc.otm.core.getBlockStateNow
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.plus
import ru.dbotthepony.mc.otm.core.math.times
import ru.dbotthepony.mc.otm.core.multiblockConfiguration
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MBlocks
class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.BLACK_HOLE_GENERATOR, blockPos, blockState) {
private var multiblock: Multiblock? = null
private var lastRange = -1
private fun findBlackHoleRange(): Int {
val normal = blockRotation.normal
val level = level!!
if (lastRange != -1) {
val pos = blockPos + normal * lastRange
if (level.getBlockStateNow(pos).block == MBlocks.BLACK_HOLE) {
return lastRange
}
}
for (i in 5 until 64) {
val pos = blockPos + normal * i
if (level.getBlockStateNow(pos).block == MBlocks.BLACK_HOLE) {
return i
}
}
return -1
}
override fun tick() {
super.tick()
val level = level!!
if (lastRange == -1) {
val found = findBlackHoleRange()
if (found != -1) {
lastRange = found
multiblock = CONFIGURATIONS[found - 5].value.create(blockPos)
} else {
multiblock = null
}
}
val multiblock = multiblock
if (multiblock != null) {
if (!multiblock.update(level, blockRotation.front)) {
val found = findBlackHoleRange()
if (found == -1) {
this.multiblock = null
} else if (found != lastRange) {
lastRange = found
this.multiblock = CONFIGURATIONS[found - 5].value.create(blockPos)
}
} else {
val blackHole = multiblock.blockEntities(BLACK_HOLE).first()
val matterHatches = multiblock.blockEntities(MatterHatchBlockEntity.INPUT_TAG)
val energyHatches = multiblock.blockEntities(EnergyHatchBlockEntity.OUTPUT_TAG)
if (matterHatches.isEmpty() || energyHatches.isEmpty()) return
var required = MachinesConfig.BlackHoleGenerator.MATTER_RATE
for (hatch in matterHatches) {
required -= hatch.matter.extractMatter(required, true)
if (required <= Decimal.ZERO) break
}
if (required > Decimal.ZERO) return
var energyLeftover = blackHole.mass / MachinesConfig.BlackHoleGenerator.MASS_DIVISOR
for (hatch in energyHatches) {
energyLeftover -= hatch.energy.receiveEnergy(energyLeftover, true)
if (energyLeftover <= Decimal.ZERO) break
}
if (energyLeftover > Decimal.ZERO) return
required = MachinesConfig.BlackHoleGenerator.MATTER_RATE
for (hatch in matterHatches) {
required -= hatch.matter.extractMatter(required, false)
if (required <= Decimal.ZERO) break
}
energyLeftover = blackHole.mass / MachinesConfig.BlackHoleGenerator.MASS_DIVISOR
for (hatch in energyHatches) {
energyLeftover -= hatch.energy.receiveEnergy(energyLeftover, false)
if (energyLeftover <= Decimal.ZERO) break
}
blackHole.mass += MachinesConfig.BlackHoleGenerator.MASS_FEEDING_RATIO * MachinesConfig.BlackHoleGenerator.MATTER_RATE
}
}
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? {
return null
}
companion object {
val BLACK_HOLE = MultiblockBuilder.EntityTag(BlackHoleBlockEntity::class)
private fun points(x: Int, z: Int, result: ObjectArraySet<BlockPos>) {
if (x == 0) {
result.add(BlockPos(0, 0, z))
result.add(BlockPos(0, 0, -z))
result.add(BlockPos(z, 0, 0))
result.add(BlockPos(-z, 0, 0))
} else if (x == z) {
result.add(BlockPos(x, 0, z))
result.add(BlockPos(-x, 0, z))
result.add(BlockPos(x, 0, -z))
result.add(BlockPos(-x, 0, -z))
} else if (x < z) {
result.add(BlockPos(x, 0, z))
result.add(BlockPos(-x, 0, z))
result.add(BlockPos(x, 0, -z))
result.add(BlockPos(-x, 0, -z))
result.add(BlockPos(z, 0, x))
result.add(BlockPos(-z, 0, x))
result.add(BlockPos(z, 0, -x))
result.add(BlockPos(-z, 0, -x))
}
}
private fun ring(size: Int): ObjectArrayList<BlockPos> {
val positions = ObjectArraySet<BlockPos>()
var x = 0
var y = size
var p = (5 - size * 4) / 4
points(x, y, positions)
while (x < y) {
x++
if (p < 0) {
p += x * 2 + 1
} else {
y--
p += (x - y) * 2 + 1
}
points(x, y, positions)
}
val result = ObjectArrayList<BlockPos>(positions.size)
for (pos in positions) {
if (pos.x == 0 && pos.z + size == 0) continue
result.add(BlockPos(pos.x, 0, pos.z + size))
}
return result
}
val CONFIGURATIONS = immutableList {
for (i2 in 0 until 59) {
val i = i2 + 5
accept(lazy {
multiblockConfiguration {
builder.customCheck {
val blocks = it.blocks()
blocks.getInt(MBlocks.MATTER_INJECTOR) == 1 &&
blocks.getInt(MBlocks.ANTIMATTER_INJECTOR) == 1 &&
blocks.getInt(MBlocks.HIGH_ENERGY_PARTICLE_COLLECTOR) == 1
}
block(MBlocks.BLACK_HOLE_GENERATOR)
relative(BlockPos(0, 0, i)) {
block(MBlocks.BLACK_HOLE)
tag(BLACK_HOLE)
}
val ring = ring(i)
for (pos in ring) {
val node = relative(pos)
if ((pos.x == i || pos.x == -i) && pos.z == i) {
node.block(MBlocks.MATTER_INJECTOR)
node.block(MBlocks.ANTIMATTER_INJECTOR)
node.tagBlock()
} else if (pos.x == 0 && pos.z == i * 2) {
node.block(MBlocks.HIGH_ENERGY_PARTICLE_COLLECTOR)
node.tagBlock()
} else if (pos.x == i || pos.x == -i || pos.z == i * 2 || pos.z == 0) {
node.or {
block(MBlocks.ENERGY_OUTPUT_HATCH)
tag(EnergyHatchBlockEntity.OUTPUT_TAG)
}
node.or {
block(MBlocks.MATTER_INPUT_HATCH)
tag(MatterHatchBlockEntity.INPUT_TAG)
}
node.block(MBlocks.MULTIBLOCK_STRUCTURE)
} else {
node.block(MBlocks.MULTIBLOCK_STRUCTURE)
}
}
}
})
}
}
}
}

View File

@ -10,6 +10,8 @@ import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.ForgeCapabilities
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.block.tech.EnergyCounterBlock
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.capability.*
@ -23,12 +25,13 @@ import ru.dbotthepony.mc.otm.core.nbt.map
import ru.dbotthepony.mc.otm.core.nbt.mapPresent
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.countingLazy
import ru.dbotthepony.mc.otm.core.util.decimal
import ru.dbotthepony.mc.otm.menu.tech.EnergyCounterMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import java.util.*
class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.ENERGY_COUNTER, p_155229_, p_155230_) {
var passed by synchronizer.decimal()
var passed by syncher.decimal()
override val blockRotation: BlockRotation by countingLazy(blockStateChangesCounter) {
BlockRotation.of(blockState[EnergyCounterBlock.INPUT_DIRECTION])
@ -37,7 +40,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
private val history = Array(10 * 20) { Decimal.ZERO }
internal var historyTick = 0
var lastTick by synchronizer.decimal()
var lastTick by syncher.decimal()
internal set
var ioLimit: Decimal? = null

View File

@ -0,0 +1,87 @@
package ru.dbotthepony.mc.otm.block.entity.tech
import net.minecraft.core.BlockPos
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.ForgeCapabilities
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
import ru.dbotthepony.mc.otm.capability.moveEnergy
import ru.dbotthepony.mc.otm.config.EnergyBalanceValues
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.container.HandlerFilter
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.MultiblockBuilder
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.menu.tech.EnergyHatchMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
class EnergyHatchBlockEntity(
val isInput: Boolean,
capacity: EnergyBalanceValues,
type: BlockEntityType<*>,
blockPos: BlockPos,
blockState: BlockState
) : MatteryDeviceBlockEntity(type, blockPos, blockState) {
val energy = ProfiledEnergyStorage(BlockEnergyStorageImpl(this::markDirtyFast, FlowDirection.input(isInput), capacity))
val container = object : MatteryContainer(this::markDirtyFast, CAPACITY) {
override fun getMaxStackSize(slot: Int, itemStack: ItemStack): Int {
return 1
}
}.also(::addDroppableContainer)
val itemHandler = container.handler(if (isInput) HandlerFilter.Dischargeable else HandlerFilter.Chargeable)
init {
savetables.stateful(::energy, ENERGY_KEY)
savetables.stateful(::container, BATTERY_KEY)
// it would cause a lot of frustration if hatches accept stuff only though one face
exposeGlobally(ForgeCapabilities.ENERGY, energy)
exposeGlobally(MatteryCapability.ENERGY, energy)
exposeGlobally(ForgeCapabilities.ITEM_HANDLER, itemHandler)
}
override fun tick() {
super.tick()
if (!redstoneControl.isBlockedByRedstone) {
container.forEach {
it.getCapability(ForgeCapabilities.ENERGY).ifPresentK {
if (isInput) {
moveEnergy(it, energy, simulate = false)
} else {
moveEnergy(energy, it, simulate = false)
}
}
}
}
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return EnergyHatchMenu(isInput, containerID, inventory, this)
}
companion object {
const val CAPACITY = 1
val INPUT_TAG = MultiblockBuilder.EntityTag(EnergyHatchBlockEntity::class) { it.isInput }
val OUTPUT_TAG = MultiblockBuilder.EntityTag(EnergyHatchBlockEntity::class) { !it.isInput }
fun input(blockPos: BlockPos, blockState: BlockState): EnergyHatchBlockEntity {
return EnergyHatchBlockEntity(true, MachinesConfig.ENERGY_HATCH, MBlockEntities.ENERGY_INPUT_HATCH, blockPos, blockState)
}
fun output(blockPos: BlockPos, blockState: BlockState): EnergyHatchBlockEntity {
return EnergyHatchBlockEntity(false, MachinesConfig.ENERGY_HATCH, MBlockEntities.ENERGY_OUTPUT_HATCH, blockPos, blockState)
}
}
}

View File

@ -0,0 +1,50 @@
package ru.dbotthepony.mc.otm.block.entity.tech
import net.minecraft.core.BlockPos
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.ForgeCapabilities
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity
import ru.dbotthepony.mc.otm.container.HandlerFilter
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.MultiblockBuilder
import ru.dbotthepony.mc.otm.menu.tech.ItemHatchMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
class ItemHatchBlockEntity(
val isInput: Boolean,
type: BlockEntityType<*>,
blockPos: BlockPos,
blockState: BlockState
) : MatteryDeviceBlockEntity(type, blockPos, blockState) {
val container = MatteryContainer(this::markDirtyFast, CAPACITY).also(::addDroppableContainer)
val itemHandler = container.handler(if (isInput) HandlerFilter.OnlyIn else HandlerFilter.OnlyOut)
init {
savetables.stateful(::container, INVENTORY_KEY)
exposeGlobally(ForgeCapabilities.ITEM_HANDLER, itemHandler)
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return ItemHatchMenu(isInput, containerID, inventory, this)
}
companion object {
const val CAPACITY = CargoCrateBlockEntity.CAPACITY
val INPUT_TAG = MultiblockBuilder.EntityTag(ItemHatchBlockEntity::class) { it.isInput }
val OUTPUT_TAG = MultiblockBuilder.EntityTag(ItemHatchBlockEntity::class) { !it.isInput }
fun input(blockPos: BlockPos, blockState: BlockState): ItemHatchBlockEntity {
return ItemHatchBlockEntity(true, MBlockEntities.ITEM_INPUT_HATCH, blockPos, blockState)
}
fun output(blockPos: BlockPos, blockState: BlockState): ItemHatchBlockEntity {
return ItemHatchBlockEntity(false, MBlockEntities.ITEM_OUTPUT_HATCH, blockPos, blockState)
}
}
}

View File

@ -0,0 +1,89 @@
package ru.dbotthepony.mc.otm.block.entity.tech
import net.minecraft.core.BlockPos
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.ForgeCapabilities
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.matter.MatterStorageImpl
import ru.dbotthepony.mc.otm.capability.matter.ProfiledMatterStorage
import ru.dbotthepony.mc.otm.capability.moveMatter
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.container.HandlerFilter
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.MultiblockBuilder
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.menu.tech.MatterHatchMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
class MatterHatchBlockEntity(
val isInput: Boolean,
type: BlockEntityType<*>,
blockPos: BlockPos,
blockState: BlockState
) : MatteryDeviceBlockEntity(type, blockPos, blockState) {
val container = object : MatteryContainer(this::markDirtyFast, CAPACITY) {
override fun getMaxStackSize(slot: Int, itemStack: ItemStack): Int {
return 1
}
}.also(::addDroppableContainer)
val matter = ProfiledMatterStorage(MatterStorageImpl(this::markDirtyFast, FlowDirection.input(isInput), MachinesConfig::MATTER_HATCH))
val itemHandler = if (isInput) {
container.handler(HandlerFilter.MatterProviders)
} else {
container.handler(HandlerFilter.MatterConsumers)
}
init {
savetables.stateful(::container, INVENTORY_KEY)
savetables.stateful(::matter, MATTER_STORAGE_KEY)
// it would cause a lot of frustration if hatches accept stuff only though one face
exposeGlobally(ForgeCapabilities.ITEM_HANDLER, itemHandler)
exposeGlobally(MatteryCapability.MATTER, matter)
}
override fun tick() {
super.tick()
if (!redstoneControl.isBlockedByRedstone && matter.missingMatter > Decimal.ZERO) {
container.forEach {
it.getCapability(MatteryCapability.MATTER).ifPresentK {
if (isInput) {
moveMatter(it, matter, simulate = false)
} else {
moveMatter(matter, it, simulate = false)
}
}
}
}
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return MatterHatchMenu(isInput, containerID, inventory, this)
}
companion object {
const val CAPACITY = 1
val INPUT_TAG = MultiblockBuilder.EntityTag(MatterHatchBlockEntity::class) { it.isInput }
val OUTPUT_TAG = MultiblockBuilder.EntityTag(MatterHatchBlockEntity::class) { !it.isInput }
fun input(blockPos: BlockPos, blockState: BlockState): MatterHatchBlockEntity {
return MatterHatchBlockEntity(true, MBlockEntities.ITEM_INPUT_HATCH, blockPos, blockState)
}
fun output(blockPos: BlockPos, blockState: BlockState): MatterHatchBlockEntity {
return MatterHatchBlockEntity(false, MBlockEntities.ITEM_OUTPUT_HATCH, blockPos, blockState)
}
}
}

View File

@ -0,0 +1,56 @@
package ru.dbotthepony.mc.otm.block.tech
import net.minecraft.core.BlockPos
import net.minecraft.core.SectionPos
import net.minecraft.world.item.context.BlockPlaceContext
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.EntityBlock
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityTicker
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.material.Material
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity
import ru.dbotthepony.mc.otm.block.entity.tech.BlackHoleGeneratorBlockEntity
import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
import ru.dbotthepony.mc.otm.core.math.plus
import ru.dbotthepony.mc.otm.core.math.times
class BlackHoleGeneratorBlock : RotatableMatteryBlock(Properties.of(Material.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(160.0f)), EntityBlock {
override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity {
return BlackHoleGeneratorBlockEntity(blockPos, blockState)
}
override fun <T : BlockEntity?> getTicker(level: Level, blockState: BlockState, blockEntityType: BlockEntityType<T>): BlockEntityTicker<T>? {
if (level.isClientSide)
return null
return BlockEntityTicker { _, _, _, tile -> if (tile is BlackHoleGeneratorBlockEntity) tile.tick() }
}
override fun getStateForPlacement(context: BlockPlaceContext): BlockState? {
var state = super.getStateForPlacement(context) ?: return null
val blockPos = context.clickedPos
val level = context.level
for (face in BlockRotationFreedom.HORIZONTAL.possibleValues) {
val dir = face.normal
for (i in 4 ..64) {
val pos = blockPos + dir * i
val chunk = level.chunkSource.getChunkNow(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z)) ?: continue
val getState = chunk.getBlockState(pos)
if (!getState.isAir) {
if (chunk.getBlockEntity(pos) is BlackHoleBlockEntity) {
state = state.setValue(BlockRotationFreedom.HORIZONTAL.property, face)
break
}
}
}
}
return state
}
}

View File

@ -0,0 +1,37 @@
package ru.dbotthepony.mc.otm.block.tech
import net.minecraft.ChatFormatting
import net.minecraft.core.BlockPos
import net.minecraft.world.item.context.BlockPlaceContext
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.EntityBlock
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityTicker
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.material.Material
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.core.TranslatableComponent
class HatchBlock(val factory: BlockEntityType.BlockEntitySupplier<out MatteryBlockEntity>, val needsTicking: Boolean = false) : RotatableMatteryBlock(Properties.of(Material.METAL).requiresCorrectToolForDrops().destroyTime(2.5f).explosionResistance(80.0f)), EntityBlock {
override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity {
return factory.create(blockPos, blockState)
}
override fun <T : BlockEntity?> getTicker(level: Level, blockState: BlockState, type: BlockEntityType<T>): BlockEntityTicker<T>? {
if (needsTicking && !level.isClientSide) {
return BlockEntityTicker { _, _, _, tile -> if (tile is MatteryBlockEntity) tile.tick() }
}
return null
}
override fun faceToPlayer(context: BlockPlaceContext): Boolean {
return true
}
init {
tooltips.add(TranslatableComponent("otm.gui.part_of_multiblock").withStyle(ChatFormatting.GRAY))
}
}

View File

@ -126,6 +126,8 @@ abstract class AbstractProfiledStorage<out P>(val parent: P) : INBTSerializable<
historyTransferInternal[i] = Decimal.deserializeNBT(it[i])
}
}
startTicking()
}
}

View File

@ -15,6 +15,7 @@ import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.fluid.iterator
import ru.dbotthepony.mc.otm.capability.fluid.stream
import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorAwareStream
import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorStream
@ -289,6 +290,30 @@ fun moveEnergy(source: IEnergyStorage, destination: IEnergyStorage, amount: Deci
return Decimal.ZERO
}
@Suppress("name_shadowing")
fun moveMatter(source: IMatterStorage, destination: IMatterStorage, amount: Decimal = Decimal.LONG_MAX_VALUE.coerceAtLeast(source.storedMatter), simulate: Boolean, ignoreFlowRestrictions: Boolean = false): Decimal {
val extracted = if (ignoreFlowRestrictions) source.extractMatter(amount, true) else source.extractMatterChecked(amount, true)
if (extracted.isPositive) {
val received = destination.receiveMatterChecked(extracted, true)
if (received.isPositive) {
val extracted = if (ignoreFlowRestrictions) source.extractMatter(received, true) else source.extractMatterChecked(received, true)
if (extracted.isPositive) {
if (simulate) {
return extracted
}
val extracted = if (ignoreFlowRestrictions) source.extractMatter(received, false) else source.extractMatterChecked(received, false)
return destination.receiveMatterChecked(extracted, false)
}
}
}
return Decimal.ZERO
}
internal fun IFluidHandler.fluidLevel(tooltips: (Component) -> Unit) {
val fluid = getFluidInTank(0)

View File

@ -4,7 +4,7 @@ import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
import it.unimi.dsi.fastutil.ints.IntSet
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import net.minecraft.ChatFormatting
import net.minecraft.client.model.PlayerModel
import net.minecraft.client.player.AbstractClientPlayer
@ -62,6 +62,18 @@ import net.minecraftforge.registries.ForgeRegistries
import net.minecraftforge.server.command.EnumArgument
import org.apache.logging.log4j.LogManager
import org.joml.Vector4f
import ru.dbotthepony.kommons.collect.ListenableMap
import ru.dbotthepony.kommons.collect.ListenableSet
import ru.dbotthepony.kommons.io.DelegateSyncher
import ru.dbotthepony.kommons.io.IntValueCodec
import ru.dbotthepony.kommons.io.RGBCodec
import ru.dbotthepony.kommons.io.UUIDValueCodec
import ru.dbotthepony.kommons.io.VarIntValueCodec
import ru.dbotthepony.kommons.io.nullable
import ru.dbotthepony.kommons.util.ListenableDelegate
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.kommons.util.value
import ru.dbotthepony.mc.otm.*
import ru.dbotthepony.mc.otm.android.AndroidFeature
import ru.dbotthepony.mc.otm.android.AndroidFeatureType
@ -91,25 +103,20 @@ import ru.dbotthepony.mc.otm.container.vanishCursedItems
import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.collect.UUIDIntModifiersMap
import ru.dbotthepony.mc.otm.core.collect.filter
import ru.dbotthepony.mc.otm.core.math.RGBColorDFUCodec
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.minus
import ru.dbotthepony.mc.otm.core.nbt.getCompoundList
import ru.dbotthepony.mc.otm.core.nbt.getIntList
import ru.dbotthepony.mc.otm.core.nbt.getStringList
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.IntValueCodec
import ru.dbotthepony.mc.otm.core.util.ItemValueCodec
import ru.dbotthepony.mc.otm.core.util.RGBCodec
import ru.dbotthepony.mc.otm.core.util.Savetables
import ru.dbotthepony.mc.otm.core.util.TickList
import ru.dbotthepony.mc.otm.core.util.UUIDValueCodec
import ru.dbotthepony.mc.otm.core.util.VarIntValueCodec
import ru.dbotthepony.mc.otm.menu.ExopackInventoryMenu
import ru.dbotthepony.mc.otm.menu.IItemStackSortingSettings
import ru.dbotthepony.mc.otm.network.*
import ru.dbotthepony.mc.otm.network.SmokeParticlesPacket.Companion.makeSmoke
import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MDamageTypes
import ru.dbotthepony.mc.otm.registry.MItems
@ -199,7 +206,12 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
* any differences in field order/types/etc between client and server
* will break *everything*
*/
val synchronizer = FieldSynchronizer()
val syncher = DelegateSyncher()
/**
* Remote for "this" player
*/
val privateSyncherRemote = syncher.Remote()
/**
* For fields that need to be synchronized to everyone
@ -208,7 +220,10 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
* any differences in field order/types/etc between client and server
* will break *everything*
*/
val publicSynchronizer = FieldSynchronizer()
val publicSyncher = DelegateSyncher()
val publicSyncherRemote = publicSyncher.Remote()
val remoteSynchers = Object2ObjectArrayMap<ServerPlayer, DelegateSyncher.Remote>()
/**
* For data to be stored to and loaded from NBT automatically
@ -218,8 +233,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
/**
* Whenever player has Exopack
*/
var hasExopack by publicSynchronizer.bool(setter = setter@{ value, access, _ ->
access.write(value)
var hasExopack by publicSyncher.boolean(setter = setter@{ access, value ->
access.accept(value)
_exoPackMenu = null
if (value && ply is ServerPlayer) {
@ -227,32 +242,34 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
ExopackObtainedTrigger.trigger(ply)
}
}
}).property
})
/**
* Whenever to render Exopack on player
*/
var isExopackVisible by publicSynchronizer.bool(true).property
var isExopackVisible by publicSyncher.boolean(true)
/**
* Whenever to render Exopack glow in dark
*/
var exopackGlows by publicSynchronizer.bool(true).property
var exopackGlows by publicSyncher.boolean(true)
var exopackColor by publicSynchronizer.Field(null, RGBCodec.nullable)
var exopackColor by publicSyncher.add(ListenableDelegate.Box(null), RGBCodec.nullable())
/**
* Tick event schedulers
*/
val tickList = TickList()
private val exopackSlotModifierMap: MutableMap<UUID, Int> by synchronizer.Map(
// kotlin moment
private fun _recomputeModifiers() {
exopackSlotModifier.recompute()
}
private val exopackSlotModifierMap = syncher.MapSlot(
ListenableMap<UUID, Int>().also { it.addListener(Runnable { _recomputeModifiers() }) },
keyCodec = UUIDValueCodec,
valueCodec = IntValueCodec,
backingMap = HashMap(),
callback = {
this.exopackSlotModifier.recompute()
},
)
/**
@ -266,16 +283,16 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
} else {
exopackContainer = PlayerMatteryContainer(it)
}
}, backingMap = this.exopackSlotModifierMap)
}, backingMap = this.exopackSlotModifierMap.delegate)
val regularSlotFilters = immutableList(Inventory.INVENTORY_SIZE) {
synchronizer.Field(null, ItemValueCodec.nullable)
syncher.add(null, ItemValueCodec.nullable())
}
val slotsChargeFlag by synchronizer.Set(
codec = VarIntValueCodec,
backingSet = IntAVLTreeSet(),
)
val slotsChargeFlag = syncher.SetSlot(
ListenableSet(IntAVLTreeSet()),
VarIntValueCodec,
).delegate
private fun slotChargeToDefault() {
// броня
@ -310,7 +327,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
}
value.deserializeNBT(field.serializeNBT())
value.addFilterSynchronizer(synchronizer)
value.addFilterSynchronizer(syncher)
field = value
_combinedInventory = null
@ -372,9 +389,9 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
/**
* Whenever Exopack has 3x3 crafting grid upgrade installed
*/
var isExopackCraftingUpgraded by publicSynchronizer.bool(setter = setter@{ value, access, _ ->
if (value != access.readBoolean()) {
access.write(value)
var isExopackCraftingUpgraded by publicSyncher.boolean(setter = setter@{ access, value ->
if (value != access.get()) {
access.accept(value)
_exoPackMenu = null
if (value && ply is ServerPlayer) {
@ -383,11 +400,11 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
}
}
}
}).property
})
var isExopackEnderAccessInstalled by publicSynchronizer.bool(setter = setter@{ value, access, _ ->
if (value != access.readBoolean()) {
access.write(value)
var isExopackEnderAccessInstalled by publicSyncher.boolean(setter = setter@{ access, value ->
if (value != access.get()) {
access.accept(value)
_exoPackMenu = null
if (value && ply is ServerPlayer) {
@ -396,7 +413,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
}
}
}
}).property
})
private var _exoPackMenu: ExopackInventoryMenu? = null
set(value) {
@ -440,11 +457,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
private var nextDischargeHurt = 20
private var nextHealTick = 0
// players tracking us
// stored separately because EntityTracker and ChunkMup, etc are buried deep and
// getting them unburied will be a very work intense task
private val trackingPlayers = Reference2ObjectOpenHashMap<ServerPlayer, FieldSynchronizer.Endpoint>()
/**
* This returns if player is an Android or will become one on death/sleep/etc
*/
@ -470,7 +482,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
/**
* Whenever player should become an Android once transformation conditions are met (e.g. player dies or sleeps in bed)
*/
var willBecomeAndroid by publicSynchronizer.bool().property
var willBecomeAndroid by publicSyncher.boolean()
/**
* Whenever player is an Android
@ -486,14 +498,14 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
*
* Android-immune (de)buffs are specified in `data/overdrive_that_matters/tags/mob_effect/android_immune_effects.json`
*/
var isAndroid by publicSynchronizer.bool().property
var isAndroid by publicSyncher.boolean()
/**
* Whenever player has exosuit smelting upgrade
*/
var isExopackSmeltingInstalled by synchronizer.bool(setter = { value, access, _ ->
if (value != access.readBoolean()) {
access.write(value)
var isExopackSmeltingInstalled by syncher.boolean(setter = { access, value ->
if (value != access.get()) {
access.accept(value)
_exoPackMenu = null
if (value && ply is ServerPlayer) {
@ -502,7 +514,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
}
}
}
}).property
})
inner class SmelterBelt(index: Int) : MachineJobEventLoop<ItemJob>(ItemJob.CODEC) {
override val energy: IMatteryEnergyStorage
@ -567,12 +579,12 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
/**
* [IMatteryEnergyStorage] instance, representing Android' battery charge
*/
val androidEnergy = BatteryBackedEnergyStorage(ply, synchronizer, AndroidConfig.ANDROID_MAX_ENERGY, AndroidConfig.ANDROID_MAX_ENERGY, true)
val androidEnergy = BatteryBackedEnergyStorage(ply, syncher, AndroidConfig.ANDROID_MAX_ENERGY, AndroidConfig.ANDROID_MAX_ENERGY, true)
/**
* [IMatteryEnergyStorage] instance, representing Exopack battery charge
*/
val exopackEnergy = ProfiledEnergyStorage(BatteryBackedEnergyStorage(ply, synchronizer, Decimal.ZERO, ExopackConfig.ENERGY_CAPACITY, false, onChange = { for (v in smelters) v.notify(MachineJobEventLoop.IdleReason.POWER) }))
val exopackEnergy = ProfiledEnergyStorage(BatteryBackedEnergyStorage(ply, syncher, Decimal.ZERO, ExopackConfig.ENERGY_CAPACITY, false, onChange = { for (v in smelters) v.notify(MachineJobEventLoop.IdleReason.POWER) }))
val exopackChargeSlots = MatteryContainer(4)
@ -603,7 +615,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
savetables.float(::exopackSmelterExperience, "exoPackSmelterExperience")
savetables.bool(::isExopackSmeltingInstalled, "isExoPackSmeltingInstalled")
savetables.codecNullable(::exopackColor, RGBAColor.CODECRGB)
savetables.codecNullable(::exopackColor, RGBColorDFUCodec)
savetables.bool(::exopackGlows)
savetables.stateful(::sortingSettings)
@ -611,8 +623,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
}
fun invalidateNetworkState() {
synchronizer.invalidate()
publicSynchronizer.invalidate()
privateSyncherRemote.invalidate()
remoteSynchers.values.forEach { it.invalidate() }
for (instance in research.values) {
instance.invalidateNetwork()
@ -981,7 +993,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
override fun deserializeNBT(tag: CompoundTag) {
savetables.deserializeNBT(tag)
if (MItems.ExopackUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON.uuid(ItemStack.EMPTY) in exopackSlotModifierMap) {
if (MItems.ExopackUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON.uuid(ItemStack.EMPTY) in exopackSlotModifierMap.delegate) {
isExopackEnderAccessInstalled = true
}
@ -1317,28 +1329,30 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
tickedOnce = true
val payload = synchronizer.collectNetworkPayload()
syncher.observe()
publicSyncher.observe()
val payload = privateSyncherRemote.write()
if (payload != null) {
MatteryPlayerNetworkChannel.send(ply, MatteryPlayerFieldPacket(payload, false))
}
val trackingIterator = trackingPlayers.entries.iterator()
val trackingIterator = remoteSynchers.entries.iterator()
for ((ply, endpoint) in trackingIterator) {
for ((ply, remote) in trackingIterator) {
if (ply.hasDisconnected()) {
trackingIterator.remove()
continue
}
val payload2 = endpoint.collectNetworkPayload()
val payload2 = remote.write()
if (payload2 != null) {
MatteryPlayerNetworkChannel.send(ply, MatteryPlayerFieldPacket(payload2, true, this.ply.uuid))
}
}
val payload3 = publicSynchronizer.collectNetworkPayload()
val payload3 = publicSyncherRemote.write()
if (payload3 != null) {
MatteryPlayerNetworkChannel.send(ply, MatteryPlayerFieldPacket(payload3, true))
@ -1591,7 +1605,9 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
mattery.iteration++
mattery.shouldSendIteration = true
mattery.deathLog.addLast(ply.tickCount to ply.combatTracker.deathMessage)
mattery.androidEnergy.batteryLevel = mattery.androidEnergy.batteryLevel.coerceAtLeast(AndroidConfig.ANDROID_MAX_ENERGY * Decimal("0.2")) // если смерть была от разряда батареи, то предотвращаем софтлок
if (mattery.androidEnergy.batteryLevel < AndroidConfig.ANDROID_MAX_ENERGY * Decimal("0.2"))
mattery.androidEnergy.batteryLevel = AndroidConfig.ANDROID_MAX_ENERGY * Decimal("0.2") // если смерть была от разряда батареи, то предотвращаем софтлок
while (mattery.deathLog.size > 6) {
mattery.deathLog.removeFirst()
@ -1748,14 +1764,14 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
fun onStartTracking(event: PlayerEvent.StartTracking) {
if (event.target is ServerPlayer) {
event.target.matteryPlayer?.let {
it.trackingPlayers[event.entity as ServerPlayer] = it.publicSynchronizer.Endpoint()
it.remoteSynchers[event.entity as ServerPlayer] = it.publicSyncher.Remote()
}
}
}
fun onStopTracking(event: PlayerEvent.StopTracking) {
if (event.target is ServerPlayer) {
event.target.matteryPlayer?.trackingPlayers?.remove(event.entity as ServerPlayer)
event.target.matteryPlayer?.remoteSynchers?.remove(event.entity as ServerPlayer)
}
}

View File

@ -6,6 +6,9 @@ import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.INBTSerializable
import ru.dbotthepony.kommons.io.DelegateSyncher
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.extractEnergy
import ru.dbotthepony.mc.otm.capability.receiveEnergy
@ -15,14 +18,15 @@ import ru.dbotthepony.mc.otm.core.math.getDecimal
import ru.dbotthepony.mc.otm.core.nbt.getItemStack
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
import ru.dbotthepony.mc.otm.core.util.decimal
import ru.dbotthepony.mc.otm.core.util.observedItem
import ru.dbotthepony.mc.otm.registry.StatNames
import ru.dbotthepony.mc.otm.triggers.AndroidBatteryTrigger
import ru.dbotthepony.mc.otm.triggers.ExopackBatterySlotTrigger
class BatteryBackedEnergyStorage(
private val ply: Player,
synchronizer: FieldSynchronizer,
synchronizer: DelegateSyncher,
initialCharge: Decimal,
maxCharge: Decimal,
val isAndroid: Boolean,
@ -34,8 +38,8 @@ class BatteryBackedEnergyStorage(
private var battery by synchronizer.decimal(initialCharge)
private var maxBattery by synchronizer.decimal(maxCharge)
var item by synchronizer.item(setter = setter@{ value, access, _ ->
access.write(value)
var item by synchronizer.observedItem(setter = setter@{ access, value ->
access.accept(value)
if (ply is ServerPlayer && isAndroid) {
AndroidBatteryTrigger.trigger(ply, value)

View File

@ -13,13 +13,25 @@ import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.nbt.mapPresent
import ru.dbotthepony.mc.otm.core.nbt.set
sealed class BlockEnergyStorageImpl(
open class BlockEnergyStorageImpl(
protected val listener: () -> Unit,
final override val energyFlow: FlowDirection,
private val maxBatteryLevelProvider: () -> Decimal,
private val maxInputProvider: () -> Decimal?,
private val maxOutputProvider: () -> Decimal?,
) : IMatteryEnergyStorage, INBTSerializable<CompoundTag?>, IEnergyStorageImpl {
constructor(
listener: () -> Unit,
energyFlow: FlowDirection,
values: EnergyBalanceValues
) : this(listener, energyFlow, values::energyCapacity, values::energyThroughput, values::energyThroughput)
constructor(
listener: () -> Unit,
energyFlow: FlowDirection,
values: VerboseEnergyBalanceValues
) : this(listener, energyFlow, values::energyCapacity, values::maxEnergyReceive, values::maxEnergyExtract)
private var maxInputStorage: Decimal? = null
private var maxOutputStorage: Decimal? = null
private var maxBatteryLevelStorage: Decimal? = null

View File

@ -3,7 +3,7 @@ package ru.dbotthepony.mc.otm.capability.energy
import net.minecraftforge.energy.IEnergyStorage
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import java.math.BigInteger
import kotlin.math.roundToInt
@ -372,5 +372,5 @@ fun IMatteryEnergyStorage.getBarColor(): Int {
if (!maxBatteryLevel.isPositive)
return 0
return RGBAColor.LOW_POWER.linearInterpolation((batteryLevel / maxBatteryLevel).toFloat(), RGBAColor.FULL_POWER).toRGB()
return RGBAColor.LOW_POWER.linearInterpolation((batteryLevel / maxBatteryLevel).toFloat(), RGBAColor.FULL_POWER).toBGR()
}

View File

@ -5,15 +5,17 @@ import net.minecraft.world.item.BlockItem
import net.minecraft.world.item.ItemStack
import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.fluids.FluidStack
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.tagNotNull
import ru.dbotthepony.mc.otm.network.synchronizer.IMutableField
import java.util.function.IntSupplier
/**
* Fluid handler for blocks
*/
open class BlockMatteryFluidHandler(private val _capacity: IntSupplier, field: IMutableField<FluidStack>) : AbstractMatteryFluidHandler(), INBTSerializable<CompoundTag?> {
open class BlockMatteryFluidHandler(private val _capacity: IntSupplier, field: Delegate<FluidStack>) : AbstractMatteryFluidHandler(), INBTSerializable<CompoundTag?> {
override var fluid by field
override val capacity: Int

View File

@ -4,7 +4,7 @@ import net.minecraftforge.common.capabilities.ICapabilityProvider
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.orNull
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import kotlin.math.roundToInt
@ -123,7 +123,7 @@ fun IMatterStorage.getBarWidth(): Int {
}
fun IMatterStorage.getBarColor(): Int {
return RGBAColor.LOW_MATTER.linearInterpolation((storedMatter / maxStoredMatter).toFloat(), RGBAColor.FULL_MATTER).toRGB()
return RGBAColor.LOW_MATTER.linearInterpolation((storedMatter / maxStoredMatter).toFloat(), RGBAColor.FULL_MATTER).toBGR()
}
val ICapabilityProvider.matter: IMatterStorage? get() = getCapability(MatteryCapability.MATTER).orNull()

View File

@ -3,7 +3,7 @@ package ru.dbotthepony.mc.otm.capability.matter
import net.minecraft.world.item.Item
import net.minecraftforge.common.capabilities.ICapabilityProvider
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.orNull
import java.util.*
import java.util.function.Predicate
@ -73,7 +73,7 @@ fun IPatternStorage.getBarWidth(): Int {
}
fun IPatternStorage.getBarColor(): Int {
return RGBAColor.LOW_PATTERNS.linearInterpolation((storedPatterns / patternCapacity).toFloat(), RGBAColor.FULL_PATTERNS).toRGB()
return RGBAColor.LOW_PATTERNS.linearInterpolation((storedPatterns / patternCapacity).toFloat(), RGBAColor.FULL_PATTERNS).toBGR()
}
val ICapabilityProvider.patterns: IPatternStorage? get() = getCapability(MatteryCapability.PATTERN).orNull()

View File

@ -12,7 +12,7 @@ import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.Widgets18
import ru.dbotthepony.mc.otm.client.render.is3DContext
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.network.ActivateAndroidFeaturePacket
import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel
import kotlin.math.roundToInt

View File

@ -16,7 +16,7 @@ import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.RenderGravity
import ru.dbotthepony.mc.otm.client.render.drawArc
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.angleDifference
import ru.dbotthepony.mc.otm.core.math.normalizeAngle
import ru.dbotthepony.mc.otm.core.util.formatTickDuration

View File

@ -32,7 +32,7 @@ import ru.dbotthepony.mc.otm.client.render.sprites.MatteryAtlas
import ru.dbotthepony.mc.otm.client.render.sprites.MatterySprite
import ru.dbotthepony.mc.otm.config.ClientConfig
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.util.formatPower
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.registry.AndroidFeatures

View File

@ -7,7 +7,7 @@ import net.minecraft.network.chat.Component
import net.minecraft.util.FormattedCharSequence
import org.joml.Matrix4f
import ru.dbotthepony.mc.otm.core.FloatSupplier
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.component1
import ru.dbotthepony.mc.otm.core.math.component2
import ru.dbotthepony.mc.otm.core.math.component3
@ -166,7 +166,7 @@ private fun Font.drawInternal(
text,
(x + shadowX) * inv,
(y + shadowY) * inv,
shadowColor.toRGB(),
shadowColor.toBGR(),
false,
poseStack.last().pose(),
buffer,
@ -190,7 +190,7 @@ private fun Font.drawInternal(
text,
x * inv + _x,
y * inv + _y,
outlineColor.toRGB(),
outlineColor.toBGR(),
drawShadow,
poseStack.last().pose(),
buffer,
@ -209,7 +209,7 @@ private fun Font.drawInternal(
text,
x * inv,
y * inv,
color.toRGB(),
color.toBGR(),
drawShadow,
poseStack.last().pose(),
buffer,

View File

@ -1,7 +1,7 @@
package ru.dbotthepony.mc.otm.client.render
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
interface IGUIRenderable {
/**

View File

@ -19,7 +19,7 @@ import net.minecraft.util.FormattedCharSequence
import net.minecraft.world.item.ItemStack
import net.minecraftforge.client.ForgeHooksClient
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import kotlin.math.PI
import kotlin.math.roundToInt

View File

@ -7,8 +7,8 @@ import net.minecraft.core.Vec3i
import org.joml.Matrix4f
import org.joml.Quaternionf
import org.joml.Vector3f
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.IAngle
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.Vector
import ru.dbotthepony.mc.otm.core.math.rotateAroundPoint
import ru.dbotthepony.mc.otm.core.math.rotateAroundThis

View File

@ -14,9 +14,9 @@ import org.apache.logging.log4j.LogManager
import org.joml.Matrix4f
import org.lwjgl.opengl.GL11.GL_ALWAYS
import org.lwjgl.opengl.GL11.GL_LESS
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import java.util.*
import kotlin.collections.ArrayDeque
import kotlin.math.PI

View File

@ -22,18 +22,19 @@ import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.rotate
import ru.dbotthepony.mc.otm.core.math.rotateY
import ru.dbotthepony.mc.otm.nanoTime
import java.util.function.BooleanSupplier
import java.util.function.Supplier
import kotlin.math.PI
abstract class BankRenderer<T : MatteryDeviceBlockEntity>(private val context: BlockEntityRendererProvider.Context) : BlockEntityRenderer<T> {
protected abstract fun gaugeLevel(entity: T): Float
protected abstract val texture: AbstractMatterySprite
protected abstract val models: List<BakedModel>
protected abstract fun status(entity: T): List<BooleanSupplier>
protected abstract fun status(entity: T): List<Supplier<Boolean>>
private val random = XoroshiroRandomSource(nanoTime)
@ -53,7 +54,7 @@ abstract class BankRenderer<T : MatteryDeviceBlockEntity>(private val context: B
stack.translate(-0.5f, -0.5f, -0.5f)
for ((i, model) in models.withIndex()) {
if (!status[i].asBoolean) {
if (!status[i].get()) {
continue
}
@ -124,7 +125,7 @@ class BatteryBankRenderer(context: BlockEntityRendererProvider.Context) : BankRe
}
}
override fun status(entity: BatteryBankBlockEntity): List<BooleanSupplier> {
override fun status(entity: BatteryBankBlockEntity): List<Supplier<Boolean>> {
return entity.batteryStatus
}
@ -151,7 +152,7 @@ class MatterBatteryBankRenderer(context: BlockEntityRendererProvider.Context) :
}
}
override fun status(entity: MatterCapacitorBankBlockEntity): List<BooleanSupplier> {
override fun status(entity: MatterCapacitorBankBlockEntity): List<Supplier<Boolean>> {
return entity.capacitorStatus
}

View File

@ -18,7 +18,7 @@ import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.render.*
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.VECTOR_FORWARD
import ru.dbotthepony.mc.otm.core.math.VECTOR_RIGHT
import ru.dbotthepony.mc.otm.core.math.VECTOR_UP

View File

@ -11,7 +11,7 @@ import ru.dbotthepony.mc.otm.block.entity.tech.EnergyCounterBlockEntity
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.render.*
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.asAngle
import ru.dbotthepony.mc.otm.core.util.formatPower
import ru.dbotthepony.mc.otm.core.math.times

View File

@ -20,7 +20,7 @@ import ru.dbotthepony.mc.otm.block.entity.decorative.FluidTankBlockEntity
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.render.rotateAround
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.linearInterpolation
import ru.dbotthepony.mc.otm.registry.MBlocks

View File

@ -20,7 +20,7 @@ import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.render.*
import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.VECTOR_DOWN
import ru.dbotthepony.mc.otm.core.math.VECTOR_FORWARD
import ru.dbotthepony.mc.otm.core.math.VECTOR_RIGHT

View File

@ -11,7 +11,7 @@ import ru.dbotthepony.mc.otm.client.render.RenderGravity
import ru.dbotthepony.mc.otm.client.render.draw
import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.rotateWithBlockFacing
class HoloSignRenderer(private val context: BlockEntityRendererProvider.Context) : BlockEntityRenderer<HoloSignBlockEntity> {

View File

@ -12,13 +12,13 @@ import net.minecraft.client.renderer.RenderType
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import org.lwjgl.opengl.GL11.GL_ALWAYS
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.IGUIRenderable
import ru.dbotthepony.mc.otm.client.render.IUVCoords
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
import ru.dbotthepony.mc.otm.client.render.color
import ru.dbotthepony.mc.otm.client.render.renderTexturedRect
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.linearInterpolation
import java.util.concurrent.ConcurrentHashMap

View File

@ -17,6 +17,8 @@ import net.minecraftforge.client.event.ContainerScreenEvent.Render.Background
import net.minecraftforge.client.event.ContainerScreenEvent.Render.Foreground
import net.minecraftforge.common.MinecraftForge
import org.lwjgl.opengl.GL11
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.setValue
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.moveMousePosScaled

View File

@ -14,7 +14,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeRectangleButtonPan
import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls
import ru.dbotthepony.mc.otm.client.screen.panels.input.NetworkedStringInputPanel
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.menu.decorative.HoloSignMenu
import ru.dbotthepony.mc.otm.registry.MItems

View File

@ -28,7 +28,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.util.ScrollableCanvasPanel
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.map
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.util.CreativeMenuItemComparator
import ru.dbotthepony.mc.otm.core.value
import ru.dbotthepony.mc.otm.menu.decorative.PainterMenu
@ -127,8 +127,8 @@ class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) :
val buttons = ArrayList<RectangleButtonPanel<PainterScreen>>()
menu.listeners.addListener {
if (frame.isRemoved) return@addListener
menu.listeners.addListener(Runnable {
if (frame.isRemoved) return@Runnable
buttons.forEach { it.remove() }
buttons.clear()
@ -187,7 +187,7 @@ class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) :
}
}
}
}
})
DeviceControls(this, frame, itemConfig = menu.itemConfig)

View File

@ -21,8 +21,8 @@ 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.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.asGetterSetter
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.mc.otm.core.math.integerDivisionDown
import ru.dbotthepony.mc.otm.core.util.ItemSorter
import ru.dbotthepony.mc.otm.core.util.formatMatter
@ -55,7 +55,7 @@ class MatterPanelScreen(
val controls = DeviceControls(this, frame)
controls.sortingButtons(menu.settings::isAscending.asGetterSetter(), menu.settings::sorting.asGetterSetter(), ItemSorter.DEFAULT) {
controls.sortingButtons(Delegate.Of(menu.settings::isAscending), Delegate.Of(menu.settings::sorting), ItemSorter.DEFAULT) {
for (v in ItemSorter.entries) {
add(v, skinElement = v.icon, tooltip = v.title)
}
@ -65,7 +65,7 @@ class MatterPanelScreen(
LargeBooleanRectangleButtonPanel(
this,
frame,
prop = menu::isProvidingTasks.asGetterSetter(),
prop = Delegate.Of(menu::isProvidingTasks),
iconActive = Widgets18.PLAY,
iconInactive = Widgets18.PAUSE,
tooltipActive = TranslatableComponent("otm.gui.matter_panel.is_providing_tasks"),

View File

@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.floats.FloatConsumer
import net.minecraft.client.gui.screens.Screen
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import ru.dbotthepony.kommons.math.HSVColor
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.client.CursorType
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
@ -19,8 +20,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.AbstractButtonPanel
import ru.dbotthepony.mc.otm.client.screen.panels.input.TextInputPanel
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.HSVColor
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import java.util.function.Consumer
import java.util.function.Supplier
import kotlin.math.roundToInt

View File

@ -14,7 +14,7 @@ import ru.dbotthepony.mc.otm.client.render.RenderGravity
import ru.dbotthepony.mc.otm.client.render.determineTooltipPosition
import ru.dbotthepony.mc.otm.client.render.sprites.sprite
import ru.dbotthepony.mc.otm.client.screen.panels.util.DiscreteScrollBarPanel
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.util.formatTickDuration
import ru.dbotthepony.mc.otm.core.math.integerDivisionDown

View File

@ -18,9 +18,9 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.SmallBooleanRectangleBu
import ru.dbotthepony.mc.otm.client.screen.panels.button.SmallRectangleButtonPanel
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleRenderButton
import ru.dbotthepony.mc.otm.compat.cos.isCosmeticArmorLoaded
import ru.dbotthepony.mc.otm.core.GetterSetter
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.mc.otm.network.DisableExopackGlowPacket
import ru.dbotthepony.mc.otm.network.DisplayExopackPacket
import ru.dbotthepony.mc.otm.network.EnableExopackGlowPacket
@ -57,7 +57,7 @@ private fun createExopackAppearanceWindow(screen: MatteryScreen<*>, matteryPlaye
screen,
frame,
text = TranslatableComponent("otm.gui.exopack.toggle_visibility"),
isChecked = GetterSetter.of(
isChecked = Delegate.Of(
{
matteryPlayer.isExopackVisible
},
@ -78,7 +78,7 @@ private fun createExopackAppearanceWindow(screen: MatteryScreen<*>, matteryPlaye
screen,
frame,
text = TranslatableComponent("otm.gui.exopack.toggle_glow"),
isChecked = GetterSetter.of(
isChecked = Delegate.Of(
{
matteryPlayer.exopackGlows
},

View File

@ -13,7 +13,7 @@ import ru.dbotthepony.mc.otm.client.render.*
import ru.dbotthepony.mc.otm.client.render.sprites.StretchingRectangleElement
import ru.dbotthepony.mc.otm.client.screen.panels.button.AbstractButtonPanel
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
open class FramePanel<out S : Screen>(
screen: S,

View File

@ -5,7 +5,7 @@ import net.minecraft.network.chat.Component
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.RenderGravity
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
open class Label<out S : Screen> @JvmOverloads constructor(
screen: S,

View File

@ -3,14 +3,14 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button
import net.minecraft.ChatFormatting
import net.minecraft.client.gui.screens.Screen
import net.minecraft.network.chat.Component
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.kommons.util.value
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.render.IGUIRenderable
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.GetterSetter
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.value
import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback
abstract class BooleanRectangleButtonPanel<out S : Screen>(
@ -20,7 +20,7 @@ abstract class BooleanRectangleButtonPanel<out S : Screen>(
y: Float = 0f,
width: Float,
height: Float,
val prop: GetterSetter<Boolean>,
val prop: Delegate<Boolean>,
var iconActive: IGUIRenderable? = null,
var iconInactive: IGUIRenderable? = null,
val onChange: ((newValue: Boolean) -> Unit)? = null,

View File

@ -6,7 +6,7 @@ import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.RenderGravity
import ru.dbotthepony.mc.otm.client.render.Widgets18
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import java.util.function.IntConsumer
open class ButtonPanel<out S : Screen>(

View File

@ -5,6 +5,8 @@ import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.kommons.util.value
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
import ru.dbotthepony.mc.otm.capability.FlowDirection
@ -24,14 +26,11 @@ import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.util.GridPanel
import ru.dbotthepony.mc.otm.config.ClientConfig
import ru.dbotthepony.mc.otm.core.GetterSetter
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.asGetterSetter
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.math.RelativeSide
import ru.dbotthepony.mc.otm.core.util.ItemStackSorter
import ru.dbotthepony.mc.otm.core.value
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.UpgradeSlots
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
@ -78,7 +77,7 @@ private class PullPushButton<out S : MatteryScreen<*>, T : Enum<T>>(
x: Float = 0f,
y: Float = 0f,
enum: Class<T>,
prop: GetterSetter<T>,
prop: Delegate<T>,
defaultValue: T,
val pullProp: BooleanInputWithFeedback,
val pushProp: BooleanInputWithFeedback
@ -372,7 +371,7 @@ class DeviceControls<out S : MatteryScreen<*>>(
alignButtons()
}
fun addStorageMode(prop: GetterSetter<FlowDirection>) {
fun addStorageMode(prop: Delegate<FlowDirection>) {
val mode = LargeEnumRectangleButtonPanel(screen, this, prop = prop, defaultValue = FlowDirection.BI_DIRECTIONAL, enum = FlowDirection::class.java)
mode.add(FlowDirection.INPUT, Widgets18.ONLY_STORE, FlowDirection.INPUT.title)
@ -383,7 +382,7 @@ class DeviceControls<out S : MatteryScreen<*>>(
addButton(mode)
}
inline fun <reified T : Enum<T>> sortingButtons(ascending: GetterSetter<Boolean>, sorting: GetterSetter<T>, default: T, configurator: LargeEnumRectangleButtonPanel<S, T>.() -> Unit): List<EditablePanel<S>> {
inline fun <reified T : Enum<T>> sortingButtons(ascending: Delegate<Boolean>, sorting: Delegate<T>, default: T, configurator: LargeEnumRectangleButtonPanel<S, T>.() -> Unit): List<EditablePanel<S>> {
val result = ArrayList<EditablePanel<S>>()
LargeBooleanRectangleButtonPanel(
@ -439,7 +438,7 @@ class DeviceControls<out S : MatteryScreen<*>>(
set(value) {}
private fun makeButtons() {
buttons = sortingButtons(input.settings::isAscending.asGetterSetter(), input.settings::sorting.asGetterSetter(), ItemStackSorter.DEFAULT) {
buttons = sortingButtons(Delegate.Of(input.settings::isAscending), Delegate.Of(input.settings::sorting), ItemStackSorter.DEFAULT) {
for (v in ItemStackSorter.entries) {
add(v, v.icon, v.title)
}

View File

@ -1,11 +1,8 @@
package ru.dbotthepony.mc.otm.client.screen.panels.button
import net.minecraft.client.gui.screens.Screen
import net.minecraft.world.entity.player.Player
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.GetterSetter
import ru.dbotthepony.mc.otm.core.value
import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback
open class CheckBoxInputPanel<out S : Screen>(

View File

@ -2,9 +2,9 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button
import net.minecraft.client.gui.screens.Screen
import net.minecraft.network.chat.Component
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.client.screen.panels.Label
import ru.dbotthepony.mc.otm.core.GetterSetter
open class CheckBoxLabelPanel<out S : Screen>(
screen: S,
@ -14,7 +14,7 @@ open class CheckBoxLabelPanel<out S : Screen>(
y: Float = 0f,
width: Float = CheckBoxPanel.REGULAR_DIMENSIONS + 120f,
height: Float = CheckBoxPanel.REGULAR_DIMENSIONS,
isChecked: GetterSetter<Boolean> = GetterSetter.box(false)
isChecked: Delegate<Boolean> = Delegate.Box(false)
) : AbstractCheckBoxLabelPanel<S>(screen, parent, x, y, width, height) {
override val checkbox = CheckBoxPanel(screen, this, 0f, 0f, isChecked = isChecked)
override val label = Label(screen, this, CheckBoxPanel.REGULAR_DIMENSIONS + 4f, 4f, text = text)

View File

@ -1,11 +1,11 @@
package ru.dbotthepony.mc.otm.client.screen.panels.button
import net.minecraft.client.gui.screens.Screen
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.sprites.AbstractMatterySprite
import ru.dbotthepony.mc.otm.client.render.WidgetLocation
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.GetterSetter
open class CheckBoxPanel<out S : Screen>(
screen: S,
@ -14,7 +14,7 @@ open class CheckBoxPanel<out S : Screen>(
y: Float = 0f,
width: Float = REGULAR_DIMENSIONS,
height: Float = REGULAR_DIMENSIONS,
open val isChecked: GetterSetter<Boolean> = GetterSetter.box(false)
open val isChecked: Delegate<Boolean> = Delegate.Box(false)
) : AbstractButtonPanel<S>(screen, parent, x, y, width, height) {
open val IDLE_UNCHECKED: AbstractMatterySprite = Companion.IDLE_UNCHECKED
open val IDLE_CHECKED: AbstractMatterySprite = Companion.IDLE_CHECKED

View File

@ -4,13 +4,15 @@ import com.mojang.blaze3d.platform.InputConstants
import net.minecraft.ChatFormatting
import net.minecraft.client.gui.screens.Screen
import net.minecraft.network.chat.Component
import ru.dbotthepony.kommons.io.StreamCodec
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.kommons.util.value
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.render.IGUIRenderable
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.util.EnumValueCodec
import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback
import java.util.*
import java.util.function.Predicate
@ -24,10 +26,10 @@ abstract class EnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
width: Float,
height: Float,
enum: Class<T>,
val prop: GetterSetter<T>,
val prop: Delegate<T>,
val defaultValue: T,
) : RectangleButtonPanel<S>(screen, parent, x, y, width, height, null) {
val enum = EnumValueCodec.searchClass(enum)
val enum = StreamCodec.Enum.searchClass(enum)
private val constants: Array<T> = enum.enumConstants
private var isBuilding = true
var predicate: Predicate<T> = Predicate { true }

View File

@ -2,10 +2,10 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button
import net.minecraft.client.gui.screens.Screen
import net.minecraft.network.chat.Component
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.mc.otm.client.render.IGUIRenderable
import ru.dbotthepony.mc.otm.client.render.Widgets18
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.GetterSetter
open class LargeBooleanRectangleButtonPanel<out S : Screen>(
screen: S,
@ -14,7 +14,7 @@ open class LargeBooleanRectangleButtonPanel<out S : Screen>(
y: Float = 0f,
width: Float = SIZE,
height: Float = SIZE,
prop: GetterSetter<Boolean>,
prop: Delegate<Boolean>,
iconActive: IGUIRenderable? = null,
iconInactive: IGUIRenderable? = null,
onChange: ((newValue: Boolean) -> Unit)? = null,

View File

@ -1,11 +1,9 @@
package ru.dbotthepony.mc.otm.client.screen.panels.button
import net.minecraft.client.gui.screens.Screen
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.mc.otm.client.render.Widgets18
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.GetterSetter
import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback
open class LargeEnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
screen: S,
@ -15,7 +13,7 @@ open class LargeEnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
width: Float = SIZE,
height: Float = SIZE,
enum: Class<T>,
prop: GetterSetter<T>,
prop: Delegate<T>,
defaultValue: T,
) : EnumRectangleButtonPanel<S, T>(screen, parent, x, y, width, height, enum, prop, defaultValue) {
final override val IDLE = Widgets18.BUTTON_IDLE

View File

@ -7,7 +7,7 @@ import ru.dbotthepony.mc.otm.client.render.IGUIRenderable
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
import ru.dbotthepony.mc.otm.client.render.Widgets18
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.menu.MatteryMenu
open class LargeRectangleButtonPanel<out S : Screen>(

View File

@ -1,10 +1,10 @@
package ru.dbotthepony.mc.otm.client.screen.panels.button
import net.minecraft.client.gui.screens.Screen
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.mc.otm.client.render.*
import ru.dbotthepony.mc.otm.client.render.sprites.AbstractMatterySprite
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.GetterSetter
open class SmallBooleanRectangleButtonPanel<out S : Screen>(
screen: S,
@ -13,7 +13,7 @@ open class SmallBooleanRectangleButtonPanel<out S : Screen>(
y: Float = 0f,
width: Float = SIZE,
height: Float = SIZE,
prop: GetterSetter<Boolean>,
prop: Delegate<Boolean>,
skinElementActive: AbstractMatterySprite? = null,
skinElementInactive: AbstractMatterySprite? = null,
onChange: ((newValue: Boolean) -> Unit)? = null,

View File

@ -1,9 +1,9 @@
package ru.dbotthepony.mc.otm.client.screen.panels.button
import net.minecraft.client.gui.screens.Screen
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.mc.otm.client.render.Widgets8
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.GetterSetter
open class SmallEnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
screen: S,
@ -13,7 +13,7 @@ open class SmallEnumRectangleButtonPanel<out S : Screen, T : Enum<T>>(
width: Float = SIZE,
height: Float = SIZE,
enum: Class<T>,
prop: GetterSetter<T>,
prop: Delegate<T>,
defaultValue: T,
) : EnumRectangleButtonPanel<S, T>(screen, parent, x, y, width, height, enum, prop, defaultValue) {
final override val IDLE = Widgets8.BUTTON_IDLE

View File

@ -6,6 +6,7 @@ import ru.dbotthepony.mc.otm.client.CursorType
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import java.math.BigDecimal
import java.util.function.BooleanSupplier
@ -13,8 +14,8 @@ import java.util.function.BooleanSupplier
open class NetworkNumberInputPanel<out S : Screen> @JvmOverloads constructor(
screen: S,
parent: EditablePanel<*>?,
val networkValue: () -> BigDecimal,
val callback: (BigDecimal) -> Unit,
val networkValue: () -> Decimal,
val callback: (Decimal) -> Unit,
val isEnabled: BooleanSupplier = BooleanSupplier { true },
x: Float = 0f,
y: Float = 0f,
@ -25,8 +26,8 @@ open class NetworkNumberInputPanel<out S : Screen> @JvmOverloads constructor(
constructor(
screen: S,
parent: EditablePanel<*>?,
widget: MatteryMenu.PlayerInput<BigDecimal>,
networkValue: () -> BigDecimal,
widget: MatteryMenu.PlayerInput<Decimal>,
networkValue: () -> Decimal,
x: Float = 0f,
y: Float = 0f,
width: Float = 0f,
@ -69,14 +70,14 @@ open class NetworkNumberInputPanel<out S : Screen> @JvmOverloads constructor(
}
if (nextUpdateFromServer < System.currentTimeMillis()) {
getOrCreateWidget().value = networkValue.invoke().toPlainString()
getOrCreateWidget().value = networkValue.invoke().toString()
inputStr = getOrCreateWidget().value
} else if (isEnabled.asBoolean) {
if (inputStr != getOrCreateWidget().value) {
inputStr = getOrCreateWidget().value
try {
callback.invoke(BigDecimal(inputStr))
callback.invoke(Decimal(inputStr))
} catch (_: Throwable) { }
}
}

View File

@ -2,19 +2,19 @@ package ru.dbotthepony.mc.otm.client.screen.panels.input
import com.mojang.blaze3d.platform.InputConstants
import net.minecraft.client.gui.screens.Screen
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.mc.otm.client.render.Widgets
import ru.dbotthepony.mc.otm.client.screen.panels.Dock
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.RectangleButtonPanel
import ru.dbotthepony.mc.otm.client.screen.panels.util.HeightControls
import ru.dbotthepony.mc.otm.core.GetterSetter
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.Decimal
abstract class NumberInputPanel<out S : Screen, N : Number>(
screen: S,
parent: EditablePanel<*>,
val prop: GetterSetter<N>,
val prop: Delegate<N>,
x: Float = 0f,
y: Float = 0f,
width: Float = WIDTH,
@ -129,7 +129,7 @@ abstract class NumberInputPanel<out S : Screen, N : Number>(
abstract class LNumberInputPanel<out S : Screen, N : Number>(
screen: S,
parent: EditablePanel<*>,
prop: GetterSetter<N>,
prop: Delegate<N>,
x: Float = 0f,
y: Float = 0f,
width: Float = WIDTH,
@ -157,7 +157,7 @@ abstract class LNumberInputPanel<out S : Screen, N : Number>(
open class IntInputPanel<out S : Screen>(
screen: S,
parent: EditablePanel<*>,
prop: GetterSetter<Int>,
prop: Delegate<Int>,
x: Float = 0f,
y: Float = 0f,
width: Float = WIDTH,
@ -185,7 +185,7 @@ open class IntInputPanel<out S : Screen>(
open class DecimalInputPanel<out S : Screen>(
screen: S,
parent: EditablePanel<*>,
prop: GetterSetter<Decimal>,
prop: Delegate<Decimal>,
x: Float = 0f,
y: Float = 0f,
width: Float = WIDTH,

View File

@ -28,7 +28,7 @@ import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.addAll
import ru.dbotthepony.mc.otm.core.collect.map
import ru.dbotthepony.mc.otm.core.collect.reduce
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.milliTime
import java.util.function.Predicate
import kotlin.math.roundToInt

View File

@ -10,7 +10,7 @@ import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.WidgetLocation
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.kommons.math.RGBAColor
abstract class AbstractSlotPanel<out S : MatteryScreen<*>>(
screen: S,

View File

@ -1,14 +1,14 @@
package ru.dbotthepony.mc.otm.client.screen.panels.slot
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.GetterSetter
open class FilterSlotPanel<out S : MatteryScreen<*>> @JvmOverloads constructor(
screen: S,
parent: EditablePanel<*>?,
val slot: GetterSetter<ItemStack>,
val slot: Delegate<ItemStack>,
x: Float = 0f,
y: Float = 0f,
width: Float = SIZE,

Some files were not shown because too many files have changed in this diff Show More