This commit is contained in:
GearShocky 2022-09-03 17:43:26 +06:00
commit 00b8e546b0
195 changed files with 3833 additions and 3285 deletions

View File

@ -14,7 +14,7 @@ import net.minecraftforge.fml.common.Mod
import net.minecraftforge.data.event.GatherDataEvent import net.minecraftforge.data.event.GatherDataEvent
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.block.* import ru.dbotthepony.mc.otm.block.*
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.block.matter.MatterBottlerBlock import ru.dbotthepony.mc.otm.block.matter.MatterBottlerBlock
import ru.dbotthepony.mc.otm.block.matter.PatternStorageBlock import ru.dbotthepony.mc.otm.block.matter.PatternStorageBlock
import ru.dbotthepony.mc.otm.block.storage.DriveViewerBlock import ru.dbotthepony.mc.otm.block.storage.DriveViewerBlock
@ -30,7 +30,7 @@ import ru.dbotthepony.mc.otm.datagen.models.BlockMatteryModelProvider
import ru.dbotthepony.mc.otm.datagen.recipes.MatteryRecipeProvider import ru.dbotthepony.mc.otm.datagen.recipes.MatteryRecipeProvider
import ru.dbotthepony.mc.otm.datagen.recipes.has import ru.dbotthepony.mc.otm.datagen.recipes.has
import ru.dbotthepony.mc.otm.registry.* import ru.dbotthepony.mc.otm.registry.*
import ru.dbotthepony.mc.otm.* import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider
import ru.dbotthepony.mc.otm.datagen.loot.addLootModifiers import ru.dbotthepony.mc.otm.datagen.loot.addLootModifiers
import ru.dbotthepony.mc.otm.datagen.recipes.addCraftingTableRecipes import ru.dbotthepony.mc.otm.datagen.recipes.addCraftingTableRecipes

View File

@ -7,12 +7,12 @@ import net.minecraftforge.client.model.generators.BlockStateProvider
import net.minecraftforge.client.model.generators.ConfiguredModel import net.minecraftforge.client.model.generators.ConfiguredModel
import net.minecraftforge.data.event.GatherDataEvent import net.minecraftforge.data.event.GatherDataEvent
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.datagen.DataGen import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.datagen.getValueNullable import ru.dbotthepony.mc.otm.datagen.getValueNullable
import ru.dbotthepony.mc.otm.datagen.toXRotBlockstate import ru.dbotthepony.mc.otm.datagen.toXRotBlockstate
import ru.dbotthepony.mc.otm.datagen.toYRotBlockstate import ru.dbotthepony.mc.otm.datagen.toYRotBlockstate
import ru.dbotthepony.mc.otm.registryName import ru.dbotthepony.mc.otm.core.registryName
typealias AdvancedBlockStateFunction = (BlockState, ConfiguredModel.Builder<*>, String) -> String? typealias AdvancedBlockStateFunction = (BlockState, ConfiguredModel.Builder<*>, String) -> String?
private data class AdvancedBlockStateEntry(val block: Block, val func: AdvancedBlockStateFunction) private data class AdvancedBlockStateEntry(val block: Block, val func: AdvancedBlockStateFunction)

View File

@ -6,7 +6,7 @@ import net.minecraftforge.client.model.generators.ItemModelProvider
import net.minecraftforge.data.event.GatherDataEvent import net.minecraftforge.data.event.GatherDataEvent
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.datagen.DataGen import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.registryName import ru.dbotthepony.mc.otm.core.registryName
private data class SimpleItemModel(val item: String, val path: ResourceLocation) { private data class SimpleItemModel(val item: String, val path: ResourceLocation) {
val traceback = IllegalArgumentException("Failed to register model") val traceback = IllegalArgumentException("Failed to register model")

View File

@ -53,6 +53,10 @@ private fun misc(provider: MatteryLanguageProvider) {
gui("exosuit.already_activated", "You already have exosuit following you") gui("exosuit.already_activated", "You already have exosuit following you")
gui("power_supplier.active_nodes", "Currently demanding nodes: %s")
misc("battery.single_use", "Single use battery, can not be recharged.")
misc("exosuit.granted1", "As you keep pressing fingerprint reader, you are getting hurt in finger.") misc("exosuit.granted1", "As you keep pressing fingerprint reader, you are getting hurt in finger.")
misc("exosuit.granted2", "After you raise your finger, fingerprint reader glows very bright.") misc("exosuit.granted2", "After you raise your finger, fingerprint reader glows very bright.")
misc("exosuit.granted3", "Then, fingerprint reader fades, leaving faint trace not of your finger, but of your very soul.") misc("exosuit.granted3", "Then, fingerprint reader fades, leaving faint trace not of your finger, but of your very soul.")
@ -128,6 +132,9 @@ private fun misc(provider: MatteryLanguageProvider) {
misc("item.power.normal.storage", "Stored energy: %s / %s") misc("item.power.normal.storage", "Stored energy: %s / %s")
misc("item.power.normal.throughput", "Max I/O %s / %s") misc("item.power.normal.throughput", "Max I/O %s / %s")
misc("item.power.output_only", "Max output %s")
misc("item.power.input_only", "Max input %s")
misc("item.pattern.stored", "Stored patterns: %s / %s") misc("item.pattern.stored", "Stored patterns: %s / %s")
misc("item.pattern.infinite.stored", "Stored patterns %s") misc("item.pattern.infinite.stored", "Stored patterns %s")
misc("item.pattern.line", "%s [%s%%]") misc("item.pattern.line", "%s [%s%%]")
@ -377,6 +384,9 @@ private fun items(provider: MatteryLanguageProvider) {
add(MItems.TRITANIUM_ORE_CLUMP, "Raw Tritanium") add(MItems.TRITANIUM_ORE_CLUMP, "Raw Tritanium")
add(MItems.PATTERN_DRIVE_NORMAL, "Pattern Drive") add(MItems.PATTERN_DRIVE_NORMAL, "Pattern Drive")
add(MItems.PATTERN_DRIVE_CREATIVE, "Creative Pattern Drive") add(MItems.PATTERN_DRIVE_CREATIVE, "Creative Pattern Drive")
add(MItems.ZPM_BATTERY, "Zero Point Module")
add(MItems.ZPM_BATTERY, "description", "Can be found in hands of those who travel between dimensions, if they ever reached different reality of origin of these constructs...")
} }
} }

View File

@ -39,11 +39,12 @@ fun addLootModifiers(it: LootModifiers) {
ItemStack(MItems.PILL_ANDROID, 1) to 0.5 ItemStack(MItems.PILL_ANDROID, 1) to 0.5
)) ))
it.add("end_city_pill", LootTableBasicAppender( it.add("end_city_modifications", LootTableBasicAppender(
arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/end_city_treasure")).build()), arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/end_city_treasure")).build()),
ItemStack(MItems.PILL_ANDROID, 1) to 0.1, ItemStack(MItems.PILL_ANDROID, 1) to 0.1,
ItemStack(MItems.PILL_HUMANE, 1) to 0.3, ItemStack(MItems.PILL_HUMANE, 1) to 0.3,
ItemStack(MItems.PILL_OBLIVION, 1) to 0.5, ItemStack(MItems.PILL_OBLIVION, 1) to 0.5,
ItemStack(MItems.ZPM_BATTERY, 1) to 0.005,
)) ))
it.add("shipwreck_supply_pill", LootTableBasicAppender( it.add("shipwreck_supply_pill", LootTableBasicAppender(

View File

@ -9,7 +9,8 @@ import net.minecraft.core.Direction
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraftforge.client.model.generators.ModelBuilder import net.minecraftforge.client.model.generators.ModelBuilder
import net.minecraftforge.common.data.ExistingFileHelper import net.minecraftforge.common.data.ExistingFileHelper
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
data class TextureSize(val width: Float, val height: Float) { data class TextureSize(val width: Float, val height: Float) {
constructor(arr: JsonArray) : this(arr[0].asFloat, arr[1].asFloat) constructor(arr: JsonArray) : this(arr[0].asFloat, arr[1].asFloat)

View File

@ -8,7 +8,7 @@ import net.minecraft.world.level.block.Block
import net.minecraftforge.client.model.generators.ModelProvider import net.minecraftforge.client.model.generators.ModelProvider
import net.minecraftforge.data.event.GatherDataEvent import net.minecraftforge.data.event.GatherDataEvent
import ru.dbotthepony.mc.otm.datagen.DataGen import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.registryName import ru.dbotthepony.mc.otm.core.registryName
private typealias Callback = (MatteryModelProvider) -> Unit private typealias Callback = (MatteryModelProvider) -> Unit

View File

@ -4,8 +4,6 @@ import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.data.recipes.ShapedRecipeBuilder import net.minecraft.data.recipes.ShapedRecipeBuilder
import net.minecraft.data.recipes.ShapelessRecipeBuilder import net.minecraft.data.recipes.ShapelessRecipeBuilder
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.TagKey
import net.minecraft.world.item.Item
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraftforge.common.Tags import net.minecraftforge.common.Tags
@ -15,7 +13,7 @@ import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
import ru.dbotthepony.mc.otm.registryName import ru.dbotthepony.mc.otm.core.registryName
import java.util.function.Consumer import java.util.function.Consumer
fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) { fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
@ -55,6 +53,22 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
.build(consumer) .build(consumer)
} }
MatteryRecipe(MBlocks.PLATE_PRESS)
.row(MItems.ELECTRIC_PARTS, MItems.ENERGY_BUS, MItems.ELECTRIC_PARTS)
.row(MItemTags.INGOT_TRITANIUM, Items.BLAST_FURNACE, MItemTags.INGOT_TRITANIUM)
.row(MItemTags.PISTONS, MItemTags.INGOT_TRITANIUM, MItemTags.PISTONS)
.unlockedBy(MItemTags.INGOT_TRITANIUM)
.unlockedBy(MItems.ELECTRIC_PARTS)
.build(consumer)
MatteryRecipe(MBlocks.PLATE_PRESS)
.rowB(MItemTags.BASIC_CIRCUIT)
.row(MItemTags.PLATE_TRITANIUM, MItems.MACHINE_FRAME, MItemTags.PLATE_TRITANIUM)
.rowAC(MItemTags.PISTONS, MItemTags.PISTONS)
.unlockedBy(MItemTags.INGOT_TRITANIUM)
.unlockedBy(MItems.ELECTRIC_PARTS)
.build(consumer, "advanced")
MatteryRecipe(MBlocks.TRITANIUM_STRIPED_BLOCK, 24) MatteryRecipe(MBlocks.TRITANIUM_STRIPED_BLOCK, 24)
.rowB(MItemTags.PLATE_TRITANIUM) .rowB(MItemTags.PLATE_TRITANIUM)
.row(MItemTags.PLATE_TRITANIUM, COBBLESTONE, MItemTags.PLATE_TRITANIUM) .row(MItemTags.PLATE_TRITANIUM, COBBLESTONE, MItemTags.PLATE_TRITANIUM)

View File

@ -11,7 +11,7 @@ import net.minecraft.world.item.Item
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.level.ItemLike import net.minecraft.world.level.ItemLike
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.registryName import ru.dbotthepony.mc.otm.core.registryName
import java.util.function.Consumer import java.util.function.Consumer
private interface RecipeCell { private interface RecipeCell {

View File

@ -7,7 +7,8 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.crafting.RecipeSerializer import net.minecraft.world.item.crafting.RecipeSerializer
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipeFactory import ru.dbotthepony.mc.otm.recipe.PlatePressRecipeFactory
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
class PlatePressFinishedRecipe(private val recipe: PlatePressRecipe) : FinishedRecipe { class PlatePressFinishedRecipe(private val recipe: PlatePressRecipe) : FinishedRecipe {
override fun serializeRecipeData(it: JsonObject) { override fun serializeRecipeData(it: JsonObject) {

View File

@ -2,8 +2,10 @@ package ru.dbotthepony.mc.otm;
import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModList;
@ -15,15 +17,15 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import ru.dbotthepony.mc.otm.block.entity.blackhole.ExplosionQueue; import ru.dbotthepony.mc.otm.block.entity.blackhole.ExplosionQueue;
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability; import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.capability.drive.DrivePool; import ru.dbotthepony.mc.otm.capability.drive.DrivePool;
import ru.dbotthepony.mc.otm.client.ClientEventHandler;
import ru.dbotthepony.mc.otm.client.MatteryGUI; import ru.dbotthepony.mc.otm.client.MatteryGUI;
import ru.dbotthepony.mc.otm.client.EventHandlerKt;
import ru.dbotthepony.mc.otm.client.model.GravitationStabilizerModel; import ru.dbotthepony.mc.otm.client.model.GravitationStabilizerModel;
import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel; import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel;
import ru.dbotthepony.mc.otm.compat.mekanism.QIOKt; import ru.dbotthepony.mc.otm.compat.mekanism.QIOKt;
import ru.dbotthepony.mc.otm.compat.mekanism.TooltipsKt; import ru.dbotthepony.mc.otm.compat.mekanism.TooltipsKt;
import ru.dbotthepony.mc.otm.core.ImpreciseFraction; import ru.dbotthepony.mc.otm.core.ImpreciseFraction;
import ru.dbotthepony.mc.otm.item.QuantumBatteryItem;
import ru.dbotthepony.mc.otm.item.weapon.AbstractWeaponItem; import ru.dbotthepony.mc.otm.item.weapon.AbstractWeaponItem;
import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem; import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem;
import ru.dbotthepony.mc.otm.matter.MatterDataKt; import ru.dbotthepony.mc.otm.matter.MatterDataKt;
@ -33,6 +35,8 @@ import ru.dbotthepony.mc.otm.registry.*;
import ru.dbotthepony.mc.otm.storage.*; import ru.dbotthepony.mc.otm.storage.*;
import ru.dbotthepony.mc.otm.worldgen.OreGen; import ru.dbotthepony.mc.otm.worldgen.OreGen;
import static net.minecraftforge.common.MinecraftForge.EVENT_BUS;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
// The value here should match an entry in the META-INF/mods.toml file // The value here should match an entry in the META-INF/mods.toml file
@ -76,49 +80,78 @@ public final class OverdriveThatMatters {
INSTANCE = this; INSTANCE = this;
MRegistry.INSTANCE.initialize(FMLJavaModLoadingContext.get()); var modBus = FMLJavaModLoadingContext.get().getModEventBus();
FMLJavaModLoadingContext.get().getModEventBus().addListener(EventPriority.HIGHEST, this::setup); MRegistry.INSTANCE.initialize(modBus);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setupClient);
MinecraftForge.EVENT_BUS.register(this); modBus.addListener(EventPriority.HIGHEST, this::setup);
MinecraftForge.EVENT_BUS.register(GlobalEventHandlerKt.class); modBus.addListener(EventPriority.NORMAL, this::setupClient);
MinecraftForge.EVENT_BUS.register(MatteryPlayerCapability.Companion);
MinecraftForge.EVENT_BUS.register(MatterRegistryKt.class);
MinecraftForge.EVENT_BUS.register(MatterDataKt.class);
MinecraftForge.EVENT_BUS.register(ExplosionQueue.Companion);
MinecraftForge.EVENT_BUS.register(AbstractWeaponItem.Companion);
FMLJavaModLoadingContext.get().getModEventBus().register(MatteryCapability.class);
FMLJavaModLoadingContext.get().getModEventBus().register(MRecipes.class);
MinecraftForge.EVENT_BUS.register(DrivePool.INSTANCE);
MinecraftForge.EVENT_BUS.register(PortableCondensationDriveItem.Companion);
FMLJavaModLoadingContext.get().getModEventBus().addListener(MatteryPlayerCapability::registerEffects);
} }
private void setup(final FMLCommonSetupEvent event) { private void setup(final FMLCommonSetupEvent event) {
EVENT_BUS.addListener(EventPriority.LOWEST, DrivePool.INSTANCE::onServerPostTick);
EVENT_BUS.addListener(EventPriority.HIGHEST, DrivePool.INSTANCE::serverStopEvent);
EVENT_BUS.addListener(EventPriority.HIGHEST, DrivePool.INSTANCE::serverStartEvent);
EVENT_BUS.addListener(EventPriority.NORMAL, DrivePool.INSTANCE::onWorldSave);
EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStopped);
EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStopping);
EVENT_BUS.addListener(EventPriority.HIGHEST, GlobalEventHandlerKt::onServerStarting);
EVENT_BUS.addListener(EventPriority.LOWEST, GlobalEventHandlerKt::onWorldTick);
EVENT_BUS.addListener(EventPriority.LOWEST, GlobalEventHandlerKt::onServerTick);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onLivingTick);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onHurtEvent);
EVENT_BUS.addGenericListener(Entity.class, EventPriority.NORMAL, MatteryPlayerCapability.Companion::onAttachCapabilityEvent);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerChangeDimensionEvent);
EVENT_BUS.addListener(EventPriority.LOWEST, MatteryPlayerCapability.Companion::onPlayerDeath);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryPlayerCapability.Companion::onPlayerCloneEvent);
EVENT_BUS.addListener(EventPriority.LOW, MatteryPlayerCapability.Companion::onPickupEvent);
EVENT_BUS.addListener(EventPriority.LOW, MatterDataKt::serverStartData);
EVENT_BUS.addListener(EventPriority.NORMAL, MatterRegistryKt::onPlayerJoin);
EVENT_BUS.addListener(EventPriority.NORMAL, ExplosionQueue.Companion::onWorldTick);
EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::tick);
EVENT_BUS.addListener(EventPriority.NORMAL, QuantumBatteryItem.Companion::tick);
EVENT_BUS.addListener(EventPriority.LOWEST, PortableCondensationDriveItem.Companion::onPickupEvent);
MatteryPlayerCapability.Companion.registerEffects(event);
MatteryPlayerNetworkChannel.INSTANCE.register(); MatteryPlayerNetworkChannel.INSTANCE.register();
MenuNetworkChannel.INSTANCE.register(); MenuNetworkChannel.INSTANCE.register();
WeaponNetworkChannel.INSTANCE.register(); WeaponNetworkChannel.INSTANCE.register();
RegistryNetworkChannel.INSTANCE.register(); RegistryNetworkChannel.INSTANCE.register();
WorldNetworkChannel.INSTANCE.register(); WorldNetworkChannel.INSTANCE.register();
GenericNetworkChannel.INSTANCE.register();
ITEM_STORAGE = StorageRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new ImpreciseFraction("3.125")); ITEM_STORAGE = StorageRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new ImpreciseFraction("3.125"));
if (ModList.get().isLoaded("mekanism")) { if (ModList.get().isLoaded("mekanism")) {
MinecraftForge.EVENT_BUS.register(QIOKt.class); EVENT_BUS.addGenericListener(BlockEntity.class, EventPriority.NORMAL, QIOKt::attachCapabilities);
MinecraftForge.EVENT_BUS.register(TooltipsKt.class);
} }
OreGen.INSTANCE.register(); OreGen.INSTANCE.register();
} }
private void setupClient(final FMLClientSetupEvent event) { private void setupClient(final FMLClientSetupEvent event) {
MinecraftForge.EVENT_BUS.register(MatteryGUI.INSTANCE); EVENT_BUS.addListener(EventPriority.NORMAL, MatterRegistryKt::tooltipEvent);
MinecraftForge.EVENT_BUS.register(EventHandlerKt.class);
EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::playerRenderHook);
EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::fovHook);
EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::clickHook);
EVENT_BUS.addListener(EventPriority.NORMAL, AbstractWeaponItem.Companion::renderViewModel);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryGUI.INSTANCE::onScreenRender);
EVENT_BUS.addListener(EventPriority.LOWEST, MatteryGUI.INSTANCE::onOpenGUIEvent);
EVENT_BUS.addListener(EventPriority.NORMAL, MatteryGUI.INSTANCE::onRenderGuiEvent);
EVENT_BUS.addListener(EventPriority.HIGH, MatteryGUI.INSTANCE::onLayerRenderEvent);
EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandler.INSTANCE::inputEvent);
EVENT_BUS.addListener(EventPriority.NORMAL, ClientEventHandler.INSTANCE::screenOpen);
if (ModList.get().isLoaded("mekanism")) {
EVENT_BUS.addListener(EventPriority.NORMAL, TooltipsKt::tooltipEvent);
}
event.enqueueWork(GlobalEventHandlerKt::recordClientThread); event.enqueueWork(GlobalEventHandlerKt::recordClientThread);

View File

@ -5,7 +5,7 @@ import net.minecraftforge.common.capabilities.*;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive; import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive;
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler; import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler;
import ru.dbotthepony.mc.otm.capability.matter.IMatterTaskProvider; import ru.dbotthepony.mc.otm.capability.matter.IReplicationTaskProvider;
import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage; import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage;
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode; import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode;
import ru.dbotthepony.mc.otm.graph.storage.IStorageGraphNode; import ru.dbotthepony.mc.otm.graph.storage.IStorageGraphNode;
@ -36,7 +36,7 @@ public class MatteryCapability {
@Nonnull @Nonnull
@NotNull @NotNull
public static final Capability<IMatterTaskProvider> TASK = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability<IReplicationTaskProvider> TASK = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull @Nonnull
@NotNull @NotNull
@ -49,16 +49,4 @@ public class MatteryCapability {
@Nonnull @Nonnull
@NotNull @NotNull
public static final Capability<IStrictEnergyHandler> MEKANISM_ENERGY = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability<IStrictEnergyHandler> MEKANISM_ENERGY = CapabilityManager.get(new CapabilityToken<>() {});
@SuppressWarnings("unused")
public static void register(final RegisterCapabilitiesEvent event) {
event.register(IMatteryEnergyStorage.class);
event.register(MatteryPlayerCapability.class);
event.register(IMatterHandler.class);
event.register(IPatternStorage.class);
event.register(IMatterTaskProvider.class);
event.register(IMatteryDrive.class);
event.register(IStorageGraphNode.class);
event.register(IMatterGraphNode.class);
}
} }

View File

@ -1,147 +0,0 @@
package ru.dbotthepony.mc.otm.capability.matter;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.RegistryManager;
import ru.dbotthepony.mc.otm.UnOverengineeringKt;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Objects;
import java.util.UUID;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public record MatterTask(UUID id, @Nullable UUID pattern, Item item, int in_progress, int finished, int required) {
public MatterTask(UUID id, @Nullable UUID pattern, Item item, int in_progress, int finished, int required) {
this.id = id;
this.pattern = pattern;
this.item = item;
this.in_progress = Math.max(0, in_progress);
this.finished = Math.max(0, finished);
this.required = Math.max(0, required);
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MatterTask obj1)
return obj1.id.equals(id);
return false;
}
public ItemStack stack() {
return new ItemStack(item, 1);
}
public ItemStack stack(int amount) {
return new ItemStack(item, amount);
}
public int total() {
return in_progress + finished + required;
}
public MatterTask shrinkRequired(int amount) {
return new MatterTask(id, pattern, item, in_progress + amount, finished, required - amount);
}
public MatterTask shrinkInProgress(int amount) {
return new MatterTask(id, pattern, item, in_progress - amount, finished + amount, required);
}
public CompoundTag serializeNBT() {
CompoundTag tag = new CompoundTag();
tag.putLong("id_l", id.getLeastSignificantBits());
tag.putLong("id_u", id.getMostSignificantBits());
if (pattern != null) {
tag.putLong("pattern_l", pattern.getLeastSignificantBits());
tag.putLong("pattern_u", pattern.getMostSignificantBits());
}
tag.putString("item", Objects.requireNonNull(UnOverengineeringKt.getRegistryName(item)).toString());
tag.putInt("in_progress", in_progress);
tag.putInt("finished", finished);
tag.putInt("required", required);
return tag;
}
@Nullable
public static MatterTask deserializeNBT(@Nullable Tag nbt) {
if (nbt == null)
return null;
if (nbt instanceof CompoundTag tag) {
Item get_item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(tag.getString("item")));
if (get_item != null && get_item != Items.AIR) {
long a = tag.getLong("pattern_u");
long b = tag.getLong("pattern_l");
UUID pattern = a != 0 && b != 0 ? new UUID(a, b) : null;
return new MatterTask(
new UUID(tag.getLong("id_u"), tag.getLong("id_l")),
pattern,
get_item,
tag.getInt("in_progress"),
tag.getInt("finished"),
tag.getInt("required")
);
}
}
return null;
}
public void write(FriendlyByteBuf buffer) {
buffer.writeLong(id.getMostSignificantBits());
buffer.writeLong(id.getLeastSignificantBits());
if (pattern != null) {
buffer.writeBoolean(true);
buffer.writeLong(pattern.getMostSignificantBits());
buffer.writeLong(pattern.getLeastSignificantBits());
} else {
buffer.writeBoolean(false);
}
buffer.writeInt(((ForgeRegistry<Item>) ForgeRegistries.ITEMS).getID(item));
buffer.writeInt(in_progress);
buffer.writeInt(finished);
buffer.writeInt(required);
}
@Nullable
public static MatterTask read(FriendlyByteBuf buffer) {
var id = new UUID(buffer.readLong(), buffer.readLong());
var pattern = buffer.readBoolean() ? new UUID(buffer.readLong(), buffer.readLong()) : null;
var item = ((ForgeRegistry<Item>) ForgeRegistries.ITEMS).getValue(buffer.readInt());
if (item == null)
return null;
var in_progress = buffer.readInt();
var finished = buffer.readInt();
var required = buffer.readInt();
return new MatterTask(id, pattern, item, in_progress, finished, required);
}
}

View File

@ -1,95 +0,0 @@
package ru.dbotthepony.mc.otm.capability.matter;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.RegistryManager;
import ru.dbotthepony.mc.otm.UnOverengineeringKt;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;
import java.util.UUID;
public record PatternState(@Nonnull UUID id, @Nonnull Item item, double research) {
public PatternState(@Nonnull UUID id, @Nonnull Item item, double research) {
this.id = id;
this.item = item;
this.research = Math.max(0, Math.min(1, research));
}
@Override
public boolean equals(Object state) {
if (state instanceof PatternState state1)
return state1.id.equals(id);
return false;
}
public ItemStack stack() {
return new ItemStack(item, 1);
}
@Override
public int hashCode() {
return id.hashCode();
}
public CompoundTag serializeNBT() {
var tag = new CompoundTag();
tag.putLong("id_m", id.getMostSignificantBits());
tag.putLong("id_l", id.getLeastSignificantBits());
tag.putString("item", Objects.requireNonNull(UnOverengineeringKt.getRegistryName(item)).toString());
tag.putDouble("research_percent", research);
return tag;
}
@Nullable
public static PatternState deserializeNBT(Tag nbt) {
if (nbt instanceof CompoundTag tag) {
var item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(tag.getString("item")));
if (item == null)
return null;
var id = new UUID(tag.getLong("id_m"), tag.getLong("id_l"));
var research_percent = tag.getDouble("research_percent");
return new PatternState(id, item, research_percent);
}
return null;
}
public void write(FriendlyByteBuf buffer) {
buffer.writeLong(id.getMostSignificantBits());
buffer.writeLong(id.getLeastSignificantBits());
buffer.writeInt(((ForgeRegistry<Item>) ForgeRegistries.ITEMS).getID(item));
buffer.writeDouble(research);
}
@Nullable
public static PatternState read(FriendlyByteBuf buffer) {
long ida = buffer.readLong();
long idb = buffer.readLong();
int item = buffer.readInt();
double percent = buffer.readDouble();
Item get_item = ((ForgeRegistry<Item>) ForgeRegistries.ITEMS).getValue(item);
if (get_item == null)
return null;
return new PatternState(new UUID(ida, idb), get_item, percent);
}
}

View File

@ -1,401 +0,0 @@
package ru.dbotthepony.mc.otm.client.screen;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.item.ItemStack;
import ru.dbotthepony.mc.otm.capability.matter.MatterTask;
import ru.dbotthepony.mc.otm.capability.matter.PatternState;
import ru.dbotthepony.mc.otm.menu.MatterPanelMenu;
import ru.dbotthepony.mc.otm.menu.ReplicationRequestPacket;
import ru.dbotthepony.mc.otm.network.MenuNetworkChannel;
import ru.dbotthepony.mc.otm.client.screen.panels.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import static ru.dbotthepony.mc.otm.UnOverengineeringKt.TextComponent;
import static ru.dbotthepony.mc.otm.UnOverengineeringKt.TranslatableComponent;
public class MatterPanelScreen extends MatteryScreen<MatterPanelMenu> {
private static final int MODAL_WIDTH = 213;
private static final int MODAL_HEIGHT = 110;
public MatterPanelScreen(MatterPanelMenu p_97741_, Inventory p_97742_, Component p_97743_) {
super(p_97741_, p_97742_, p_97743_);
imageWidth = 176;
imageHeight = 187;
titleLabelY = 5;
}
public static final int GRID_WIDTH = 8;
public static final int GRID_HEIGHT = 9;
private final ArrayList<AbstractSlotPanel> pattern_slots = new ArrayList<>();
private final ArrayList<AbstractSlotPanel> task_slots = new ArrayList<>();
@Nullable
@Override
protected FramePanel makeMainFrame() {
float width = GRID_WIDTH * AbstractSlotPanel.SIZE + ScrollBarConstants.WIDTH + FramePanel.PADDING * 2 + 8;
float height = GRID_HEIGHT * AbstractSlotPanel.SIZE + FramePanel.PADDING_TOP + FramePanel.PADDING;
var scroll_panel = new ContinuousScrollBarPanel(this, null, 0, 0, 0);
var frame = new FramePanel(this, null, 0, 0, width, height, getTitle()) {
@Override
protected boolean mouseScrolledInner(double x, double y, double scroll) {
return scroll_panel.mouseScrolledInner(x, y, scroll);
}
};
var patterns_tab = frame.addTab(FramePanel.Position.TOP, () -> {
for (var slot : pattern_slots) {
slot.setVisible(true);
}
}, () -> {
for (var slot : pattern_slots) {
slot.setVisible(false);
}
});
var tasks_tab = frame.addTab(FramePanel.Position.TOP, () -> {
for (var slot : task_slots) {
slot.setVisible(true);
}
}, () -> {
for (var slot : task_slots) {
slot.setVisible(false);
}
});
scroll_panel.setParent(frame);
scroll_panel.setDock(Dock.RIGHT);
scroll_panel.setupRowMultiplier(() -> {
if (tasks_tab.isActive()) {
return menu.getTasks().size() / GRID_WIDTH;
}
return menu.getPatterns().size() / GRID_WIDTH;
});
var grid = new GridPanel(this, frame, 0, 0, GRID_WIDTH * AbstractSlotPanel.SIZE, 0, GRID_WIDTH, GRID_HEIGHT) {
@Override
protected boolean mouseScrolledInner(double x, double y, double scroll) {
return scroll_panel.mouseScrolledInner(x, y, scroll);
}
};
grid.setDock(Dock.LEFT);
grid.setDockMargin(4, 0, 0, 0);
for (int i = 0; i < GRID_WIDTH * GRID_HEIGHT; i++) {
int slot = i;
pattern_slots.add(new AbstractSlotPanel(this, grid, 0, 0) {
@Nonnull
@Override
protected ItemStack getItemStack() {
var slot1 = slot + scroll_panel.getScroll(menu.getPatterns().size() / GRID_WIDTH) * GRID_WIDTH;
if (slot1 >= menu.getPatterns().size()) {
return ItemStack.EMPTY;
}
return menu.getPatterns().get(slot1).stack();
}
@Nonnull
@Override
protected List<Component> getItemStackTooltip(@Nonnull ItemStack stack) {
var slot1 = slot + scroll_panel.getScroll(menu.getPatterns().size() / GRID_WIDTH) * GRID_WIDTH;
if (slot1 >= menu.getPatterns().size()) {
return List.of();
}
return getPatternTooltip(super.getItemStackTooltip(stack), menu.getPatterns().get(slot1));
}
@Override
protected boolean mouseScrolledInner(double x, double y, double scroll) {
return scroll_panel.mouseScrolledInner(x, y, scroll);
}
@Override
protected boolean mouseClickedInner(double x, double y, int flag) {
if (slot >= menu.getPatterns().size()) {
return true;
}
openPattern(menu.getPatterns().get(slot));
return true;
}
});
task_slots.add(new AbstractSlotPanel(this, grid, 0, 0) {
@Nonnull
@Override
protected ItemStack getItemStack() {
var slot1 = slot + scroll_panel.getScroll(menu.getTasks().size() / GRID_WIDTH) * GRID_WIDTH;
if (slot1 >= menu.getTasks().size()) {
return ItemStack.EMPTY;
}
var task = menu.getTasks().get(slot1);
return task.stack(Math.max(task.required(), 1));
}
@Nonnull
@Override
protected List<Component> getItemStackTooltip(@Nonnull ItemStack stack) {
var slot1 = slot + scroll_panel.getScroll(menu.getTasks().size() / GRID_WIDTH) * GRID_WIDTH;
if (slot1 >= menu.getTasks().size()) {
return List.of();
}
return getTaskTooltip(super.getItemStackTooltip(stack), menu.getTasks().get(slot1));
}
@Override
protected boolean mouseScrolledInner(double x, double y, double scroll) {
return scroll_panel.mouseScrolledInner(x, y, scroll);
}
@Override
protected boolean mouseClickedInner(double x, double y, int flag) {
if (slot >= menu.getTasks().size()) {
return true;
}
openTask(menu.getTasks().get(slot));
return true;
}
});
}
for (var slot : task_slots) {
slot.setVisible(false);
}
return frame;
}
private List<Component> getTaskTooltip(List<Component> input, MatterTask task) {
input.add(TranslatableComponent("otm.gui.matter_task.total", task.total()).withStyle(ChatFormatting.GRAY));
input.add(TranslatableComponent("otm.gui.matter_task.required", task.required()).withStyle(ChatFormatting.GRAY));
input.add(TranslatableComponent("otm.gui.matter_task.in_progress", task.in_progress()).withStyle(ChatFormatting.GRAY));
input.add(TranslatableComponent("otm.gui.matter_task.finished", task.finished()).withStyle(ChatFormatting.GRAY));
return input;
}
private List<Component> getPatternTooltip(List<Component> input, PatternState pattern) {
input.add(TranslatableComponent("otm.item.pattern.research", String.format("%.2f", pattern.research() * 100d)).withStyle(ChatFormatting.AQUA));
return input;
}
private void openTask(MatterTask task) {
var task_frame = new FramePanel(this, null, 0, 0, 170, 40, TranslatableComponent("otm.container.matter_panel.task")) {
@Override
public void tick() {
super.tick();
if (!menu.getTasks().contains(task)) {
remove();
}
}
};
var slot = new AbstractSlotPanel(this, task_frame, 0, 0) {
@Nonnull
@Override
protected ItemStack getItemStack() {
var task1_index = menu.getTasks().indexOf(task);
if (task1_index != -1) {
var task1 = menu.getTasks().get(task1_index);
return task1.stack(Math.max(task1.required(), 1));
}
return ItemStack.EMPTY;
}
@Nonnull
@Override
protected List<Component> getItemStackTooltip(@Nonnull ItemStack stack) {
var task1_index = menu.getTasks().indexOf(task);
List<Component> get_list = super.getItemStackTooltip(stack);
if (task1_index != -1) {
getTaskTooltip(get_list, menu.getTasks().get(task1_index));
}
return get_list;
}
};
slot.setDock(Dock.LEFT);
var button = new ButtonPanel(this, task_frame, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.close"));
button.setDock(Dock.RIGHT);
button.setDockMargin(2, 0, 0, 0);
button.bind(task_frame::remove);
button = new ButtonPanel(this, task_frame, 0, 0, 80, 20, TranslatableComponent("otm.container.matter_panel.cancel_task"));
button.setDock(Dock.RIGHT);
button.setDockMargin(2, 0, 0, 0);
button.bind(() -> {
menu.requestTaskCancel(task.id());
task_frame.remove();
});
task_frame.toScreenCenter();
addPanel(task_frame);
}
private void openPattern(PatternState state) {
var pattern_frame = new FramePanel(this, null, 0, 0, MODAL_WIDTH, MODAL_HEIGHT, TranslatableComponent("otm.container.matter_panel.label")){
@Override
public void tick() {
super.tick();
if (!menu.getPatterns().contains(state)) {
remove();
}
}
};
var row_1 = new EditablePanel(this, pattern_frame);
var row_2 = new EditablePanel(this, pattern_frame);
var row_3 = new EditablePanel(this, pattern_frame);
var row_4 = new EditablePanel(this, pattern_frame);
row_1.setDock(Dock.TOP);
row_2.setDock(Dock.TOP);
row_3.setDock(Dock.TOP);
row_4.setDock(Dock.TOP);
row_1.setHeight(20);
row_2.setHeight(20);
row_3.setHeight(20);
row_4.setHeight(20);
row_1.setDockMargin(0, 2, 0, 0);
row_2.setDockMargin(0, 2, 0, 0);
row_3.setDockMargin(0, 2, 0, 0);
row_4.setDockMargin(0, 2, 0, 0);
var slot = new AbstractSlotPanel(this, row_2, 0, 0) {
@Nonnull
@Override
protected ItemStack getItemStack() {
return new ItemStack(state.item(), 1);
}
@Nonnull
@Override
protected List<Component> getItemStackTooltip(@Nonnull ItemStack stack) {
return getPatternTooltip(super.getItemStackTooltip(stack), state);
}
};
var input_amount = new EditBoxPanel(this, row_2, 0, 0, 10, 20, TextComponent("Input amount")) {
@Override
protected void configureNew(@Nonnull EditBox widget, boolean recreation) {
super.configureNew(widget, recreation);
widget.setMaxLength(6);
if (!recreation) {
widget.setValue("1");
}
}
private void increase(int amount) {
int value = 1;
try {
value = Integer.parseInt(getOrCreateWidget().getValue());
} catch (Exception ignored) {
}
if (value == 1 && amount > 0)
getOrCreateWidget().setValue(Integer.toString(amount));
else
getOrCreateWidget().setValue(Integer.toString(Math.max(1, Math.min(99999, value + amount))));
}
};
var button = new ButtonPanel(this, row_1, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.increase_by", 8));
button.bind(() -> input_amount.increase(8));
button.setDock(Dock.RIGHT);
button.setDockMargin(2, 0, 0, 0);
button = new ButtonPanel(this, row_1, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.increase_by", 64));
button.setDock(Dock.RIGHT);
button.bind(() -> input_amount.increase(64));
button.setDockMargin(2, 0, 0, 0);
button = new ButtonPanel(this, row_1, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.increase_by", 256));
button.setDock(Dock.RIGHT);
button.bind(() -> input_amount.increase(256));
button.setDockMargin(2, 0, 0, 0);
slot.setDock(Dock.LEFT);
slot.setDockMargin(0, 0, 4, 0);
input_amount.setDock(Dock.FILL);
button = new ButtonPanel(this, row_3, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.decrease_by", 8));
button.bind(() -> input_amount.increase(-8));
button.setDock(Dock.RIGHT);
button.setDockMargin(2, 0, 0, 0);
button = new ButtonPanel(this, row_3, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.decrease_by", 64));
button.setDock(Dock.RIGHT);
button.bind(() -> input_amount.increase(-64));
button.setDockMargin(2, 0, 0, 0);
button = new ButtonPanel(this, row_3, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.decrease_by", 256));
button.setDock(Dock.RIGHT);
button.bind(() -> input_amount.increase(-256));
button.setDockMargin(2, 0, 0, 0);
button = new ButtonPanel(this, row_4, 0, 0, 40, 20, TranslatableComponent("otm.container.matter_panel.cancel"));
button.setDock(Dock.RIGHT);
button.bind(pattern_frame::remove);
button.setDockMargin(2, 0, 0, 0);
button = new ButtonPanel(this, row_4, 0, 0, 82, 20, TranslatableComponent("otm.container.matter_panel.send"));
button.setDock(Dock.RIGHT);
button.bind(() -> {
int value = 1;
try {
value = Integer.parseInt(input_amount.getOrCreateWidget().getValue());
} catch (Exception ignored) {
}
MenuNetworkChannel.INSTANCE.sendToServer(new ReplicationRequestPacket(state, value));
pattern_frame.remove();
});
button.setDockMargin(2, 0, 0, 0);
addPanel(pattern_frame);
pattern_frame.toScreenCenter();
popup(pattern_frame);
}
}

View File

@ -4,6 +4,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.item.crafting.RecipeType;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistries;
@ -35,8 +36,8 @@ public class MRecipes {
typesRegistry.register(MNames.PLATE_PRESS, () -> PLATE_PRESS); typesRegistry.register(MNames.PLATE_PRESS, () -> PLATE_PRESS);
} }
public static void register() { public static void register(IEventBus bus) {
registry.register(FMLJavaModLoadingContext.get().getModEventBus()); registry.register(bus);
typesRegistry.register(FMLJavaModLoadingContext.get().getModEventBus()); typesRegistry.register(bus);
} }
} }

View File

@ -1,213 +0,0 @@
@file:Suppress("unused")
package ru.dbotthepony.mc.otm
import com.google.common.collect.ImmutableList
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.core.Vec3i
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.LongArrayTag
import net.minecraft.nbt.Tag
import net.minecraft.world.Container
import net.minecraft.world.entity.Entity
import net.minecraft.world.item.ItemStack
import net.minecraft.world.phys.Vec3
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.IItemHandler
import java.util.*
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
operator fun Direction.unaryMinus(): Direction = this.opposite
operator fun Vec3i.unaryMinus(): Vec3i = Vec3i(-x, -y, -z)
operator fun BlockPos.unaryMinus(): BlockPos = BlockPos(-x, -y, -z)
operator fun CompoundTag.set(index: String, value: Tag) = put(index, value)
operator fun CompoundTag.set(index: String, value: Int) = putInt(index, value)
operator fun CompoundTag.set(index: String, value: Byte) = putByte(index, value)
operator fun CompoundTag.set(index: String, value: Short) = putShort(index, value)
operator fun CompoundTag.set(index: String, value: Long) = putLong(index, value)
operator fun CompoundTag.set(index: String, value: Float) = putFloat(index, value)
operator fun CompoundTag.set(index: String, value: Double) = putDouble(index, value)
operator fun CompoundTag.set(index: String, value: String) = putString(index, value)
operator fun CompoundTag.set(index: String, value: Boolean) = putBoolean(index, value)
operator fun CompoundTag.set(index: String, value: ByteArray) = putByteArray(index, value)
operator fun CompoundTag.set(index: String, value: IntArray) = putIntArray(index, value)
operator fun CompoundTag.set(index: String, value: LongArray) = putLongArray(index, value)
@JvmInline
value class CompoundTagInt(val tag: CompoundTag) : ReadWriteProperty<Any, Int> {
override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getInt(property.name)
override fun setValue(thisRef: Any, property: KProperty<*>, value: Int) = tag.putInt(property.name, value)
}
@JvmInline
value class CompoundTagLong(val tag: CompoundTag) : ReadWriteProperty<Any, Long> {
override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getLong(property.name)
override fun setValue(thisRef: Any, property: KProperty<*>, value: Long) = tag.putLong(property.name, value)
}
@JvmInline
value class CompoundTagByte(val tag: CompoundTag) : ReadWriteProperty<Any, Byte> {
override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getByte(property.name)
override fun setValue(thisRef: Any, property: KProperty<*>, value: Byte) = tag.putByte(property.name, value)
}
@JvmInline
value class CompoundTagShort(val tag: CompoundTag) : ReadWriteProperty<Any, Short> {
override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getShort(property.name)
override fun setValue(thisRef: Any, property: KProperty<*>, value: Short) = tag.putShort(property.name, value)
}
@JvmInline
value class CompoundTagFloat(val tag: CompoundTag) : ReadWriteProperty<Any, Float> {
override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getFloat(property.name)
override fun setValue(thisRef: Any, property: KProperty<*>, value: Float) = tag.putFloat(property.name, value)
}
@JvmInline
value class CompoundTagBoolean(val tag: CompoundTag) : ReadWriteProperty<Any, Boolean> {
override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getBoolean(property.name)
override fun setValue(thisRef: Any, property: KProperty<*>, value: Boolean) = tag.putBoolean(property.name, value)
}
@JvmInline
value class CompoundTagDouble(val tag: CompoundTag) : ReadWriteProperty<Any, Double> {
override fun getValue(thisRef: Any, property: KProperty<*>) = tag.getDouble(property.name)
override fun setValue(thisRef: Any, property: KProperty<*>, value: Double) = tag.putDouble(property.name, value)
}
@JvmInline
value class CompoundTagString(val tag: CompoundTag) : ReadWriteProperty<Any, String> {
override fun getValue(thisRef: Any, property: KProperty<*>): String = tag.getString(property.name)
override fun setValue(thisRef: Any, property: KProperty<*>, value: String) = tag.putString(property.name, value)
}
val EMPTY_UUID = UUID(0L, 0L)
@JvmInline
value class CompoundTagUUID(val tag: CompoundTag) : ReadWriteProperty<Any, UUID> {
override fun getValue(thisRef: Any, property: KProperty<*>) = (tag.get(property.name) as LongArrayTag?)?.asLongArray?.let { UUID(it[0], it[1]) } ?: EMPTY_UUID
override fun setValue(thisRef: Any, property: KProperty<*>, value: UUID) = tag.putLongArray(property.name, longArrayOf(value.mostSignificantBits, value.leastSignificantBits))
}
val CompoundTag.ints get() = CompoundTagInt(this)
val CompoundTag.longs get() = CompoundTagLong(this)
val CompoundTag.bytes get() = CompoundTagByte(this)
val CompoundTag.shorts get() = CompoundTagShort(this)
val CompoundTag.floats get() = CompoundTagFloat(this)
val CompoundTag.doubles get() = CompoundTagDouble(this)
val CompoundTag.booleans get() = CompoundTagBoolean(this)
val CompoundTag.strings get() = CompoundTagString(this)
val CompoundTag.uuids get() = CompoundTagUUID(this)
operator fun Container.set(index: Int, value: ItemStack) = setItem(index, value)
operator fun Container.get(index: Int): ItemStack = getItem(index)
operator fun IItemHandler.get(index: Int): ItemStack = getStackInSlot(index)
operator fun JsonObject.set(s: String, value: JsonElement) = add(s, value)
inline fun CompoundTag.ifHas(s: String, consumer: (Tag) -> Unit) {
val tag = get(s)
if (tag != null) {
consumer(tag)
}
}
inline fun CompoundTag.ifHas(s: String, type: Byte, consumer: (Tag) -> Unit) {
val tag = get(s)
if (tag != null && tag.id == type) {
consumer(tag)
}
}
inline fun <reified T : Tag> CompoundTag.ifHas(s: String, type: Class<T>, consumer: (T) -> Unit) {
val tag = get(s)
if (tag != null && tag::class.java === type) {
consumer(tag as T)
}
}
fun <T> LazyOptional<T>.orNull(): T? {
if (!isPresent) {
return null
}
return resolve().orElse(null)
}
fun <T> LazyOptional<T>.orThrow(): T {
if (!isPresent) {
throw IllegalStateException("Capability was expected to be not null")
}
return resolve().orElse(null) ?: throw IllegalStateException("Capability was expected to be not null")
}
inline fun <T> LazyOptional<T>.ifPresentK(lambda: (T) -> Unit) {
if (isPresent) {
val value = resolve().orElse(null) ?: throw IllegalStateException("Capability was expected to be not null")
lambda.invoke(value)
}
}
val ItemStack.tagNotNull: CompoundTag get() = orCreateTag
inline var Entity.position: Vec3
get() = position()
set(value) { setPos(value) }
inline val <reified T : Enum<T>> T.next: T get() {
val values = enumValues<T>()
val next = (ordinal + 1) % values.size
return values[next]
}
inline val <reified T : Enum<T>> T.prev: T get() {
val values = enumValues<T>()
var next = ordinal - 1
if (next < 0) {
next = values.size - 1
}
return values[next]
}
fun <T : Enum<T>> T.next(values: Array<out T>): T {
val next = (ordinal + 1) % values.size
return values[next]
}
fun <T : Enum<T>> T.prev(values: Array<out T>): T {
var next = ordinal - 1
if (next < 0) {
next = values.size - 1
}
return values[next]
}
inline fun <T> ImmutableList(size: Int, initializer: (index: Int) -> T): ImmutableList<T> {
require(size >= 0) { "Invalid list size $size" }
return when (size) {
0 -> ImmutableList.of()
1 -> ImmutableList.of(initializer(0))
else -> ImmutableList.Builder<T>().let {
for (i in 0 until size) {
it.add(initializer(i))
}
it.build()
}
}
}

View File

@ -118,6 +118,8 @@ private var _server: MinecraftServer? = null
private var _serverThread: Thread? = null private var _serverThread: Thread? = null
private var _clientThread: Thread? = null private var _clientThread: Thread? = null
val isClient: Boolean get() = _clientThread !== null
fun recordClientThread() { fun recordClientThread() {
if (_clientThread != null) { if (_clientThread != null) {
throw IllegalStateException("Already have client channel") throw IllegalStateException("Already have client channel")
@ -127,13 +129,13 @@ fun recordClientThread() {
} }
fun runIfClient(lambda: () -> Unit) { fun runIfClient(lambda: () -> Unit) {
if (_clientThread !== null) { if (isClient) {
lambda.invoke() lambda.invoke()
} }
} }
fun <V> runIfClient(value: V, lambda: () -> V): V { fun <V> runIfClient(value: V, lambda: () -> V): V {
if (_clientThread !== null) { if (isClient) {
return lambda.invoke() return lambda.invoke()
} }
@ -178,7 +180,6 @@ interface IConditionalTickable : ITickable {
val canTick: Boolean val canTick: Boolean
} }
@SubscribeEvent(priority = EventPriority.LOWEST)
fun onServerTick(event: ServerTickEvent) { fun onServerTick(event: ServerTickEvent) {
if (event.phase === TickEvent.Phase.START) { if (event.phase === TickEvent.Phase.START) {
preServerTickTimers.tick() preServerTickTimers.tick()
@ -253,7 +254,6 @@ fun addPostServerTickerOnce(ticker: ITickable) {
postServerTickOnce.add(ticker) postServerTickOnce.add(ticker)
} }
@SubscribeEvent(priority = EventPriority.LOWEST)
fun onWorldTick(event: LevelTickEvent) { fun onWorldTick(event: LevelTickEvent) {
if (event.phase === TickEvent.Phase.START) { if (event.phase === TickEvent.Phase.START) {
val it = preWorldTick[event.level] val it = preWorldTick[event.level]
@ -353,7 +353,6 @@ private fun clear() {
postWorldTickOnce.clear() postWorldTickOnce.clear()
} }
@SubscribeEvent(priority = EventPriority.HIGHEST)
fun onServerStarting(event: ServerAboutToStartEvent) { fun onServerStarting(event: ServerAboutToStartEvent) {
clear() clear()
SERVER_IS_DYING = false SERVER_IS_DYING = false
@ -361,13 +360,11 @@ fun onServerStarting(event: ServerAboutToStartEvent) {
_serverThread = Thread.currentThread() _serverThread = Thread.currentThread()
} }
@SubscribeEvent(priority = EventPriority.HIGHEST)
fun onServerStopping(event: ServerStoppingEvent) { fun onServerStopping(event: ServerStoppingEvent) {
clear() clear()
SERVER_IS_DYING = true SERVER_IS_DYING = true
} }
@SubscribeEvent(priority = EventPriority.HIGHEST)
fun onServerStopped(event: ServerStoppedEvent) { fun onServerStopped(event: ServerStoppedEvent) {
if (!SERVER_IS_DYING) { if (!SERVER_IS_DYING) {
LOGGER.fatal("ServerStoppingEvent did not fire. If server has crashed this is normal. However, if server finished it's work 'gracefully' this is a bug.") LOGGER.fatal("ServerStoppingEvent did not fire. If server has crashed this is normal. However, if server finished it's work 'gracefully' this is a bug.")

View File

@ -4,9 +4,10 @@ import net.minecraft.nbt.CompoundTag
import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.event.entity.living.LivingHurtEvent import net.minecraftforge.event.entity.living.LivingHurtEvent
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.readNbt import ru.dbotthepony.mc.otm.core.readNbt
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.writeNbt import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.core.writeNbt
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream

View File

@ -5,7 +5,7 @@ import net.minecraft.network.chat.ComponentContents
import net.minecraft.network.chat.MutableComponent import net.minecraft.network.chat.MutableComponent
import net.minecraft.network.chat.contents.TranslatableContents import net.minecraft.network.chat.contents.TranslatableContents
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.getKeyNullable import ru.dbotthepony.mc.otm.core.getKeyNullable
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
open class AndroidFeatureType<T : AndroidFeature> { open class AndroidFeatureType<T : AndroidFeature> {

View File

@ -7,9 +7,10 @@ import net.minecraft.world.item.ItemStack
import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.common.util.INBTSerializable
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.client.render.SkinElement import ru.dbotthepony.mc.otm.client.render.SkinElement
import ru.dbotthepony.mc.otm.readNbt import ru.dbotthepony.mc.otm.core.readNbt
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.writeNbt import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.core.writeNbt
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream

View File

@ -6,9 +6,10 @@ import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.client.render.SkinElement import ru.dbotthepony.mc.otm.client.render.SkinElement
import ru.dbotthepony.mc.otm.container.iterator import ru.dbotthepony.mc.otm.container.iterator
import ru.dbotthepony.mc.otm.core.nonEmpty
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
@ -260,7 +261,7 @@ class AndroidResearchBuilder(
for (item in items) { for (item in items) {
var required = item.count var required = item.count
val iterator = capability.ply.inventory.iterator() val iterator = capability.ply.inventory.iterator().nonEmpty()
for (invItem in iterator) { for (invItem in iterator) {
if (ItemStack.isSameItemSameTags(invItem, item)) { if (ItemStack.isSameItemSameTags(invItem, item)) {
@ -335,7 +336,8 @@ class AndroidResearchBuilder(
} }
if (experience != 0) { if (experience != 0) {
builder.add(TranslatableComponent("otm.android_station.research.xp_cost", experience).withStyle( builder.add(
TranslatableComponent("otm.android_station.research.xp_cost", experience).withStyle(
if (capability.ply.experienceLevel >= experience) if (capability.ply.experienceLevel >= experience)
ChatFormatting.DARK_GREEN ChatFormatting.DARK_GREEN
else else
@ -346,7 +348,8 @@ class AndroidResearchBuilder(
for (value in this.type.flatPrerequisites) { for (value in this.type.flatPrerequisites) {
val instance = capability.getResearch(value) val instance = capability.getResearch(value)
builder.add(TranslatableComponent("android_research.status.requires", instance.screenTooltipHeader).withStyle( builder.add(
TranslatableComponent("android_research.status.requires", instance.screenTooltipHeader).withStyle(
if (instance.isResearched) if (instance.isResearched)
ChatFormatting.DARK_GREEN ChatFormatting.DARK_GREEN
else else

View File

@ -6,9 +6,9 @@ import net.minecraft.network.chat.Component
import net.minecraft.network.chat.ComponentContents import net.minecraft.network.chat.ComponentContents
import net.minecraft.network.chat.MutableComponent import net.minecraft.network.chat.MutableComponent
import net.minecraft.network.chat.contents.TranslatableContents import net.minecraft.network.chat.contents.TranslatableContents
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.getKeyNullable import ru.dbotthepony.mc.otm.core.getKeyNullable
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
import java.util.* import java.util.*
import kotlin.collections.HashSet import kotlin.collections.HashSet

View File

@ -9,7 +9,8 @@ import ru.dbotthepony.mc.otm.capability.extractEnergyInnerExact
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.registry.AndroidFeatures import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.StatNames import ru.dbotthepony.mc.otm.registry.StatNames
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
import kotlin.math.roundToInt import kotlin.math.roundToInt
class NanobotsArmor(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.NANOBOTS_ARMOR, android) { class NanobotsArmor(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.NANOBOTS_ARMOR, android) {

View File

@ -8,7 +8,8 @@ import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.registry.AndroidFeatures import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.StatNames import ru.dbotthepony.mc.otm.registry.StatNames
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
import kotlin.math.roundToInt import kotlin.math.roundToInt
class NanobotsRegeneration(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.NANOBOTS_REGENERATION, android) { class NanobotsRegeneration(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.NANOBOTS_REGENERATION, android) {

View File

@ -16,7 +16,7 @@ import net.minecraft.world.phys.shapes.CollisionContext
import net.minecraft.world.phys.shapes.VoxelShape import net.minecraft.world.phys.shapes.VoxelShape
import ru.dbotthepony.mc.otm.block.entity.AndroidStationBlockEntity import ru.dbotthepony.mc.otm.block.entity.AndroidStationBlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.orNull import ru.dbotthepony.mc.otm.core.orNull
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.shapes.BlockShapes import ru.dbotthepony.mc.otm.shapes.BlockShapes

View File

@ -15,7 +15,7 @@ import net.minecraft.world.phys.shapes.CollisionContext
import net.minecraft.world.phys.shapes.VoxelShape import net.minecraft.world.phys.shapes.VoxelShape
import ru.dbotthepony.mc.otm.addPreWorldTickerOnce import ru.dbotthepony.mc.otm.addPreWorldTickerOnce
import ru.dbotthepony.mc.otm.block.entity.ChemicalGeneratorBlockEntity import ru.dbotthepony.mc.otm.block.entity.ChemicalGeneratorBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.shapes.BlockShapes import ru.dbotthepony.mc.otm.shapes.BlockShapes

View File

@ -25,7 +25,7 @@ import net.minecraft.world.phys.shapes.VoxelShape
import ru.dbotthepony.mc.otm.addPreWorldTickerOnce import ru.dbotthepony.mc.otm.addPreWorldTickerOnce
import ru.dbotthepony.mc.otm.block.entity.GravitationStabilizerBlockEntity import ru.dbotthepony.mc.otm.block.entity.GravitationStabilizerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.core.plus import ru.dbotthepony.mc.otm.core.plus
import ru.dbotthepony.mc.otm.core.times import ru.dbotthepony.mc.otm.core.times
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities

View File

@ -14,7 +14,7 @@ import net.minecraft.world.level.block.state.StateDefinition
import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.CollisionContext
import net.minecraft.world.phys.shapes.VoxelShape import net.minecraft.world.phys.shapes.VoxelShape
import ru.dbotthepony.mc.otm.block.entity.PlatePressBlockEntity import ru.dbotthepony.mc.otm.block.entity.PlatePressBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.shapes.BlockShapes import ru.dbotthepony.mc.otm.shapes.BlockShapes

View File

@ -9,7 +9,7 @@ import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.AABB import net.minecraft.world.phys.AABB
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.ImpreciseFraction

View File

@ -22,7 +22,7 @@ import ru.dbotthepony.mc.otm.block.BatteryBankBlock
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.capability.*
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.menu.BatteryBankMenu import ru.dbotthepony.mc.otm.menu.BatteryBankMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import javax.annotation.ParametersAreNonnullByDefault import javax.annotation.ParametersAreNonnullByDefault

View File

@ -12,13 +12,13 @@ import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.CargoCrateBlock import ru.dbotthepony.mc.otm.block.CargoCrateBlock
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.menu.CargoCrateMenu import ru.dbotthepony.mc.otm.menu.CargoCrateMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
class CargoCrateBlockEntity( class CargoCrateBlockEntity(
p_155229_: BlockPos, p_155229_: BlockPos,

View File

@ -19,11 +19,9 @@ import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.energy.IEnergyStorage import net.minecraftforge.energy.IEnergyStorage
import ru.dbotthepony.mc.otm.* import ru.dbotthepony.mc.otm.*
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState
import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.capability.*
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.plus
import ru.dbotthepony.mc.otm.menu.ChemicalGeneratorMenu import ru.dbotthepony.mc.otm.menu.ChemicalGeneratorMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import java.lang.ref.WeakReference import java.lang.ref.WeakReference

View File

@ -25,7 +25,7 @@ import ru.dbotthepony.mc.otm.*
import ru.dbotthepony.mc.otm.block.EnergyCounterBlock import ru.dbotthepony.mc.otm.block.EnergyCounterBlock
import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.capability.*
import ru.dbotthepony.mc.otm.compat.mekanism.MatteryToMekanismEnergyWrapper import ru.dbotthepony.mc.otm.compat.mekanism.MatteryToMekanismEnergyWrapper
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.menu.EnergyCounterMenu import ru.dbotthepony.mc.otm.menu.EnergyCounterMenu
import ru.dbotthepony.mc.otm.network.MatteryPacket import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.network.WorldNetworkChannel import ru.dbotthepony.mc.otm.network.WorldNetworkChannel

View File

@ -9,12 +9,11 @@ import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.AABB import net.minecraft.world.phys.AABB
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.BlockGravitationStabilizer import ru.dbotthepony.mc.otm.block.BlockGravitationStabilizer
import ru.dbotthepony.mc.otm.block.BlockGravitationStabilizerLens import ru.dbotthepony.mc.otm.block.BlockGravitationStabilizerLens
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState
import ru.dbotthepony.mc.otm.core.plus import ru.dbotthepony.mc.otm.core.plus
import ru.dbotthepony.mc.otm.core.times import ru.dbotthepony.mc.otm.core.times
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities

View File

@ -23,8 +23,9 @@ import net.minecraft.network.chat.Component
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
import ru.dbotthepony.mc.otm.addPreWorldTickerOnce import ru.dbotthepony.mc.otm.addPreWorldTickerOnce
import ru.dbotthepony.mc.otm.ifHas import ru.dbotthepony.mc.otm.core.ifHas
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : BlockEntity(p_155228_, p_155229_, p_155230_), MenuProvider { abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : BlockEntity(p_155228_, p_155229_, p_155230_), MenuProvider {
var customDisplayName: Component? = null var customDisplayName: Component? = null

View File

@ -8,13 +8,13 @@ import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.energy.CapabilityEnergy
import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.capability.*
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.ifHas import ru.dbotthepony.mc.otm.core.ifHas
import ru.dbotthepony.mc.otm.ifPresentK import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : MatteryBlockEntity(p_155228_, p_155229_, p_155230_) { abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : MatteryBlockEntity(p_155228_, p_155229_, p_155230_) {
abstract val energy: BlockEnergyStorageImpl abstract val energy: BlockEnergyStorageImpl

View File

@ -0,0 +1,342 @@
package ru.dbotthepony.mc.otm.block.entity
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.core.BlockPos
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.nbt.CompoundTag
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.Block
import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.map
private fun isReason(status: Any?, reason: Any) = status == null || status == reason
abstract class MatteryWorkerBlockEntity<JobType : MatteryWorkerBlockEntity.Job>(
type: BlockEntityType<*>,
blockPos: BlockPos,
blockState: BlockState,
val jobDeserializer: (tag: CompoundTag) -> JobType?
) : MatteryPoweredBlockEntity(type, blockPos, blockState) {
open class Job(
open val ticks: Double,
open val powerUsage: ImpreciseFraction = ImpreciseFraction.ZERO
) {
constructor(
tag: CompoundTag
) : this(tag.getDouble("ticks"), tag.getImpreciseFraction("power"))
open fun serializeNBT(): CompoundTag {
return CompoundTag().also {
it["ticks"] = ticks
it["power"] = powerUsage
}
}
}
@Suppress("LeakingThis")
open class ItemJob : Job {
open val itemStack: ItemStack
constructor(
itemStack: ItemStack,
ticks: Double,
power: ImpreciseFraction = ImpreciseFraction.ZERO
) : super(ticks, power) {
this.itemStack = itemStack
}
constructor(
tag: CompoundTag
) : super(tag) {
this.itemStack = (tag["item"] as? CompoundTag)?.let { ItemStack.of(it) } ?: ItemStack.EMPTY
}
override fun serializeNBT(): CompoundTag {
return super.serializeNBT().also {
it["item"] = itemStack.serializeNBT()
}
}
}
enum class IdleReason {
ITEM,
POWER,
MATTER,
/**
* Observing external factor, such as waiting for matter/item network tasks
*/
OBSERVING
}
data class Status(val success: Boolean, val throttleTicks: Int = 0, val idleReason: IdleReason? = null) {
companion object {
val SUCCESS = Status(true)
val FAILURE = Status(false)
val FAILURE_ITEM = Status(false, 20, IdleReason.ITEM)
val FAILURE_MATTER = Status(false, 20, IdleReason.MATTER)
val FAILURE_WAIT = Status(false, 100)
val FAILURE_WAIT_FAST = Status(false, 20)
}
}
var workTicks = 0.0
protected set
var throttleTicks = 0
protected set
var currentJob: JobType? = null
protected set
/**
* Can be whatever you want, but [IdleReason] certainly contains all cases
*/
var idleReason: Any? = null
private set
var isIdling = false
protected set
val isUnableToProcess: Boolean get() = throttleTicks > 0
val workProgress: Float
get() {
val currentJob = currentJob ?: return 0.0f
return (workTicks / currentJob.ticks).coerceAtMost(1.0).toFloat()
}
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt["work_ticks"] = workTicks
currentJob?.let { nbt["job"] = it.serializeNBT() }
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
workTicks = nbt.getDouble("work_ticks")
currentJob = nbt.map("job", jobDeserializer::invoke)
if (currentJob == null)
workTicks = 0.0
}
override fun setChanged() {
super.setChanged()
isIdling = false
}
override fun setChangedLight() {
super.setChangedLight()
isIdling = false
}
protected fun powerLevelUpdated() {
super.setChangedLight()
if (isReason(idleReason, IdleReason.POWER)) {
isIdling = false
throttleTicks = 0
}
}
protected fun itemContainerUpdated() {
super.setChanged()
if (isReason(idleReason, IdleReason.ITEM)) {
isIdling = false
throttleTicks = 0
}
}
protected fun matterLevelUpdated() {
super.setChangedLight()
if (isReason(idleReason, IdleReason.MATTER)) {
isIdling = false
throttleTicks = 0
}
}
/**
* Called whenever reaching desired amount of ticks at job
*/
protected abstract fun onJobFinish(job: JobType): Status
/**
* [Pair.second] is reason why job can't be performed
*
* If not null, it is written to [idleReason]
*/
protected abstract fun computeNextJob(): Pair<JobType?, Any?>
protected open fun onWorkTick(requiredPower: ImpreciseFraction, extractedPower: ImpreciseFraction, ticksAdvanced: Double): Status {
return Status.SUCCESS
}
private var idleTicksAnim = 0
private var workingTicksAnim = 0
private var errorTicksAnim = 0
override fun redstoneStatusUpdated(new_blocked: Boolean, old_blocked: Boolean) {
super.redstoneStatusUpdated(new_blocked, old_blocked)
isIdling = new_blocked
}
protected fun workerLoop() {
if (errorTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.ERROR) {
level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.ERROR), Block.UPDATE_CLIENTS)
}
if (throttleTicks > 0) {
workingTicksAnim = 0
idleTicksAnim = 0
throttleTicks--
errorTicksAnim++
if (throttleTicks > 0)
return
else
isIdling = false
}
if (isIdling) {
workingTicksAnim = 0
errorTicksAnim = 0
idleTicksAnim++
if (idleTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(
WorkerState.WORKER_STATE
) != WorkerState.IDLE
) {
level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS)
}
return
}
var availableTicks = 1.0
while (!isIdling && weakGreaterThan(availableTicks, 0.0)) {
if (isBlockedByRedstone) {
isIdling = true
break
}
var currentJob = currentJob
if (currentJob == null) {
if (isBlockedByRedstone) {
isIdling = true
break
}
val (job, reason) = computeNextJob()
if (job == null) {
idleReason = reason
isIdling = reason != null
workingTicksAnim = 0
break
}
this.currentJob = job
currentJob = job
}
if (!currentJob.powerUsage.isZero && energy.batteryLevel.isZero) {
idleReason = IdleReason.POWER
isIdling = true
idleTicksAnim++
if (idleTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(
WorkerState.WORKER_STATE
) != WorkerState.IDLE
) {
level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS)
}
break
}
idleTicksAnim = 0
if (weakLessThan(workTicks, currentJob.ticks)) {
val ticksLeft = currentJob.ticks - workTicks
val ticksAdvanced: Double
var requiredPower: ImpreciseFraction? = null
var extractedPower: ImpreciseFraction? = null
if (currentJob.powerUsage.isZero) {
ticksAdvanced = availableTicks.coerceAtMost(ticksLeft)
} else {
requiredPower = currentJob.powerUsage * ticksLeft.coerceAtMost(availableTicks)
extractedPower = energy.extractEnergyInner(requiredPower, true)
ticksAdvanced = (extractedPower / requiredPower).toDouble().coerceAtMost(ticksLeft).coerceAtMost(availableTicks)
}
if (weakEqualDoubles(ticksAdvanced, 0.0)) {
break
}
val status = onWorkTick(requiredPower ?: ImpreciseFraction.ZERO, extractedPower ?: ImpreciseFraction.ZERO, ticksAdvanced)
if (!status.success) {
throttleTicks += status.throttleTicks
if (status.idleReason != null) {
idleReason = status.idleReason
isIdling = true
}
break
}
workingTicksAnim++
errorTicksAnim = 0
workTicks += ticksAdvanced
availableTicks -= ticksAdvanced
if (extractedPower != null) {
energy.extractEnergyInner(extractedPower, false)
}
continue
}
val status = onJobFinish(currentJob)
if (status.success) {
this.currentJob = null
workTicks = 0.0
errorTicksAnim = 0
} else {
throttleTicks += status.throttleTicks
if (status.idleReason != null) {
idleReason = status.idleReason
isIdling = true
}
errorTicksAnim++
}
}
if (workingTicksAnim > 20 &&
errorTicksAnim == 0 &&
blockState.hasProperty(WorkerState.WORKER_STATE) &&
blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.WORKING
)
{
level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS)
}
}
fun basicTicker() {
batteryChargeLoop()
workerLoop()
}
}

View File

@ -1,5 +1,6 @@
package ru.dbotthepony.mc.otm.block.entity package ru.dbotthepony.mc.otm.block.entity
import com.google.common.collect.Streams
import javax.annotation.ParametersAreNonnullByDefault import javax.annotation.ParametersAreNonnullByDefault
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
@ -9,7 +10,6 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.block.matter.PatternStorageBlock import ru.dbotthepony.mc.otm.block.matter.PatternStorageBlock
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.CapabilityItemHandler
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.inventory.AbstractContainerMenu
@ -21,15 +21,19 @@ import net.minecraft.server.level.ServerLevel
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
import ru.dbotthepony.mc.otm.TranslatableComponent import net.minecraftforge.common.capabilities.ForgeCapabilities
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.capability.matter.* import ru.dbotthepony.mc.otm.capability.matter.*
import ru.dbotthepony.mc.otm.container.forEachCapability
import ru.dbotthepony.mc.otm.core.iterator
import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.ifHas import ru.dbotthepony.mc.otm.core.ifHas
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.core.set
import java.util.ArrayList import java.util.ArrayList
import java.util.stream.Stream
@MethodsReturnNonnullByDefault @MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
@ -48,13 +52,13 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
if (grid != null && !ItemStack.isSameItemSameTags(new, old)) { if (grid != null && !ItemStack.isSameItemSameTags(new, old)) {
if (!old.isEmpty) { if (!old.isEmpty) {
old.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage -> old.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage ->
cap.storedPatterns.forEach { state: PatternState? -> grid.onPatternRemoved(state!!) } cap.storedPatterns.forEach { grid.onPatternRemoved(it) }
} }
} }
if (!new.isEmpty) { if (!new.isEmpty) {
new.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage -> new.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage ->
cap.storedPatterns.forEach { state: PatternState? -> grid.onPatternAdded(state!!) } cap.storedPatterns.forEach { grid.onPatternAdded(it) }
} }
} }
@ -130,9 +134,9 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> { override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid) { if (valid) {
if (cap === MatteryCapability.PATTERN) return resolverPatterns.cast() if (cap == MatteryCapability.PATTERN) return resolverPatterns.cast()
if (cap === MatteryCapability.MATTER_NODE) return resolverNode.cast() if (cap == MatteryCapability.MATTER_NODE) return resolverNode.cast()
if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return resolverItem.get().cast() if (cap == ForgeCapabilities.ITEM_HANDLER) return resolverItem.get().cast()
} }
return super.getCapability(cap, side) return super.getCapability(cap, side)
@ -145,16 +149,20 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
return PatternStorageMenu(containerID, inventory, this) return PatternStorageMenu(containerID, inventory, this)
} }
override val storedPatterns: Collection<PatternState> get() { override val storedPatterns: Stream<out IPatternState> get() {
val list = ArrayList<PatternState>() val streams = ArrayList<Stream<out IPatternState>>()
patterns.consumeCapability(MatteryCapability.PATTERN) { capability: IPatternStorage -> list.addAll(capability.storedPatterns) }
return list for (provider in patterns.iterator(MatteryCapability.PATTERN)) {
streams.add(provider.second.storedPatterns)
}
return Streams.concat(*streams.toTypedArray())
} }
override val capacity: Int get() { override val capacity: Int get() {
var stored = 0L var stored = 0L
for (pattern in patterns.capabilityIterator(MatteryCapability.PATTERN)) for ((_, pattern) in patterns.iterator(MatteryCapability.PATTERN))
stored += pattern.capacity.toLong() stored += pattern.capacity.toLong()
return if (stored > Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt() return if (stored > Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt()
@ -163,7 +171,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override val stored: Int get() { override val stored: Int get() {
var stored = 0L var stored = 0L
for (pattern in patterns.capabilityIterator(MatteryCapability.PATTERN)) for ((_, pattern) in patterns.iterator(MatteryCapability.PATTERN))
stored += pattern.stored.toLong() stored += pattern.stored.toLong()
return if (stored > Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt() return if (stored > Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt()
@ -174,9 +182,9 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
matterNode.destroy(::MatterNetworkGraph) matterNode.destroy(::MatterNetworkGraph)
} }
override fun insertPattern(pattern: PatternState, only_update: Boolean, simulate: Boolean): PatternInsertStatus { override fun insertPattern(pattern: IPatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus {
for (storage in patterns.capabilityIterator(MatteryCapability.PATTERN)) { for (pair in patterns.iterator(MatteryCapability.PATTERN)) {
val status = storage.insertPattern(pattern, only_update, simulate) val status = pair.second.insertPattern(pattern, onlyUpdate, simulate)
if (!status.isFailed) { if (!status.isFailed) {
if (!simulate) { if (!simulate) {

View File

@ -10,12 +10,9 @@ import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.CapabilityItemHandler import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.worker.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJob
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJobStatus
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.MatteryContainerFilter import ru.dbotthepony.mc.otm.container.MatteryContainerFilter
@ -23,9 +20,13 @@ import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.menu.PlatePressMenu import ru.dbotthepony.mc.otm.menu.PlatePressMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MRecipes import ru.dbotthepony.mc.otm.registry.MRecipes
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
class PlatePressBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryWorkerBlockEntity(MBlockEntities.PLATE_PRESS, p_155229_, p_155230_) { class PlatePressBlockEntity(
p_155229_: BlockPos,
p_155230_: BlockState
) : MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.ItemJob>(MBlockEntities.PLATE_PRESS, p_155229_, p_155230_, ::ItemJob) {
val container = MatteryContainer(this::setChangedLight, 2) val container = MatteryContainer(this::setChangedLight, 2)
override val energy = WorkerEnergyStorage(this::setChangedLight) override val energy = WorkerEnergyStorage(this::setChangedLight)
@ -50,7 +51,7 @@ class PlatePressBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matter
} }
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> { override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) if (cap == ForgeCapabilities.ITEM_HANDLER)
return itemHandler.get().cast() return itemHandler.get().cast()
return super.getCapability(cap, side) return super.getCapability(cap, side)
@ -73,32 +74,24 @@ class PlatePressBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matter
return PlatePressMenu(containerID, inventory, this) return PlatePressMenu(containerID, inventory, this)
} }
override fun onJobFinish(job: WorkerJob): WorkerJobStatus { override fun onJobFinish(job: ItemJob): Status {
val resultTag = job.data["result"] as? CompoundTag ?: return WorkerJobStatus() if (job.itemStack.isEmpty)
val result = ItemStack.of(resultTag) return Status.SUCCESS
if (result.isEmpty) if (!container.fullyAddItem(job.itemStack, start = SLOT_OUTPUT, end = SLOT_OUTPUT))
return WorkerJobStatus() return Status.FAILURE_ITEM
if (!container.fullyAddItem(result, start = SLOT_OUTPUT, end = SLOT_OUTPUT)) { return Status.SUCCESS
return WorkerJobStatus(false, 20)
} }
return WorkerJobStatus() override fun computeNextJob(): Pair<ItemJob?, IdleReason?> {
if (energy.batteryLevel.isZero) {
return null to IdleReason.POWER
} }
override fun computeNextJob(): WorkerJob? { val recipe = level?.recipeManager?.getRecipeFor(MRecipes.PLATE_PRESS, container, level!!)?.orElse(null) ?: return null to IdleReason.ITEM
val level = level ?: return null
val recipe = level.recipeManager.getRecipeFor(MRecipes.PLATE_PRESS, container, level).orElse(null) ?: return null
val copy = container[SLOT_INPUT].copy()
container[SLOT_INPUT].shrink(1) container[SLOT_INPUT].shrink(1)
container.setChanged(SLOT_INPUT) return ItemJob(recipe.resultItem, recipe.workTime.toDouble(), BASELINE_CONSUMPTION) to null
copy.count = 1
return WorkerJob(copy, recipe.workTime.toDouble(), BASELINE_CONSUMPTION, CompoundTag().also {
it["result"] = recipe.resultItem.serializeNBT()
})
} }
companion object { companion object {

View File

@ -1,7 +1,7 @@
package ru.dbotthepony.mc.otm.block.entity package ru.dbotthepony.mc.otm.block.entity
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
enum class RedstoneSetting(val label: Component, val description: Component) { enum class RedstoneSetting(val label: Component, val description: Component) {
IGNORED(TranslatableComponent("otm.gui.redstone.ignored"), TranslatableComponent("otm.gui.redstone.ignored.description")), IGNORED(TranslatableComponent("otm.gui.redstone.ignored"), TranslatableComponent("otm.gui.redstone.ignored.description")),

View File

@ -0,0 +1,21 @@
package ru.dbotthepony.mc.otm.block.entity
import net.minecraft.util.StringRepresentable
import net.minecraft.world.level.block.state.properties.EnumProperty
enum class WorkerState : StringRepresentable {
IDLE,
WORKING,
ERROR;
companion object {
@JvmField
val WORKER_STATE: EnumProperty<WorkerState> = EnumProperty.create("worker", WorkerState::class.java)
@JvmField
val SEMI_WORKER_STATE: EnumProperty<WorkerState> = EnumProperty.create("worker", WorkerState::class.java, IDLE, WORKING)
}
override fun getSerializedName(): String {
return if (this == IDLE) "idle" else if (this == WORKING) "working" else "error"
}
}

View File

@ -31,7 +31,8 @@ import ru.dbotthepony.mc.otm.matter.getMatterValue
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
import kotlin.math.roundToInt import kotlin.math.roundToInt
import kotlin.math.sqrt import kotlin.math.sqrt

View File

@ -23,7 +23,6 @@ import ru.dbotthepony.mc.otm.block.BlockExplosionDebugger
import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.Vector import ru.dbotthepony.mc.otm.core.Vector
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
import ru.dbotthepony.mc.otm.set
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.collections.HashMap import kotlin.collections.HashMap

View File

@ -15,25 +15,22 @@ import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.CapabilityItemHandler import net.minecraftforge.items.CapabilityItemHandler
import ru.dbotthepony.mc.otm.TranslatableComponent
import ru.dbotthepony.mc.otm.block.matter.MatterBottlerBlock import ru.dbotthepony.mc.otm.block.matter.MatterBottlerBlock
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
import ru.dbotthepony.mc.otm.capability.matter.MatterDirection import ru.dbotthepony.mc.otm.capability.matter.MatterDirection
import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerImpl import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerImpl
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.menu.MatterBottlerMenu import ru.dbotthepony.mc.otm.menu.MatterBottlerMenu
import ru.dbotthepony.mc.otm.orNull
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.*
class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryPoweredBlockEntity(MBlockEntities.MATTER_BOTTLER, p_155229_, p_155230_), IMatterGraphNode { MatteryPoweredBlockEntity(MBlockEntities.MATTER_BOTTLER, p_155229_, p_155230_), IMatterGraphNode {

View File

@ -15,7 +15,7 @@ import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.BatteryBankBlock import ru.dbotthepony.mc.otm.block.BatteryBankBlock
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
@ -28,7 +28,8 @@ import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.menu.MatterCapacitorBankMenu import ru.dbotthepony.mc.otm.menu.MatterCapacitorBankMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
import javax.annotation.ParametersAreNonnullByDefault import javax.annotation.ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault @MethodsReturnNonnullByDefault

View File

@ -12,24 +12,22 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.CapabilityItemHandler
import net.minecraftforge.items.IItemHandler import net.minecraftforge.items.IItemHandler
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJob
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJobStatus
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
import ru.dbotthepony.mc.otm.capability.matter.MatterDirection import ru.dbotthepony.mc.otm.capability.matter.MatterDirection
import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerImpl import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerImpl
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.container.MatteryContainerFilter
import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.item.MatterDustItem import ru.dbotthepony.mc.otm.item.MatterDustItem
import ru.dbotthepony.mc.otm.matter.baselineComplexityDecomposeTicks import ru.dbotthepony.mc.otm.matter.baselineComplexityDecomposeTicks
import ru.dbotthepony.mc.otm.matter.canDecompose import ru.dbotthepony.mc.otm.matter.canDecompose
@ -37,7 +35,6 @@ import ru.dbotthepony.mc.otm.matter.getMatterValue
import ru.dbotthepony.mc.otm.menu.MatterDecomposerMenu import ru.dbotthepony.mc.otm.menu.MatterDecomposerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.set
fun moveMatterAsDustIntoContainer(_matterValue: ImpreciseFraction, container: MatteryContainer, OUTPUT_DUST_MAIN: Int, OUTPUT_DUST_STACKING: Int): ImpreciseFraction { fun moveMatterAsDustIntoContainer(_matterValue: ImpreciseFraction, container: MatteryContainer, OUTPUT_DUST_MAIN: Int, OUTPUT_DUST_STACKING: Int): ImpreciseFraction {
var matterValue = _matterValue var matterValue = _matterValue
@ -93,7 +90,29 @@ fun moveMatterAsDustIntoContainer(_matterValue: ImpreciseFraction, container: Ma
} }
class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState) class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
: MatteryWorkerBlockEntity(MBlockEntities.MATTER_DECOMPOSER, pos, state), IMatterGraphNode { : MatteryWorkerBlockEntity<MatterDecomposerBlockEntity.DecomposerJob>(MBlockEntities.MATTER_DECOMPOSER, pos, state, ::DecomposerJob), IMatterGraphNode {
class DecomposerJob : Job {
val toDust: Boolean
var matterValue: ImpreciseFraction
constructor(tag: CompoundTag) : super(tag) {
toDust = tag.getBoolean("to_dust")
matterValue = tag.getImpreciseFraction("value")
}
constructor(toDust: Boolean, matterValue: ImpreciseFraction, ticks: Double) : super(ticks, BASE_CONSUMPTION) {
this.toDust = toDust
this.matterValue = matterValue
}
override fun serializeNBT(): CompoundTag {
return super.serializeNBT().also {
it["to_dust"] = toDust
it["value"] = matterValue
}
}
}
override val energy = WorkerEnergyStorage(this, ENERGY_STORAGE, MAX_IO) override val energy = WorkerEnergyStorage(this, ENERGY_STORAGE, MAX_IO)
private var valid = true private var valid = true
@ -110,13 +129,18 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
private var resolverNode = LazyOptional.of { this } private var resolverNode = LazyOptional.of { this }
// вход, выход // вход, выход
@JvmField
val container = MatteryContainer(this::setChangedLight, 3) val container = MatteryContainer(this::setChangedLight, 3)
private val itemHandler = LazyOptional.of<IItemHandler> { private val itemHandler = LazyOptional.of<IItemHandler> {
container.handler( container.handler(object : MatteryContainerFilter {
{ slot: Int, stack: ItemStack -> slot == INPUT_SLOT && canDecompose(stack) }, override fun canInsert(slot: Int, stack: ItemStack): Boolean {
{ slot: Int, _: Int, _: ItemStack -> slot != INPUT_SLOT }) return slot == INPUT_SLOT && canDecompose(stack)
}
override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean {
return slot != INPUT_SLOT
}
})
} }
override val defaultDisplayName: Component override val defaultDisplayName: Component
@ -156,39 +180,35 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> { override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid) { if (valid) {
if (cap === MatteryCapability.MATTER) return resolverMatter.cast() if (cap == MatteryCapability.MATTER) return resolverMatter.cast()
if (cap === MatteryCapability.MATTER_NODE) return resolverNode.cast() if (cap == MatteryCapability.MATTER_NODE) return resolverNode.cast()
if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return itemHandler.cast() if (cap == ForgeCapabilities.ITEM_HANDLER) return itemHandler.cast()
} }
return super.getCapability(cap, side) return super.getCapability(cap, side)
} }
override fun onJobFinish(job: WorkerJob): WorkerJobStatus { override fun onJobFinish(job: DecomposerJob): Status {
var matterValue = ImpreciseFraction.deserializeNBT(job.data["value"]) if (job.toDust) {
job.matterValue = moveMatterAsDustIntoContainer(job.matterValue, container, OUTPUT_DUST_MAIN, OUTPUT_DUST_STACKING)
if (job.data.getBoolean("to_dust")) { if (!job.matterValue.isZero) {
matterValue = moveMatterAsDustIntoContainer(matterValue, container, OUTPUT_DUST_MAIN, OUTPUT_DUST_STACKING) return Status.FAILURE_WAIT_FAST
if (!matterValue.isZero) {
job.data["value"] = matterValue.serializeNBT()
return WorkerJobStatus(20)
} }
return WorkerJobStatus() return Status.SUCCESS
} }
matterValue -= matter.receiveMatterInner(matterValue, false) job.matterValue -= matter.receiveMatterInner(job.matterValue, false)
if (matterValue.isPositive) { if (job.matterValue.isPositive) {
job.data["value"] = matterValue.serializeNBT() return Status.FAILURE_MATTER
return WorkerJobStatus(false, 20)
} }
return WorkerJobStatus() return Status.SUCCESS
} }
override fun computeNextJob(): WorkerJob? { override fun computeNextJob(): Pair<DecomposerJob?, IdleReason?> {
val stack = container[INPUT_SLOT] val stack = container[INPUT_SLOT]
if (!stack.isEmpty) { if (!stack.isEmpty) {
@ -197,19 +217,13 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
if (canDecompose(copy)) { if (canDecompose(copy)) {
val matter = getMatterValue(copy) val matter = getMatterValue(copy)
if (!matter.isZero) {
stack.count-- stack.count--
return WorkerJob(copy, matter.complexity * baselineComplexityDecomposeTicks, BASE_CONSUMPTION, CompoundTag().also { return DecomposerJob((level?.random?.nextDouble() ?: 1.0) <= 0.2, matter.value, matter.complexity * baselineComplexityDecomposeTicks) to null
it["to_dust"] = (level?.random?.nextDouble() ?: 1.0) <= 0.2
it["value"] = matter.value.serializeNBT()
})
}
} }
} }
return null return null to IdleReason.ITEM
} }
override fun setRemoved() { override fun setRemoved() {

View File

@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.block.entity.matter
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.core.Direction import net.minecraft.core.Direction
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.capability.matter.IMatterTaskProvider
import ru.dbotthepony.mc.otm.menu.MatterPanelMenu import ru.dbotthepony.mc.otm.menu.MatterPanelMenu
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player
@ -12,10 +11,6 @@ import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import java.util.HashMap import java.util.HashMap
import java.util.UUID import java.util.UUID
import ru.dbotthepony.mc.otm.capability.matter.MatterTask
import java.util.stream.Collectors
import ru.dbotthepony.mc.otm.capability.matter.MatterTaskAllocation
import ru.dbotthepony.mc.otm.capability.matter.PatternState
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag import net.minecraft.nbt.ListTag
import net.minecraft.nbt.Tag import net.minecraft.nbt.Tag
@ -23,17 +18,18 @@ import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerLevel
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.capability.matter.*
import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import java.util.ArrayList import java.util.ArrayList
import java.util.List import java.util.stream.Stream
class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryBlockEntity(MBlockEntities.MATTER_PANEL, p_155229_, p_155230_), IMatterGraphNode, IMatterTaskProvider { MatteryBlockEntity(MBlockEntities.MATTER_PANEL, p_155229_, p_155230_), IMatterGraphNode, IReplicationTaskProvider {
private val listeners = ArrayList<MatterPanelMenu>() private val listeners = ArrayList<MatterPanelMenu>()
override val matterNode = Graph6Node<IMatterGraphNode>(this) override val matterNode = Graph6Node<IMatterGraphNode>(this)
@ -88,61 +84,59 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
matterNode.destroy(::MatterNetworkGraph) matterNode.destroy(::MatterNetworkGraph)
} }
override fun getTaskHandler(): IMatterTaskProvider? { override fun getTaskHandler(): IReplicationTaskProvider {
return this return this
} }
private val _tasks = HashMap<UUID, MatterTask>() private val _tasks = HashMap<UUID, ReplicationTask>()
override val tasks: Collection<MatterTask> get() { override val replicationTasks: Stream<ReplicationTask> get() {
return _tasks.values.stream().filter { task: MatterTask? -> task!!.required() > 0 }.collect(Collectors.toList()) as Collection<MatterTask> return _tasks.values.stream().filter { it.required > 0 }
} }
override val allTasks: Collection<MatterTask> get() { override val allReplicationTasks: Stream<ReplicationTask> get() {
return List.copyOf(_tasks.values) as Collection<MatterTask> return _tasks.values.stream()
} }
override fun allocateTask(simulate: Boolean): MatterTaskAllocation? { override fun allocateTask(simulate: Boolean): ReplicationTaskAllocation? {
val graph = matterNode.graph as MatterNetworkGraph? ?: return null val graph = matterNode.graph as MatterNetworkGraph? ?: return null
for ((key, task) in _tasks) { for ((key, task) in _tasks) {
if (task.required > 0) { if (task.required > 0) {
val getPattern = graph.getPattern(task.pattern!!) val pattern = task.patternId?.let(graph::getPattern) ?: continue
if (getPattern != null) {
if (!simulate) { if (!simulate) {
val new = task.shrinkRequired(1) val new = task.allocate()
_tasks[key] = new _tasks[key] = new
listeners.forEach { menu: MatterPanelMenu -> menu.taskUpdated(new) } listeners.forEach { it.taskUpdated(new) }
graph.onMatterTaskUpdated(new, task) graph.onMatterTaskUpdated(new, task)
setChanged() setChanged()
} }
return MatterTaskAllocation(task, getPattern) return ReplicationTaskAllocation(task, pattern)
}
} }
} }
return null return null
} }
override fun notifyTaskCompletion(task: MatterTask): Boolean { override fun notifyTaskCompletion(taskId: UUID): Boolean {
var localTask = _tasks[task.id] ?: return false var localTask = _tasks[taskId] ?: return false
val oldTask = localTask val oldTask = localTask
localTask = localTask.shrinkInProgress(1) localTask = localTask.finish()
val graph = matterNode.graph as MatterNetworkGraph? val graph = matterNode.graph as MatterNetworkGraph?
// Задача полностью выполнена // Задача полностью выполнена
if (localTask.required <= 0 && localTask.in_progress <= 0) { if (localTask.required <= 0 && localTask.inProgress <= 0) {
_tasks.remove(task.id) _tasks.remove(taskId)
graph?.onMatterTaskCreated(task) graph?.onMatterTaskFinished(localTask)
listeners.forEach { menu: MatterPanelMenu -> menu.taskRemoved(localTask) } listeners.forEach { it.taskRemoved(localTask) }
} else { } else {
// Задача обновлена // Задача обновлена
_tasks[task.id()] = localTask _tasks[taskId] = localTask
graph?.onMatterTaskUpdated(localTask, oldTask) graph?.onMatterTaskUpdated(localTask, oldTask)
listeners.forEach { menu: MatterPanelMenu -> menu.taskUpdated(localTask) } listeners.forEach { it.taskUpdated(localTask) }
} }
setChanged() setChanged()
@ -155,7 +149,7 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
val list = ListTag() val list = ListTag()
for (task in _tasks.values) { for (task in _tasks.values) {
list.add(task!!.serializeNBT()) list.add(task.serializeNBT())
} }
nbt.put("tasks", list) nbt.put("tasks", list)
@ -167,16 +161,16 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
val list = nbt.getList("tasks", Tag.TAG_COMPOUND.toInt()) val list = nbt.getList("tasks", Tag.TAG_COMPOUND.toInt())
for (tag in list) { for (tag in list) {
val task = MatterTask.deserializeNBT(tag) val task = ReplicationTask.deserializeNBT(tag)
if (task != null) { if (task != null) {
_tasks[task.id()] = task _tasks[task.id] = task
} }
} }
} }
override fun getTask(id: UUID): MatterTask? { override fun getTask(id: UUID): ReplicationTask? {
return _tasks[id] return _tasks[id]?.asImmutable()
} }
fun removeTask(id: UUID) { fun removeTask(id: UUID) {
@ -185,19 +179,17 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
(matterNode.graph as MatterNetworkGraph?)?.onMatterTaskRemoved(task) (matterNode.graph as MatterNetworkGraph?)?.onMatterTaskRemoved(task)
listeners.forEach { menu: MatterPanelMenu -> menu.taskRemoved(task) } listeners.forEach { it.taskRemoved(task) }
setChanged() setChanged()
} }
fun removeTask(state: PatternState) = removeTask(state.id) fun addTask(state: IPatternState, count: Int): IReplicationTask<*> {
val task = ReplicationTask(UUID.randomUUID(), state.id, state.item, 0, 0, count)
fun addTask(state: PatternState, how_much: Int): MatterTask { _tasks[task.id] = task
val task = MatterTask(UUID.randomUUID(), state.id, state.item, 0, 0, how_much)
_tasks[task.id()] = task
(matterNode.graph as MatterNetworkGraph?)?.onMatterTaskCreated(task) (matterNode.graph as MatterNetworkGraph?)?.onMatterTaskCreated(task)
listeners.forEach { menu: MatterPanelMenu -> menu.taskUpdated(task) } listeners.forEach { it.taskUpdated(task) }
setChanged() setChanged()
return task return task

View File

@ -12,13 +12,10 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.CapabilityItemHandler import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJob
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJobStatus
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerTickContext
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
@ -30,26 +27,27 @@ import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.item.MatterDustItem import ru.dbotthepony.mc.otm.item.MatterDustItem
import ru.dbotthepony.mc.otm.core.map
import ru.dbotthepony.mc.otm.menu.MatterRecyclerMenu import ru.dbotthepony.mc.otm.menu.MatterRecyclerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState) class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
: MatteryWorkerBlockEntity(MBlockEntities.MATTER_RECYCLER, blockPos, blockState), IMatterGraphNode { : MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.Job>(MBlockEntities.MATTER_RECYCLER, blockPos, blockState, ::Job), IMatterGraphNode {
val matter = MatterHandlerImpl( val matter = MatterHandlerImpl(
this::setChangedLight, this::matterLevelUpdated,
MatterDirection.EXTRACT, MatterDirection.EXTRACT,
STORAGE STORAGE
) )
val container = MatteryContainer(this::setChangedLight, 1) val container = MatteryContainer(this::itemContainerUpdated, 1)
override val matterNode = Graph6Node<IMatterGraphNode>(this) override val matterNode = Graph6Node<IMatterGraphNode>(this)
private var resolverNode = LazyOptional.of { this } private var resolverNode = LazyOptional.of { this }
private var valid = true private var valid = true
override val energy = WorkerEnergyStorage(this, MAX_POWER) override val energy = WorkerEnergyStorage(this::powerLevelUpdated, MAX_POWER)
override fun getMatterHandler(): IMatterHandler { override fun getMatterHandler(): IMatterHandler {
return matter return matter
@ -99,7 +97,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
override fun load(nbt: CompoundTag) { override fun load(nbt: CompoundTag) {
super.load(nbt) super.load(nbt)
nbt.ifHas("matter", CompoundTag::class.java, matter::deserializeNBT) nbt.map("matter", matter::deserializeNBT)
container.deserializeNBT(nbt["container"]) container.deserializeNBT(nbt["container"])
} }
@ -107,15 +105,12 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
if (!valid) if (!valid)
return super.getCapability(cap, side) return super.getCapability(cap, side)
if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { return when (cap) {
return itemHandler.get().cast() ForgeCapabilities.ITEM_HANDLER -> itemHandler.get().cast()
} else if (cap === MatteryCapability.MATTER) { MatteryCapability.MATTER -> matter.get().cast()
return matter.get().cast() MatteryCapability.MATTER_NODE -> resolverNode.cast()
} else if (cap === MatteryCapability.MATTER_NODE) { else -> super.getCapability(cap, side)
return resolverNode.cast()
} }
return super.getCapability(cap, side)
} }
override val defaultDisplayName: Component override val defaultDisplayName: Component
@ -125,41 +120,39 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
return MatterRecyclerMenu(containerID, inventory, this) return MatterRecyclerMenu(containerID, inventory, this)
} }
override fun onJobFinish(job: WorkerJob): WorkerJobStatus { override fun onJobFinish(job: Job): Status {
// вся логика в onWorkTick // вся логика в onWorkTick
return WorkerJobStatus() return Status.SUCCESS
} }
override fun computeNextJob(): WorkerJob? { override fun computeNextJob(): Pair<Job?, IdleReason?> {
if (matter.missingMatter.isZero) if (matter.missingMatter.isZero)
return null return null to IdleReason.ITEM
val stack = container[0] val stack = container[0]
if (stack.isEmpty || stack.item !is MatterDustItem) { if (stack.isEmpty || stack.item !is MatterDustItem) {
return null return null to IdleReason.ITEM
} }
val copy = stack.copy() val dustMatter = (stack.item as MatterDustItem).getMatterValue(stack.copy().also { it.count = 1 }) ?: return null to IdleReason.ITEM
copy.count = 1
val dustMatter = (stack.item as MatterDustItem).getMatterValue(copy) ?: return null
stack.shrink(1) stack.shrink(1)
return WorkerJob(copy, dustMatter.value.toDouble() * MATTER_TICKS, POWER_CONSUMPTION) container.setChanged(0)
return Job(dustMatter.value.toDouble() * MATTER_TICKS, POWER_CONSUMPTION) to null
} }
override fun onWorkTick(context: WorkerTickContext): WorkerJobStatus { override fun onWorkTick(requiredPower: ImpreciseFraction, extractedPower: ImpreciseFraction, ticksAdvanced: Double): Status {
if ((level?.random?.nextDouble() ?: 1.0) <= 0.4) if ((level?.random?.nextDouble() ?: 1.0) <= 0.4)
return WorkerJobStatus() return Status.SUCCESS
val receive = if (context.ticksAdvanced == 1.0) MATTER_PER_TICK else MATTER_PER_TICK * context.ticksAdvanced val receive = MATTER_PER_TICK * ticksAdvanced
val received = matter.receiveMatterInner(receive, true) val received = matter.receiveMatterInner(receive, true)
if (receive != received) if (receive != received)
return WorkerJobStatus(false, 20) return Status.FAILURE_MATTER
matter.receiveMatterInner(receive, false) matter.receiveMatterInner(receive, false)
return WorkerJobStatus() return Status.SUCCESS
} }
fun tick() { fun tick() {

View File

@ -8,49 +8,93 @@ import net.minecraft.server.level.ServerLevel
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.CapabilityItemHandler import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.worker.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJob
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJobStatus
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerTickContext
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.* import ru.dbotthepony.mc.otm.capability.matter.*
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.MatteryContainerFilterOnlyOut import ru.dbotthepony.mc.otm.container.MatteryContainerFilterOnlyOut
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.matter.baselineComplexityReplicateTicks import ru.dbotthepony.mc.otm.matter.baselineComplexityReplicateTicks
import ru.dbotthepony.mc.otm.matter.getMatterValue import ru.dbotthepony.mc.otm.matter.getMatterValue
import ru.dbotthepony.mc.otm.menu.MatterReplicatorMenu import ru.dbotthepony.mc.otm.menu.MatterReplicatorMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.*
class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryWorkerBlockEntity(MBlockEntities.MATTER_REPLICATOR, p_155229_, p_155230_), IMatterGraphNode { MatteryWorkerBlockEntity<MatterReplicatorBlockEntity.ReplicatorJob>(MBlockEntities.MATTER_REPLICATOR, p_155229_, p_155230_, {
try {
ReplicatorJob(it)
} catch(err: NoSuchElementException) {
null
}
}), IMatterGraphNode {
override val energy = WorkerEnergyStorage(this, STORAGE, MAX_IO) class ReplicatorJob : ItemJob {
val matterPerTick: ImpreciseFraction
val task: ReplicationTask
var matterValue: ImpreciseFraction
val pattern: PatternState?
val asDust: Boolean
constructor(tag: CompoundTag) : super(tag) {
matterPerTick = tag.getImpreciseFraction("matterPerTick")
matterValue = tag.getImpreciseFraction("matterValue")
pattern = tag.map("pattern", PatternState::deserializeNBT)
asDust = tag.getBoolean("asDust")
task = tag.map("task", ReplicationTask::deserializeNBT) ?: throw NoSuchElementException("Unable to deserialize matter task")
}
constructor(
itemStack: ItemStack,
matterPerTick: ImpreciseFraction,
task: ReplicationTask,
matterValue: ImpreciseFraction,
pattern: PatternState?,
asDust: Boolean,
ticks: Double,
) : super(itemStack, ticks, BASE_CONSUMPTION) {
this.matterPerTick = matterPerTick
this.task = task
this.matterValue = matterValue
this.pattern = pattern
this.asDust = asDust
}
override fun serializeNBT(): CompoundTag {
return super.serializeNBT().also {
it["matterPerTick"] = this.matterPerTick
it["task"] = this.task.serializeNBT()
it["matterValue"] = this.matterValue
if (this.pattern != null)
it["pattern"] = this.pattern.serializeNBT()
it["asDust"] = this.asDust
}
}
}
override val energy = WorkerEnergyStorage(this::powerLevelUpdated, STORAGE, MAX_IO)
override val matterNode = Graph6Node<IMatterGraphNode>(this) override val matterNode = Graph6Node<IMatterGraphNode>(this)
private val resolverNode = LazyOptional.of { this } private val resolverNode = LazyOptional.of { this }
@JvmField
val matter = MatterHandlerImpl( val matter = MatterHandlerImpl(
this::setChangedLight, this::matterLevelUpdated,
MatterDirection.RECEIVE, MatterDirection.RECEIVE,
ImpreciseFraction(2) ImpreciseFraction(2)
) )
// обычные запросы val container = MatteryContainer(this::itemContainerUpdated, 5)
@JvmField
val container = MatteryContainer(this::setChangedLight, 5)
private val itemHandler = container.handler(MatteryContainerFilterOnlyOut) private val itemHandler = container.handler(MatteryContainerFilterOnlyOut)
override val defaultDisplayName: Component override val defaultDisplayName: Component
@ -60,39 +104,43 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
return MatterReplicatorMenu(containerID, inventory, this) return MatterReplicatorMenu(containerID, inventory, this)
} }
override fun onJobFinish(job: WorkerJob): WorkerJobStatus { override fun onJobFinish(job: ReplicatorJob): Status {
if (job.data.getBoolean("as_dust")) { if (job.asDust) {
val matterValue = moveMatterAsDustIntoContainer(ImpreciseFraction.deserializeNBT(job["matter"]), container, OUTPUT_DUST_MAIN, OUTPUT_DUST_STACKING) job.matterValue = moveMatterAsDustIntoContainer(job.matterValue, container, OUTPUT_DUST_MAIN, OUTPUT_DUST_STACKING)
if (!matterValue.isZero) { if (!job.matterValue.isZero) {
job["matter"] = matterValue.serializeNBT() return Status.FAILURE_WAIT
return WorkerJobStatus(false, 20)
} }
(matterNode.graph as MatterNetworkGraph?)?.notifyTaskCompletion(MatterTask.deserializeNBT(job["task"])!!) (matterNode.graph as MatterNetworkGraph?)?.notifyTaskCompletion(job.task.id)
return Status.SUCCESS
return WorkerJobStatus()
} }
if (!container.fullyAddItem(job.stack, FIRST_ACTUAL_OUTPUT_SLOT .. LAST_ACTUAL_OUTPUT_SLOT)) { if (!container.fullyAddItem(job.itemStack, FIRST_ACTUAL_OUTPUT_SLOT .. LAST_ACTUAL_OUTPUT_SLOT)) {
return WorkerJobStatus(false, 20) return Status.FAILURE_ITEM
} }
(matterNode.graph as MatterNetworkGraph?)?.notifyTaskCompletion(MatterTask.deserializeNBT(job["task"])!!) (matterNode.graph as MatterNetworkGraph?)?.notifyTaskCompletion(job.task.id)
return WorkerJobStatus() return Status.SUCCESS
} }
override fun onMatterTaskCreated(task: MatterTask) { override fun onMatterTaskCreated(task: IReplicationTask<*>) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false isIdling = false
} }
override fun onMatterTaskUpdated(new_state: MatterTask, old_state: MatterTask) {
isIdling = false
} }
override fun onPatternAdded(state: PatternState) { override fun <T : IReplicationTask<*>> onMatterTaskUpdated(newState: T, oldState: T) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false isIdling = false
} }
}
override fun onPatternAdded(state: IPatternState) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false
}
}
override fun setRemoved() { override fun setRemoved() {
super.setRemoved() super.setRemoved()
@ -106,33 +154,35 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatterNetworkGraph.discoverFull(this, matterNode) MatterNetworkGraph.discoverFull(this, matterNode)
} }
override fun computeNextJob(): WorkerJob? { override fun computeNextJob(): Pair<ReplicatorJob?, IdleReason?> {
val graph = matterNode.graph as MatterNetworkGraph? ?: return null if (energy.batteryLevel < BASE_CONSUMPTION) {
val allocation = graph.allocateTask(false) ?: return null return null to IdleReason.POWER
}
val graph = matterNode.graph as MatterNetworkGraph? ?: return null to null
val allocation = graph.allocateTask(simulate = false) ?: return null to IdleReason.OBSERVING
val stack = allocation.task.stack(1) val stack = allocation.task.stack(1)
val matter = getMatterValue(stack) val matter = getMatterValue(stack)
// ???????? // ????????
if (matter.isZero) return null if (matter.isZero) return null to null
val ticks = matter.complexity * baselineComplexityReplicateTicks val ticks = matter.complexity * baselineComplexityReplicateTicks
return WorkerJob(stack, ticks, BASE_CONSUMPTION, CompoundTag().also { return ReplicatorJob(
it["matter_per_tick"] = (matter.value / ticks).serializeNBT() itemStack = stack,
it["task"] = allocation.task.serializeNBT() matterPerTick = matter.value / ticks,
it["matter"] = matter.value.serializeNBT() task = allocation.task.asImmutable(),
matterValue = matter.value,
if (allocation.pattern != null) pattern = allocation.pattern?.asImmutable(),
it["pattern"] = allocation.pattern.serializeNBT() asDust = (level?.random?.nextDouble() ?: 1.0) > (allocation.pattern?.researchPercent ?: 2.0),
ticks = ticks,
if ((level?.random?.nextDouble() ?: 1.0) > (allocation.pattern?.research ?: 2.0)) ) to null
it["as_dust"] = true
})
} }
override fun onWorkTick(context: WorkerTickContext): WorkerJobStatus { override fun onWorkTick(requiredPower: ImpreciseFraction, extractedPower: ImpreciseFraction, ticksAdvanced: Double): Status {
val drainPerTick = ImpreciseFraction.deserializeNBT(context.job.data["matter_per_tick"]) val drainPerTick = currentJob!!.matterPerTick * ticksAdvanced
val graph = matterNode.graph as MatterNetworkGraph? ?: return WorkerJobStatus(false, 20) val graph = matterNode.graph as MatterNetworkGraph? ?: return Status.FAILURE_WAIT_FAST
if (matter.extractMatterInner(drainPerTick, true) < drainPerTick) { if (matter.extractMatterInner(drainPerTick, true) < drainPerTick) {
// в машине недостаточно материи // в машине недостаточно материи
@ -142,44 +192,42 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
val toExtract = drainPerTick - matter.extractMatterInner(drainPerTick, true) val toExtract = drainPerTick - matter.extractMatterInner(drainPerTick, true)
val drain = graph.extractMatter(toExtract, true) val drain = graph.extractMatter(toExtract, true)
if (drain < toExtract) { if (drain != toExtract) {
// недостаточно материи в сети // недостаточно материи в сети
return WorkerJobStatus(false, 200) return Status.FAILURE_MATTER
} }
// достаточно материи в сети + внутри машины // достаточно материи в сети + внутри машины
matter.extractMatterInner(drainPerTick, false) matter.extractMatterInner(drainPerTick, false)
graph.extractMatter(drain, false) graph.extractMatter(drain, false)
return WorkerJobStatus() return Status.SUCCESS
} else { } else {
// в тик требуется меньше материи, чем её может хранить репликатор // в тик требуется меньше материи, чем её может хранить репликатор
// примем из сети недостающее количество бака материи, или 200 тиков репликации, что меньше // примем из сети недостающее количество бака материи, или 200 тиков репликации, что меньше
val toExtract = val drain = graph.extractMatter(matter.missingMatter.coerceAtMost(drainPerTick * DRAIN_MULT), true)
matter.missingMatter.coerceAtMost(drainPerTick.times(DRAIN_MULT))
val drain = graph.extractMatter(toExtract, true)
if (drain.isZero) { if (drain.isZero) {
// в сети нет материи // в сети нет материи
return WorkerJobStatus(false, 200) return Status.FAILURE_MATTER
} }
val received = matter.receiveMatterOuter(drain, false) val received = matter.receiveMatterOuter(drain, false)
graph.extractMatter(received, false) graph.extractMatter(received, false)
// получили материю, проверяем возможность работы // получили материю, проверяем возможность работы
if (matter.extractMatterInner(drainPerTick, false) >= drainPerTick) { if (matter.extractMatterInner(drainPerTick, true) >= drainPerTick) {
return WorkerJobStatus() matter.extractMatterInner(drainPerTick, false)
return Status.SUCCESS
} else { } else {
// :( // :(
return WorkerJobStatus(false, 200) return Status.FAILURE_WAIT
} }
} }
} }
// в машине достаточно материи // в машине достаточно материи
matter.extractMatterInner(drainPerTick, false) matter.extractMatterInner(drainPerTick, false)
return WorkerJobStatus() return Status.SUCCESS
} }
override fun saveAdditional(nbt: CompoundTag) { override fun saveAdditional(nbt: CompoundTag) {
@ -191,10 +239,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override fun load(nbt: CompoundTag) { override fun load(nbt: CompoundTag) {
super.load(nbt) super.load(nbt)
container.deserializeNBT(nbt["container"]) container.deserializeNBT(nbt["container"])
nbt.map("matter", matter::deserializeNBT)
nbt.ifHas("matter", CompoundTag::class.java) {
matter.deserializeNBT(it)
}
} }
private var valid = true private var valid = true
@ -213,8 +258,8 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> { override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid) { if (valid) {
if (cap === MatteryCapability.MATTER_NODE) return resolverNode.cast() if (cap == MatteryCapability.MATTER_NODE) return resolverNode.cast()
if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return itemHandler.get().cast() if (cap == ForgeCapabilities.ITEM_HANDLER) return itemHandler.get().cast()
} }
return super.getCapability(cap, side) return super.getCapability(cap, side)

View File

@ -12,16 +12,16 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.CapabilityItemHandler import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJob
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerJobStatus
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IPatternState
import ru.dbotthepony.mc.otm.capability.matter.PatternState import ru.dbotthepony.mc.otm.capability.matter.PatternState
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.MatteryContainerFilter
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
@ -32,27 +32,39 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities
import java.util.* import java.util.*
class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryWorkerBlockEntity(MBlockEntities.MATTER_SCANNER, p_155229_, p_155230_), IMatterGraphNode { MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.ItemJob>(MBlockEntities.MATTER_SCANNER, p_155229_, p_155230_, ::ItemJob), IMatterGraphNode {
val container = MatteryContainer(this::setChanged, 1) val container = MatteryContainer(this::itemContainerUpdated, 1)
override val energy = WorkerEnergyStorage(this, STORAGE, MAX_IO) override val energy = WorkerEnergyStorage(this::powerLevelUpdated, STORAGE, MAX_IO)
private val itemHandler = container.handler(
{ _: Int, stack: ItemStack -> canDecompose(stack) }, private val itemHandler = container.handler(object : MatteryContainerFilter {
{ _: Int, _: Int, _: ItemStack -> isIdling } override fun canInsert(slot: Int, stack: ItemStack): Boolean {
) return canDecompose(stack)
}
override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean {
return isIdling
}
})
// IMatterGraphNode // IMatterGraphNode
override fun onPatternAdded(state: PatternState) { override fun onPatternAdded(state: IPatternState) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false isIdling = false
} }
override fun onPatternRemoved(state: PatternState) {
isIdling = false
} }
override fun onPatternUpdated(new_state: PatternState, old_state: PatternState) { override fun onPatternRemoved(state: IPatternState) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false isIdling = false
} }
}
override fun onPatternUpdated(newState: IPatternState, oldState: IPatternState) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false
}
}
// /IMatterGraphNode // /IMatterGraphNode
private var valid = true private var valid = true
@ -61,7 +73,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> { override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid) { if (valid) {
if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return itemHandler.get().cast() if (cap == ForgeCapabilities.ITEM_HANDLER) return itemHandler.get().cast()
if (cap == MatteryCapability.MATTER_NODE) return resolverNode.cast() if (cap == MatteryCapability.MATTER_NODE) return resolverNode.cast()
} }
@ -105,72 +117,71 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
super.load(nbt) super.load(nbt)
} }
override fun onJobFinish(job: WorkerJob): WorkerJobStatus { override fun onJobFinish(job: ItemJob): Status {
val grid = matterNode.graph as MatterNetworkGraph? ?: return WorkerJobStatus(false, 100) val grid = matterNode.graph as MatterNetworkGraph? ?: return Status.FAILURE_WAIT
val stack = job.stack val stack = job.itemStack
if (stack.isEmpty || !hasMatterValue(stack)) return WorkerJobStatus() if (stack.isEmpty || !hasMatterValue(stack)) return Status.SUCCESS
val getState = grid.findPatterns(stack.item) var findState: IPatternState? = null
var findState: PatternState? = null
for (state in getState) { for (state in grid.patterns.filter { it.item === stack.item }) {
if (state.item() === stack.item) { if (findState == null && state.researchPercent < 1.0) {
if (findState == null && state.research() < 1.0) {
findState = state findState = state
} else if (findState != null && findState.research() < state.research()) { } else if (findState != null && findState.researchPercent < state.researchPercent) {
findState = state findState = state
} }
} }
}
val new = val new =
if (findState != null) { if (findState != null) {
PatternState(findState.id(), stack.item, findState.research() + 0.2) PatternState(findState.id, stack.item, findState.researchPercent + 0.2)
} else { } else {
PatternState(UUID.randomUUID(), stack.item, 0.2) PatternState(UUID.randomUUID(), stack.item, 0.2)
} }
if (!grid.insertPattern(new, onlyUpdate = false, simulate = false).isFailed) { if (!grid.insertPattern(new, onlyUpdate = false, simulate = false).isFailed) {
return WorkerJobStatus() return Status.SUCCESS
} else { } else {
return WorkerJobStatus(false, 200) return Status.FAILURE_WAIT
} }
} }
override fun computeNextJob(): WorkerJob? { override fun computeNextJob(): Pair<ItemJob?, IdleReason?> {
val grid = matterNode.graph as MatterNetworkGraph? ?: return null if (energy.batteryLevel.isZero) {
return null to IdleReason.POWER
}
val grid = matterNode.graph as MatterNetworkGraph? ?: return null to null
val stack = container.getItem(0) val stack = container.getItem(0)
if (stack.isEmpty || !canDecompose(stack)) return null if (stack.isEmpty || !canDecompose(stack)) return null to IdleReason.ITEM
val getState = grid.findPatterns(stack.item) var findState: IPatternState? = null
var findState: PatternState? = null
for (state in getState) { for (state in grid.patterns.filter { it.item === stack.item }) {
if (state.item === stack.item && state.research < 1.0) { if (state.researchPercent < 1.0) {
findState = state findState = state
} else if (state.item === stack.item && state.research >= 1.0) { } else if (state.researchPercent >= 1.0) {
return null return null to IdleReason.ITEM
} }
} }
val new: PatternState = val new: IPatternState =
if (findState != null) { if (findState != null) {
PatternState(findState.id, stack.item, findState.research + 0.2) PatternState(findState.id, stack.item, findState.researchPercent + 0.2)
} else { } else {
PatternState(UUID.randomUUID(), stack.item, 0.2) PatternState(UUID.randomUUID(), stack.item, 0.2)
} }
if (!grid.insertPattern(new, onlyUpdate = false, simulate = true).isFailed) { if (!grid.insertPattern(new, onlyUpdate = false, simulate = true).isFailed) {
val copy = stack.copy() val copy = stack.copy().also { it.count = 1 }
copy.count = 1
stack.shrink(1) stack.shrink(1)
container.setChanged() container.setChanged()
return WorkerJob(copy, getMatterValue(copy).complexity * baselineComplexityScanTicks, BASE_CONSUMPTION) return ItemJob(copy, getMatterValue(copy).complexity * baselineComplexityScanTicks, BASE_CONSUMPTION) to null
} }
return null return null to IdleReason.ITEM
} }
override fun setLevel(p_155231_: Level) { override fun setLevel(p_155231_: Level) {

View File

@ -13,16 +13,17 @@ import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.ifHas import ru.dbotthepony.mc.otm.core.ifHas
import ru.dbotthepony.mc.otm.menu.DriveRackMenu import ru.dbotthepony.mc.otm.menu.DriveRackMenu
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.storage.* import ru.dbotthepony.mc.otm.storage.*

View File

@ -11,16 +11,17 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.block.storage.DriveViewerBlock import ru.dbotthepony.mc.otm.block.storage.DriveViewerBlock
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.menu.DriveViewerMenu import ru.dbotthepony.mc.otm.menu.DriveViewerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
import javax.annotation.ParametersAreNonnullByDefault import javax.annotation.ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault @MethodsReturnNonnullByDefault

View File

@ -26,26 +26,26 @@ import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.network.NetworkEvent import net.minecraftforge.network.NetworkEvent
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.get import ru.dbotthepony.mc.otm.container.get
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
import ru.dbotthepony.mc.otm.ifHas import ru.dbotthepony.mc.otm.core.ifHas
import ru.dbotthepony.mc.otm.menu.ItemMonitorMenu import ru.dbotthepony.mc.otm.menu.ItemMonitorMenu
import ru.dbotthepony.mc.otm.network.MatteryPacket import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.storage.* import ru.dbotthepony.mc.otm.storage.*
import java.math.BigInteger import java.math.BigInteger
import java.util.* import java.util.*
import java.util.function.Supplier import java.util.function.Supplier
import kotlin.collections.HashMap import kotlin.collections.HashMap
import kotlin.collections.HashSet
class ItemMonitorPlayerSettings : INBTSerializable<CompoundTag>, MatteryPacket { class ItemMonitorPlayerSettings : INBTSerializable<CompoundTag>, MatteryPacket {
enum class RefillSource(val component: Component) { enum class RefillSource(val component: Component) {
@ -296,6 +296,7 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override fun stillValid(p_18946_: Player) = true override fun stillValid(p_18946_: Player) = true
override fun getItem(p_18941_: Int): ItemStack { override fun getItem(p_18941_: Int): ItemStack {
require(p_18941_ == 1) { "Invalid slot ID: $p_18941_" }
return craftingRecipe?.resultItem?.copy() ?: ItemStack.EMPTY return craftingRecipe?.resultItem?.copy() ?: ItemStack.EMPTY
} }
@ -423,12 +424,13 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
} }
override fun removeItemNoUpdate(p_18951_: Int): ItemStack { override fun removeItemNoUpdate(p_18951_: Int): ItemStack {
// return removeItem(p_18951_, craftingRecipe?.resultItem?.count ?: Int.MAX_VALUE)
throw UnsupportedOperationException() throw UnsupportedOperationException()
} }
override fun setItem(p_18944_: Int, p_18945_: ItemStack) { override fun setItem(p_18944_: Int, p_18945_: ItemStack) {
throw UnsupportedOperationException() if ((craftingRecipe != null && !craftingRecipe!!.resultItem.isEmpty) || !p_18945_.isEmpty) {
throw RuntimeException("BUG-DETECT: Tried to set crafting result slot item to something, and either we have crafting recipe which have valid result, or we are trying to set slot to non empty item: $p_18945_")
}
} }
override fun setChanged() {} override fun setChanged() {}

View File

@ -25,10 +25,7 @@ import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.container.ItemFilter
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.isPositive
import ru.dbotthepony.mc.otm.core.isZero
import ru.dbotthepony.mc.otm.core.plus
import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.GraphNodeListener import ru.dbotthepony.mc.otm.graph.GraphNodeListener
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode

View File

@ -23,8 +23,7 @@ import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.capability.*
import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.container.ItemFilter
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.plus
import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.GraphNodeListener import ru.dbotthepony.mc.otm.graph.GraphNodeListener
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode

View File

@ -13,7 +13,7 @@ import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
@ -24,7 +24,8 @@ import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
import ru.dbotthepony.mc.otm.menu.StoragePowerSupplierMenu import ru.dbotthepony.mc.otm.menu.StoragePowerSupplierMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MNames import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.STORAGE_POWER_SUPPLIER, blockPos, blockState) { class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.STORAGE_POWER_SUPPLIER, blockPos, blockState) {
override val defaultDisplayName: Component override val defaultDisplayName: Component

View File

@ -1,261 +0,0 @@
package ru.dbotthepony.mc.otm.block.entity.worker
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.core.BlockPos
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.DoubleTag
import net.minecraft.world.level.block.Block
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.weakGreaterOrEqual
import ru.dbotthepony.mc.otm.core.weakLessThan
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.set
abstract class MatteryWorkerBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) :
MatteryPoweredBlockEntity(p_155228_, p_155229_, p_155230_) {
var workTicks = 0.0
protected set
var throttleTicks = 0
protected set
var currentJob: WorkerJob? = null
protected set
// если isIdling То ничего не делать
// isIdling должна быть выставлена в true если что то изменилось, что могло создать работу
var isIdling = false
protected set
val isUnableToProcess: Boolean get() = throttleTicks > 0
val workProgress: Float
get() {
val currentJob = currentJob ?: return 0.0f
return (workTicks / currentJob.ticks).coerceAtMost(1.0).toFloat()
}
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt["work_ticks"] = workTicks
currentJob?.let { nbt["current_job"] = it.serializeNBT() }
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.ifHas("work_ticks", DoubleTag::class.java) {
workTicks = it.asDouble
}
currentJob = WorkerJob.deserializeNBT(nbt["current_job"])
if (currentJob == null)
workTicks = 0.0
}
override fun setChanged() {
super.setChanged()
isIdling = false
}
override fun setChangedLight() {
super.setChangedLight()
isIdling = false
}
/**
* @param job current job
* @return whenever machine can finish it's job. return false if machine for whatever reason can't finish it's job,
* waiting on conditions to be met
*/
protected abstract fun onJobFinish(job: WorkerJob): WorkerJobStatus
/**
* @param context context for current job
* @return whenever machine can perform it
*/
protected open fun onWorkTick(context: WorkerTickContext): WorkerJobStatus {
return WorkerJobStatus()
}
private var idleTicksAnim = 0
private var workingTicksAnim = 0
private var errorTicksAnim = 0
override fun redstoneStatusUpdated(new_blocked: Boolean, old_blocked: Boolean) {
super.redstoneStatusUpdated(new_blocked, old_blocked)
isIdling = new_blocked
}
protected fun workerLoop() {
if (errorTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.ERROR) {
level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.ERROR), Block.UPDATE_CLIENTS)
}
if (throttleTicks > 0) {
workingTicksAnim = 0
idleTicksAnim = 0
throttleTicks--
errorTicksAnim++
if (throttleTicks > 0)
return
}
if (isIdling) {
workingTicksAnim = 0
errorTicksAnim = 0
idleTicksAnim++
if (idleTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.IDLE) {
level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS)
}
return
}
var currentJob = currentJob
if (currentJob == null) {
if (isBlockedByRedstone) {
isIdling = true
return
}
val input = computeNextJob()
if (input == null) {
isIdling = true
workingTicksAnim = 0
return
}
this.currentJob = input
currentJob = input
}
if (isBlockedByRedstone) {
isIdling = true
return
}
if (!currentJob.power.isZero && energy.batteryLevel.isZero) {
idleTicksAnim++
if (idleTicksAnim > 20 && blockState.hasProperty(WorkerState.WORKER_STATE) && blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.IDLE) {
level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS)
}
return
}
idleTicksAnim = 0
if (weakLessThan(workTicks, currentJob.ticks)) {
if (!currentJob.power.isZero) {
// сколько осталось тиков работать
val ticksLeft = currentJob.ticks - workTicks
val requiredPower: ImpreciseFraction
// запрос энергии на то количество, сколько действительно осталось работать
if (ticksLeft > 1.0) {
requiredPower = currentJob.power
} else {
requiredPower = currentJob.power * ticksLeft
}
val extractedPower = if (requiredPower.isZero) ImpreciseFraction.ZERO else energy.extractEnergyInner(requiredPower, true)
// сколько тиков мы "проработали"
// может быть меньше, чем единица, если недостаточно питания или мы завершаем работу,
// для которой осталось дробное количество тиков
val ticksAdvanced = (extractedPower / requiredPower).toDouble().coerceAtMost(ticksLeft)
val ticksAdvancedWeak = if (requiredPower.isZero) 1.0 else ticksAdvanced
val status = onWorkTick(WorkerTickContext(currentJob, requiredPower, extractedPower, ticksAdvanced))
if (!status.valid) {
throttleTicks += status.throttle
return
}
workingTicksAnim++
errorTicksAnim = 0
val updatedWorkTicks = (workTicks + ticksAdvancedWeak).coerceAtMost(currentJob.ticks)
if (weakGreaterOrEqual(updatedWorkTicks, currentJob.ticks)) {
workTicks = currentJob.ticks
energy.extractEnergyInner(extractedPower * (1.0 - (updatedWorkTicks - currentJob.ticks)), false)
val finish = onJobFinish(currentJob)
if (finish.valid) {
this.currentJob = null
workTicks = 0.0
} else {
throttleTicks += finish.throttle
}
} else {
workTicks = updatedWorkTicks
energy.extractEnergyInner(extractedPower, false)
}
} else {
val ticksLeft = (currentJob.ticks - workTicks).coerceAtMost(1.0)
val status = onWorkTick(WorkerTickContext(currentJob, ImpreciseFraction.ZERO, ImpreciseFraction.ZERO, ticksLeft))
if (!status.valid) {
throttleTicks += status.throttle
return
}
workingTicksAnim++
errorTicksAnim = 0
workTicks = (workTicks + 1.0).coerceAtMost(currentJob.ticks)
if (weakGreaterOrEqual(workTicks, currentJob.ticks)) {
val finish = onJobFinish(currentJob)
if (finish.valid) {
this.currentJob = null
workTicks = 0.0
} else {
throttleTicks += finish.throttle
}
}
}
} else {
val finish = onJobFinish(currentJob)
if (finish.valid) {
this.currentJob = null
workTicks = 0.0
errorTicksAnim = 0
} else {
throttleTicks += finish.throttle
errorTicksAnim++
}
}
if (workingTicksAnim > 20 &&
errorTicksAnim == 0 &&
blockState.hasProperty(WorkerState.WORKER_STATE) &&
blockState.getValue(WorkerState.WORKER_STATE) != WorkerState.WORKING)
{
level?.setBlock(blockPos, blockState.setValue(WorkerState.WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS)
}
}
/**
* Determine which item can be processed from input slots if idling
* @return any item in input slots. null if no work is available
*/
protected abstract fun computeNextJob(): WorkerJob?
fun basicTicker() {
batteryChargeLoop()
workerLoop()
}
}

View File

@ -1,85 +0,0 @@
package ru.dbotthepony.mc.otm.block.entity.worker
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.DoubleTag
import net.minecraft.nbt.Tag
import net.minecraft.util.StringRepresentable
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.state.properties.EnumProperty
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.set
@JvmRecord
data class WorkerTickContext(
val job: WorkerJob,
val requiredPower: ImpreciseFraction,
val extractedPower: ImpreciseFraction,
val ticksAdvanced: Double
)
enum class WorkerState : StringRepresentable {
IDLE,
WORKING,
ERROR;
companion object {
@JvmField
val WORKER_STATE: EnumProperty<WorkerState> = EnumProperty.create("worker", WorkerState::class.java)
@JvmField
val SEMI_WORKER_STATE: EnumProperty<WorkerState> = EnumProperty.create("worker", WorkerState::class.java, IDLE, WORKING)
}
override fun getSerializedName(): String {
return if (this == IDLE) "idle" else if (this == WORKING) "working" else "error"
}
}
@JvmRecord
data class WorkerJobStatus @JvmOverloads constructor(val valid: Boolean = true, val throttle: Int = 0) {
constructor(throttle: Int) : this(false, throttle)
}
@JvmRecord
data class WorkerJob @JvmOverloads constructor(
val stack: ItemStack,
val ticks: Double,
val power: ImpreciseFraction = ImpreciseFraction.ZERO,
val data: CompoundTag = CompoundTag()) {
fun serializeNBT(): CompoundTag {
return CompoundTag().also {
it["stack"] = stack.serializeNBT()
it["ticks"] = ticks
it["power"] = power.serializeNBT()
it["data"] = data
}
}
operator fun get(index: String) = data[index]
operator fun set(index: String, value: Tag) { data[index] = value }
operator fun set(index: String, value: Int) { data[index] = value }
operator fun set(index: String, value: Byte) { data[index] = value }
operator fun set(index: String, value: Short) { data[index] = value }
operator fun set(index: String, value: Long) { data[index] = value }
operator fun set(index: String, value: Float) { data[index] = value }
operator fun set(index: String, value: Double) { data[index] = value }
operator fun set(index: String, value: String) { data[index] = value }
operator fun set(index: String, value: Boolean) { data[index] = value }
operator fun set(index: String, value: ByteArray) { data[index] = value }
operator fun set(index: String, value: IntArray) { data[index] = value }
operator fun set(index: String, value: LongArray) { data[index] = value }
companion object {
@JvmStatic
fun deserializeNBT(tag: Tag?): WorkerJob? {
val nbt = tag as? CompoundTag ?: return null
return WorkerJob(
ItemStack.of(nbt["stack"] as? CompoundTag ?: return null),
(nbt["ticks"] as? DoubleTag ?: return null).asDouble,
ImpreciseFraction.deserializeNBT(nbt["power"]),
nbt["data"] as? CompoundTag ?: return null
)
}
}
}

View File

@ -19,7 +19,7 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty
import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.CollisionContext
import net.minecraft.world.phys.shapes.VoxelShape import net.minecraft.world.phys.shapes.VoxelShape
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.shapes.BlockShapes import ru.dbotthepony.mc.otm.shapes.BlockShapes

View File

@ -17,7 +17,7 @@ import net.minecraft.world.level.block.Block
import net.minecraft.world.phys.shapes.CollisionContext import net.minecraft.world.phys.shapes.CollisionContext
import net.minecraft.world.phys.shapes.VoxelShape import net.minecraft.world.phys.shapes.VoxelShape
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.shapes.BlockShapes import ru.dbotthepony.mc.otm.shapes.BlockShapes

View File

@ -15,7 +15,7 @@ import net.minecraft.world.phys.shapes.CollisionContext
import net.minecraft.world.phys.shapes.VoxelShape import net.minecraft.world.phys.shapes.VoxelShape
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.matter.MatterRecyclerBlockEntity import ru.dbotthepony.mc.otm.block.entity.matter.MatterRecyclerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.shapes.BlockShapes import ru.dbotthepony.mc.otm.shapes.BlockShapes

View File

@ -15,7 +15,7 @@ import net.minecraft.world.phys.shapes.CollisionContext
import net.minecraft.world.phys.shapes.VoxelShape import net.minecraft.world.phys.shapes.VoxelShape
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.matter.MatterReplicatorBlockEntity import ru.dbotthepony.mc.otm.block.entity.matter.MatterReplicatorBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.shapes.BlockShapes import ru.dbotthepony.mc.otm.shapes.BlockShapes

View File

@ -15,7 +15,7 @@ import net.minecraft.world.phys.shapes.CollisionContext
import net.minecraft.world.phys.shapes.VoxelShape import net.minecraft.world.phys.shapes.VoxelShape
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.matter.MatterScannerBlockEntity import ru.dbotthepony.mc.otm.block.entity.matter.MatterScannerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.shapes.BlockShapes import ru.dbotthepony.mc.otm.shapes.BlockShapes

View File

@ -17,7 +17,7 @@ import net.minecraft.world.phys.shapes.CollisionContext
import net.minecraft.world.phys.shapes.VoxelShape import net.minecraft.world.phys.shapes.VoxelShape
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.storage.DriveViewerBlockEntity import ru.dbotthepony.mc.otm.block.entity.storage.DriveViewerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.shapes.BlockShapes import ru.dbotthepony.mc.otm.shapes.BlockShapes

View File

@ -22,7 +22,7 @@ import ru.dbotthepony.mc.otm.block.StorageCableBlock
import ru.dbotthepony.mc.otm.block.entity.storage.StorageBusBlockEntity import ru.dbotthepony.mc.otm.block.entity.storage.StorageBusBlockEntity
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.shapes.BlockShapes import ru.dbotthepony.mc.otm.shapes.BlockShapes
import ru.dbotthepony.mc.otm.unaryMinus import ru.dbotthepony.mc.otm.core.unaryMinus
class StorageBusBlock : RotatableMatteryBlock(), EntityBlock { class StorageBusBlock : RotatableMatteryBlock(), EntityBlock {
override val hasFreeRotation: Boolean get() = true override val hasFreeRotation: Boolean get() = true

View File

@ -23,7 +23,7 @@ import ru.dbotthepony.mc.otm.block.entity.storage.StorageExporterBlockEntity
import ru.dbotthepony.mc.otm.block.entity.storage.StorageImporterBlockEntity import ru.dbotthepony.mc.otm.block.entity.storage.StorageImporterBlockEntity
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.shapes.BlockShapes import ru.dbotthepony.mc.otm.shapes.BlockShapes
import ru.dbotthepony.mc.otm.unaryMinus import ru.dbotthepony.mc.otm.core.unaryMinus
class StorageImporterBlock : RotatableMatteryBlock(), EntityBlock { class StorageImporterBlock : RotatableMatteryBlock(), EntityBlock {
override val hasFreeRotation: Boolean get() = true override val hasFreeRotation: Boolean get() = true

View File

@ -12,12 +12,12 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.capabilities.ICapabilityProvider import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.energy.CapabilityEnergy
import ru.dbotthepony.mc.otm.compat.mekanism.MatteryToMekanismEnergyWrapper import ru.dbotthepony.mc.otm.compat.mekanism.MatteryToMekanismEnergyWrapper
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.ifHas import ru.dbotthepony.mc.otm.core.ifHas
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.tagNotNull import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.core.tagNotNull
private enum class EnergyFlow { private enum class EnergyFlow {
INPUT, OUTPUT, BI_DIRECTIONAL INPUT, OUTPUT, BI_DIRECTIONAL
@ -47,9 +47,9 @@ sealed class ItemEnergyStorageImpl(
protected set protected set
override var batteryLevel: ImpreciseFraction override var batteryLevel: ImpreciseFraction
get() = itemStack.tag?.get("energy")?.let { ImpreciseFraction.deserializeNBT(it) } ?: ImpreciseFraction.ZERO get() = itemStack.tag?.get(NBT_KEY)?.let { ImpreciseFraction.deserializeNBT(it) } ?: ImpreciseFraction.ZERO
protected set(value) { protected set(value) {
itemStack.tagNotNull.put("energy", value.serializeNBT()) itemStack.tagNotNull.put(NBT_KEY, value.serializeNBT())
} }
override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
@ -127,6 +127,10 @@ sealed class ItemEnergyStorageImpl(
override fun canReceive(): Boolean { override fun canReceive(): Boolean {
return type != EnergyFlow.OUTPUT return type != EnergyFlow.OUTPUT
} }
companion object {
const val NBT_KEY = "energy"
}
} }
open class EnergyConsumerItem(stack: ItemStack, maxBatteryLevel: ImpreciseFraction, maxInput: ImpreciseFraction? = null, maxOutput: ImpreciseFraction? = maxInput) open class EnergyConsumerItem(stack: ItemStack, maxBatteryLevel: ImpreciseFraction, maxInput: ImpreciseFraction? = null, maxOutput: ImpreciseFraction? = maxInput)

View File

@ -1,7 +1,8 @@
package ru.dbotthepony.mc.otm.capability package ru.dbotthepony.mc.otm.capability
import net.minecraft.core.Direction import net.minecraft.core.Direction
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.capabilities.ICapabilityProvider import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
@ -9,8 +10,10 @@ import net.minecraftforge.energy.IEnergyStorage
import net.minecraftforge.fml.ModList import net.minecraftforge.fml.ModList
import ru.dbotthepony.mc.otm.compat.mekanism.getMekanismEnergySided import ru.dbotthepony.mc.otm.compat.mekanism.getMekanismEnergySided
import ru.dbotthepony.mc.otm.compat.mekanism.mekanismEnergy import ru.dbotthepony.mc.otm.compat.mekanism.mekanismEnergy
import ru.dbotthepony.mc.otm.container.iterator
import ru.dbotthepony.mc.otm.core.iterator
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.orNull import ru.dbotthepony.mc.otm.core.orNull
val ICapabilityProvider.matteryPlayer: MatteryPlayerCapability? get() = getCapability(MatteryCapability.MATTERY_PLAYER).orNull() val ICapabilityProvider.matteryPlayer: MatteryPlayerCapability? get() = getCapability(MatteryCapability.MATTERY_PLAYER).orNull()
@ -117,3 +120,58 @@ fun ICapabilityProvider.getMatteryEnergySided(side: Direction? = null): LazyOpti
return getCapability(MatteryCapability.ENERGY, side) return getCapability(MatteryCapability.ENERGY, side)
} }
fun Player.extendedItemIterator(): MutableIterator<ItemStack> {
return object : MutableIterator<ItemStack> {
private val regular = this@extendedItemIterator.inventory.iterator()
private val mattery: MutableIterator<ItemStack>
private var isSecond = false
init {
val get = this@extendedItemIterator.matteryPlayer
if (get != null && get.hasExoSuit) {
mattery = get.exoSuitContainer.iterator()
} else {
mattery = object : MutableIterator<ItemStack> {
override fun hasNext(): Boolean {
return false
}
override fun next(): ItemStack {
throw UnsupportedOperationException()
}
override fun remove() {
throw UnsupportedOperationException()
}
}
}
}
override fun hasNext(): Boolean {
return regular.hasNext() || mattery.hasNext()
}
override fun next(): ItemStack {
if (isSecond) {
return mattery.next()
}
if (!regular.hasNext()) {
isSecond = true
return mattery.next()
}
return regular.next()
}
override fun remove() {
if (isSecond) {
mattery.remove()
} else {
regular.remove()
}
}
}
}

View File

@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.capability
import it.unimi.dsi.fastutil.objects.ObjectArraySet import it.unimi.dsi.fastutil.objects.ObjectArraySet
import net.minecraft.ChatFormatting import net.minecraft.ChatFormatting
import net.minecraft.advancements.CriteriaTriggers
import net.minecraft.core.Direction import net.minecraft.core.Direction
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag import net.minecraft.nbt.ListTag
@ -39,7 +38,7 @@ import ru.dbotthepony.mc.otm.android.AndroidFeatureType
import ru.dbotthepony.mc.otm.android.AndroidResearch import ru.dbotthepony.mc.otm.android.AndroidResearch
import ru.dbotthepony.mc.otm.android.AndroidResearchType import ru.dbotthepony.mc.otm.android.AndroidResearchType
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.menu.ExoSuitInventoryMenu import ru.dbotthepony.mc.otm.menu.ExoSuitInventoryMenu
import ru.dbotthepony.mc.otm.network.* import ru.dbotthepony.mc.otm.network.*
import ru.dbotthepony.mc.otm.registry.AndroidFeatures import ru.dbotthepony.mc.otm.registry.AndroidFeatures
@ -79,6 +78,10 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn
private set(value) { private set(value) {
_exoSuitMenu = null _exoSuitMenu = null
if (ply.containerMenu.slots.any { it.container == field }) {
ply.closeContainer()
}
for (i in 0 until value.containerSize.coerceAtMost(field.containerSize)) { for (i in 0 until value.containerSize.coerceAtMost(field.containerSize)) {
if (!field[i].isEmpty) { if (!field[i].isEmpty) {
value[i] = field[i] value[i] = field[i]
@ -627,7 +630,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn
shouldSendIteration = false shouldSendIteration = false
} }
if (hasExoSuit && ply.containerMenu != exoSuitMenu) { if (hasExoSuit && ply.containerMenu == ply.inventoryMenu) {
exoSuitMenu.broadcastChanges() exoSuitMenu.broadcastChanges()
} }
@ -762,10 +765,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn
@Suppress("unused") @Suppress("unused")
companion object { companion object {
@JvmField
val UNAFFECTED_EFFECTS = ObjectArraySet<MobEffect>() val UNAFFECTED_EFFECTS = ObjectArraySet<MobEffect>()
@JvmStatic
fun registerEffects(event: FMLCommonSetupEvent) { fun registerEffects(event: FMLCommonSetupEvent) {
UNAFFECTED_EFFECTS.add(MobEffects.CONDUIT_POWER) UNAFFECTED_EFFECTS.add(MobEffects.CONDUIT_POWER)
UNAFFECTED_EFFECTS.add(MobEffects.HEAL) UNAFFECTED_EFFECTS.add(MobEffects.HEAL)
@ -782,7 +783,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn
UNAFFECTED_EFFECTS.add(MobEffects.DOLPHINS_GRACE) UNAFFECTED_EFFECTS.add(MobEffects.DOLPHINS_GRACE)
} }
@SubscribeEvent
fun onLivingTick(event: LivingTickEvent) { fun onLivingTick(event: LivingTickEvent) {
val ent = event.entity val ent = event.entity
@ -797,7 +797,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn
} }
} }
@SubscribeEvent(priority = EventPriority.LOWEST)
fun onHurtEvent(event: LivingHurtEvent) { fun onHurtEvent(event: LivingHurtEvent) {
if (event.isCanceled) { if (event.isCanceled) {
return return
@ -809,8 +808,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn
const val CAPABILITY_KEY = "otm_player" const val CAPABILITY_KEY = "otm_player"
val CAPABILITY_LOCATION = ResourceLocation(OverdriveThatMatters.MOD_ID, CAPABILITY_KEY) val CAPABILITY_LOCATION = ResourceLocation(OverdriveThatMatters.MOD_ID, CAPABILITY_KEY)
@SubscribeEvent fun onAttachCapabilityEvent(event: AttachCapabilitiesEvent<Entity>) {
fun onAttachCapabilityEvent(event: AttachCapabilitiesEvent<Entity?>) {
val ent = event.`object` val ent = event.`object`
if (ent is Player) { if (ent is Player) {
@ -818,18 +816,12 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn
} }
} }
@SubscribeEvent
fun onPlayerChangeDimensionEvent(event: PlayerEvent.PlayerChangedDimensionEvent) { fun onPlayerChangeDimensionEvent(event: PlayerEvent.PlayerChangedDimensionEvent) {
event.entity.getCapability(MatteryCapability.MATTERY_PLAYER) event.entity.getCapability(MatteryCapability.MATTERY_PLAYER)
.ifPresentK { it.invalidateNetworkState() } .ifPresentK { it.invalidateNetworkState() }
} }
@SubscribeEvent(priority = EventPriority.LOWEST)
fun onPlayerDeath(event: LivingDeathEvent) { fun onPlayerDeath(event: LivingDeathEvent) {
if (event.isCanceled) {
return
}
val ply = event.entity as? Player ?: return val ply = event.entity as? Player ?: return
val mattery = ply.matteryPlayer ?: return val mattery = ply.matteryPlayer ?: return
@ -856,7 +848,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn
} }
} }
@SubscribeEvent
fun onPlayerCloneEvent(event: PlayerEvent.Clone) { fun onPlayerCloneEvent(event: PlayerEvent.Clone) {
val it = event.entity.matteryPlayer ?: return val it = event.entity.matteryPlayer ?: return
@ -889,7 +880,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, IMatteryEn
private val itemPickupTicks = WeakHashMap<Player, WeakHashMap<ItemEntity, MutableInt>>() private val itemPickupTicks = WeakHashMap<Player, WeakHashMap<ItemEntity, MutableInt>>()
@SubscribeEvent(priority = EventPriority.LOW)
fun onPickupEvent(event: EntityItemPickupEvent) { fun onPickupEvent(event: EntityItemPickupEvent) {
if (event.item.owner != null && event.item.owner != event.entity.uuid && event.item.age < 200 || event.item.item.isEmpty) { if (event.item.owner != null && event.item.owner != event.entity.uuid && event.item.age < 200 || event.item.item.isEmpty) {
return return

View File

@ -1,21 +1,14 @@
package ru.dbotthepony.mc.otm.capability.drive package ru.dbotthepony.mc.otm.capability.drive
import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.objects.ObjectArraySet import it.unimi.dsi.fastutil.objects.ObjectArraySet
import kotlin.jvm.JvmOverloads import kotlin.jvm.JvmOverloads
import java.util.UUID import java.util.UUID
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag import net.minecraft.nbt.ListTag
import net.minecraft.nbt.LongTag
import net.minecraft.nbt.Tag import net.minecraft.nbt.Tag
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.core.BigInteger import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.isPositive
import ru.dbotthepony.mc.otm.core.serializeNBT
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.set
import ru.dbotthepony.mc.otm.storage.* import ru.dbotthepony.mc.otm.storage.*
import java.math.BigInteger import java.math.BigInteger
import java.util.ArrayList import java.util.ArrayList

View File

@ -36,7 +36,6 @@ import java.util.ArrayList
* 5. Mods which check items for being stack-able even with stack size of 1 gonna compare nbt tag, * 5. Mods which check items for being stack-able even with stack size of 1 gonna compare nbt tag,
* which will be performance tanking due to clause 1. * which will be performance tanking due to clause 1.
*/ */
@Suppress("unused")
object DrivePool { object DrivePool {
private val LOGGER = LogManager.getLogger() private val LOGGER = LogManager.getLogger()
private val pool = Object2ObjectAVLTreeMap<UUID, WeakDriveReference>() private val pool = Object2ObjectAVLTreeMap<UUID, WeakDriveReference>()
@ -130,7 +129,6 @@ object DrivePool {
} }
} }
@SubscribeEvent(priority = EventPriority.LOWEST)
fun onServerPostTick(event: ServerTickEvent) { fun onServerPostTick(event: ServerTickEvent) {
if (event.phase == TickEvent.Phase.END) { if (event.phase == TickEvent.Phase.END) {
if (exception != null) { if (exception != null) {
@ -152,7 +150,6 @@ object DrivePool {
return Thread.currentThread() === serverThread return Thread.currentThread() === serverThread
} }
@SubscribeEvent(priority = EventPriority.HIGHEST)
fun serverStartEvent(event: ServerAboutToStartEvent) { fun serverStartEvent(event: ServerAboutToStartEvent) {
if (thread?.isAlive == true) { if (thread?.isAlive == true) {
LOGGER.error("FMLServerStartedEvent fired twice.") LOGGER.error("FMLServerStartedEvent fired twice.")
@ -172,7 +169,6 @@ object DrivePool {
thread = Thread(null, this::thread, "Overdrive That Matters DrivePool IO").also { it.start() } thread = Thread(null, this::thread, "Overdrive That Matters DrivePool IO").also { it.start() }
} }
@SubscribeEvent(priority = EventPriority.HIGHEST)
fun serverStopEvent(event: ServerStoppingEvent) { fun serverStopEvent(event: ServerStoppingEvent) {
val thread = thread val thread = thread
@ -189,7 +185,6 @@ object DrivePool {
pool.clear() pool.clear()
} }
@SubscribeEvent
fun onWorldSave(event: LevelEvent.Save) { fun onWorldSave(event: LevelEvent.Save) {
writeBacklog() writeBacklog()
} }

View File

@ -6,12 +6,11 @@ import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraftforge.registries.ForgeRegistries import net.minecraftforge.registries.ForgeRegistries
import net.minecraftforge.registries.RegistryManager
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.core.BigInteger import ru.dbotthepony.mc.otm.core.BigInteger
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.serializeNBT import ru.dbotthepony.mc.otm.core.serializeNBT
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.storage.IStorageTuple import ru.dbotthepony.mc.otm.storage.IStorageTuple
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
import ru.dbotthepony.mc.otm.storage.StorageStackType import ru.dbotthepony.mc.otm.storage.StorageStackType

View File

@ -5,6 +5,7 @@ import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import java.util.* import java.util.*
import java.util.function.Predicate import java.util.function.Predicate
import java.util.stream.Collectors import java.util.stream.Collectors
import java.util.stream.Stream
interface IMatterHandler { interface IMatterHandler {
val storedMatter: ImpreciseFraction val storedMatter: ImpreciseFraction
@ -14,6 +15,7 @@ interface IMatterHandler {
fun receiveMatterInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction fun receiveMatterInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
fun extractMatterOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction fun extractMatterOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
fun extractMatterInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction fun extractMatterInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
val direction: MatterDirection val direction: MatterDirection
val missingMatter: ImpreciseFraction val missingMatter: ImpreciseFraction
get() = maxStoredMatter.minus(storedMatter).moreThanZero() get() = maxStoredMatter.minus(storedMatter).moreThanZero()
@ -27,42 +29,44 @@ interface IMatterHandler {
enum class MatterDirection { RECEIVE, EXTRACT, BIDIRECTIONAL } enum class MatterDirection { RECEIVE, EXTRACT, BIDIRECTIONAL }
interface IMatterTaskProvider { interface IReplicationTaskProvider {
/** /**
* @return immutable collection of tasks that can be allocated by a worker * It must return new stream each time
*/ */
val tasks: Collection<MatterTask> val replicationTasks: Stream<out IReplicationTask<*>>
/** /**
* @return immutable collection of all stored tasks, even fully allocated by workers * It must return new stream each time
*/ */
val allTasks: Collection<MatterTask> val allReplicationTasks: Stream<out IReplicationTask<*>>
/** /**
* Allocates (marks as work-in-progress) a task * Allocates (marks as work-in-progress) a task
* by incrementing it's in_progress by 1 * by incrementing it's [IReplicationTask.inProgress] by 1
* and shrinking required by 1 * and shrinking [IReplicationTask.required] by 1
* *
* If required == 0, it should not be returned by this method * If [IReplicationTask.required] == 0, it should not be returned by this method
* @param simulate whenever to change internal state * @param simulate whenever to change internal state
* @return MatterTaskAllocation(task, pattern) that should be performed, or null if no work is available * @return MatterTaskAllocation(task, pattern) that should be performed, or null if no work is available
*/ */
fun allocateTask(simulate: Boolean): MatterTaskAllocation? fun allocateTask(simulate: Boolean): ReplicationTaskAllocation?
/** /**
* Notify about task completion. If this provider indeed contain this task, it should * Notify about task completion. If this provider indeed contain this task, it should
* shrink in_progress by 1 * shrink in_progress by 1
* If in_progress == 0 and required == 0, it should discard the task * If in_progress == 0 and required == 0, it should discard the task
* @param task task being completed. this method should ignore tasks that are not owned by it. * @param taskId task being completed. this method should ignore tasks that are not owned by it.
* @return whenever task indeed belong to this provider and internal state was updated * @return whenever task indeed belong to this provider and internal state was updated
*/ */
fun notifyTaskCompletion(task: MatterTask): Boolean fun notifyTaskCompletion(taskId: UUID): Boolean
/** /**
* @param id uuid of task * @param id uuid of task
* @return MatterTask that this capability holds with this id, or null * @return MatterTask that this capability holds with this id, or null
*/ */
fun getTask(id: UUID): MatterTask? fun getTask(id: UUID): IReplicationTask<*>? {
return allReplicationTasks.filter { it.id == id }.findAny().orElse(null)
}
/** /**
* Destroys all tasks this capability contains * Destroys all tasks this capability contains
@ -72,50 +76,36 @@ interface IMatterTaskProvider {
interface IPatternStorage { interface IPatternStorage {
/** /**
* @return unmodifiable collection of stored patterns * It must return new stream each time
*/ */
val storedPatterns: Collection<PatternState> val storedPatterns: Stream<out IPatternState>
fun findPatterns(item: Item): Collection<PatternState> { fun findPatterns(item: Item): Collection<IPatternState> {
return findPatterns { item2: PatternState -> item == item2.item() } return findPatterns { item == it.item }
} }
fun findPatterns(predicate: Predicate<PatternState>?): Collection<PatternState> { fun findPatterns(predicate: Predicate<IPatternState>): Collection<IPatternState> {
return storedPatterns.stream().filter(predicate).collect(Collectors.toList()) return storedPatterns.filter(predicate).collect(Collectors.toList())
} }
fun findPattern(item: Item): PatternState? { fun findPattern(item: Item): IPatternState? {
return findPattern { item2: PatternState -> item == item2.item() } return storedPatterns.filter { it.item == item }.findAny().orElse(null)
} }
fun findPattern(predicate: Predicate<PatternState>): PatternState? { fun getPattern(id: UUID?): IPatternState? {
for (pattern in storedPatterns) { return storedPatterns.filter { it.id == id }.findAny().orElse(null)
if (predicate.test(pattern)) {
return pattern
}
} }
return null fun hasPattern(item: Item): Boolean {
return storedPatterns.filter { it.item == item }.findAny().isPresent
} }
fun getPattern(id: UUID?): PatternState? { fun hasPattern(state: IPatternState): Boolean {
id ?: return null return hasPattern(state.id)
for (pattern in storedPatterns) {
if (pattern.id == id) {
return pattern
}
}
return null
}
fun hasPattern(state: PatternState): Boolean {
return getPattern(state.id) != null
} }
fun hasPattern(id: UUID?): Boolean { fun hasPattern(id: UUID?): Boolean {
return getPattern(id) != null return storedPatterns.filter { it.id == id }.findAny().isPresent
} }
val capacity: Int val capacity: Int
@ -126,17 +116,17 @@ interface IPatternStorage {
* and if it fail, try only_update = false * and if it fail, try only_update = false
* *
* @param pattern pattern to be inserted or update value from * @param pattern pattern to be inserted or update value from
* @param only_update do not insert new pattern if this pattern's UUID is not matched * @param onlyUpdate do not insert new pattern if this pattern's UUID is not matched
* @param simulate whenever to affect state * @param simulate whenever to affect state
* @return record of status of the operation (at status() FAIL, UPDATED, INSERTED) as well as new_state and old_state * @return record of status of the operation (at status() FAIL, UPDATED, INSERTED) as well as new_state and old_state
*/ */
fun insertPattern(pattern: PatternState, only_update: Boolean, simulate: Boolean): PatternInsertStatus fun insertPattern(pattern: IPatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus
fun insertPattern(pattern: PatternState, simulate: Boolean): PatternInsertStatus { fun insertPattern(pattern: IPatternState, simulate: Boolean): PatternInsertStatus {
return insertPattern(pattern, false, simulate) return insertPattern(pattern, false, simulate)
} }
fun updatePattern(pattern: PatternState, simulate: Boolean): PatternInsertStatus { fun updatePattern(pattern: IPatternState, simulate: Boolean): PatternInsertStatus {
return insertPattern(pattern, true, simulate) return insertPattern(pattern, true, simulate)
} }
} }

View File

@ -8,17 +8,17 @@ private enum class PatternInsertResult {
sealed class PatternInsertStatus( sealed class PatternInsertStatus(
private val status: PatternInsertResult, private val status: PatternInsertResult,
val newState: PatternState?, val newState: IPatternState?,
val oldState: PatternState? val oldState: IPatternState?
) { ) {
val isFailed get() = status === PatternInsertResult.FAIL val isFailed get() = status == PatternInsertResult.FAIL
val isUpdated get() = status === PatternInsertResult.UPDATED val isUpdated get() = status == PatternInsertResult.UPDATED
val isInserted get() = status === PatternInsertResult.INSERTED val isInserted get() = status == PatternInsertResult.INSERTED
} }
object PatternInsertFailure : PatternInsertStatus(PatternInsertResult.FAIL, null, null) object PatternInsertFailure : PatternInsertStatus(PatternInsertResult.FAIL, null, null)
class PatternInsertUpdated(new: PatternState, old: PatternState) : PatternInsertStatus(PatternInsertResult.UPDATED, new, old) class PatternInsertUpdated(new: IPatternState, old: IPatternState) : PatternInsertStatus(PatternInsertResult.UPDATED, new, old)
class PatternInsertInserted(new: PatternState) : PatternInsertStatus(PatternInsertResult.INSERTED, new, null) class PatternInsertInserted(new: IPatternState) : PatternInsertStatus(PatternInsertResult.INSERTED, new, null)
@JvmRecord @JvmRecord
data class MatterTaskAllocation(val task: MatterTask, val pattern: PatternState?) data class ReplicationTaskAllocation(val task: IReplicationTask<*>, val pattern: IPatternState?)

View File

@ -4,7 +4,8 @@ import net.minecraft.nbt.CompoundTag
import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
open class MatterHandlerImpl @JvmOverloads constructor( open class MatterHandlerImpl @JvmOverloads constructor(
protected val listener: Runnable?, protected val listener: Runnable?,

View File

@ -0,0 +1,146 @@
package ru.dbotthepony.mc.otm.capability.matter
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.core.*
import java.util.*
sealed interface IPatternState {
val id: UUID
val item: Item
val researchPercent: Double
fun asMutable(): MutablePatternState
fun asImmutable() : PatternState
fun matchId(other: IPatternState): Boolean {
return other.id == id
}
fun copyAsMutable(
id: UUID = this.id,
item: Item = this.item,
researchPercent: Double = this.researchPercent,
): MutablePatternState {
return MutablePatternState(id, item, researchPercent)
}
fun copyAsImmutable(
id: UUID = this.id,
item: Item = this.item,
researchPercent: Double = this.researchPercent,
) : PatternState {
return PatternState(id, item, researchPercent)
}
fun stack(count: Int = 1): ItemStack {
return ItemStack(item, count)
}
fun serializeNBT(): CompoundTag {
return CompoundTag().also {
it["id"] = id
it["item"] = item.registryName!!.toString()
it["researchPercent"] = researchPercent
}
}
fun write(buff: FriendlyByteBuf) {
buff.writeUUID(id)
buff.writeItemType(item)
buff.writeDouble(researchPercent)
}
}
private fun deserializeNBT(nbt: Tag?, mutable: Boolean): IPatternState? {
if (nbt !is CompoundTag)
return null
if (!nbt.contains("id", "researchPercent", "item"))
return null
val id = nbt.getUUID("id")
val researchPercent = nbt.getDouble("researchPercent")
val item = ForgeRegistries.ITEMS.getValue(ResourceLocation(nbt.getString("item"))) ?: return null
if (item == Items.AIR)
return null
if (mutable) {
return MutablePatternState(id, item, researchPercent)
} else {
return PatternState(id, item, researchPercent)
}
}
private fun read(buff: FriendlyByteBuf, mutable: Boolean): IPatternState? {
val id = buff.readUUID()
val item = buff.readItemType()
val researchPercent = buff.readDouble()
item ?: return null
if (mutable) {
return MutablePatternState(id, item, researchPercent)
} else {
return PatternState(id, item, researchPercent)
}
}
data class PatternState(
override val id: UUID,
override val item: Item,
override val researchPercent: Double,
) : IPatternState {
override fun asMutable(): MutablePatternState {
return MutablePatternState(id, item, researchPercent)
}
override fun asImmutable(): PatternState {
return this
}
companion object {
fun deserializeNBT(tag: Tag?): PatternState? {
return deserializeNBT(tag, false) as PatternState?
}
fun read(buff: FriendlyByteBuf): PatternState? {
return read(buff, false) as PatternState?
}
}
}
data class MutablePatternState(
override val id: UUID,
override val item: Item,
override var researchPercent: Double,
) : IPatternState {
override fun asMutable(): MutablePatternState {
return this
}
override fun asImmutable(): PatternState {
return PatternState(id, item, researchPercent)
}
companion object {
fun deserializeNBT(tag: Tag?): MutablePatternState? {
return deserializeNBT(tag, true) as MutablePatternState?
}
fun read(buff: FriendlyByteBuf): MutablePatternState? {
return read(buff, true) as MutablePatternState?
}
}
}
fun FriendlyByteBuf.writePatternState(state: IPatternState) = state.write(this)
fun FriendlyByteBuf.readPatternState() = PatternState.read(this)
fun FriendlyByteBuf.readMutablePatternState() = MutablePatternState.read(this)

View File

@ -0,0 +1,210 @@
package ru.dbotthepony.mc.otm.capability.matter
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.Tag
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.core.readItemType
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.core.writeItemType
import java.util.UUID
sealed interface IReplicationTask<S : IReplicationTask<S>> {
val id: UUID
val patternId: UUID?
val item: Item
val inProgress: Int
val finished: Int
val required: Int
fun asMutable(): MutableReplicationTask
fun asImmutable(): ReplicationTask
val total get() = inProgress + finished + required
fun copyAsMutable(
id: UUID = this.id,
patternId: UUID? = this.patternId,
item: Item = this.item,
inProgress: Int = this.inProgress,
finished: Int = this.finished,
required: Int = this.required,
): MutableReplicationTask {
return MutableReplicationTask(id, patternId, item, inProgress, finished, required)
}
fun copyAsImmutable(
id: UUID = this.id,
patternId: UUID? = this.patternId,
item: Item = this.item,
inProgress: Int = this.inProgress,
finished: Int = this.finished,
required: Int = this.required,
): ReplicationTask {
return ReplicationTask(id, patternId, item, inProgress, finished, required)
}
fun matchId(other: IReplicationTask<*>): Boolean {
return other.id == id
}
fun stack(count: Int = 1): ItemStack {
return ItemStack(item, count)
}
fun allocate(amount: Int = 1): S
fun finish(amount: Int = 1): S
fun serializeNBT(): CompoundTag {
return CompoundTag().also {
it["id"] = id
if (patternId != null)
it["patternId"] = patternId!!
it["item"] = item.registryName!!.toString()
it["inProgress"] = inProgress
it["finished"] = finished
it["required"] = required
}
}
fun write(buff: FriendlyByteBuf) {
buff.writeUUID(id)
buff.writeBoolean(patternId != null)
patternId?.let(buff::writeUUID)
buff.writeItemType(item)
buff.writeInt(inProgress)
buff.writeInt(finished)
buff.writeInt(required)
}
}
private fun deserializeNBT(nbt: Tag?, mutable: Boolean): IReplicationTask<*>? {
if (nbt !is CompoundTag)
return null
if (!nbt.contains("id") || !nbt.contains("inProgress") || !nbt.contains("finished") || !nbt.contains("required") || !nbt.contains("item"))
return null
val item = ForgeRegistries.ITEMS.getValue(ResourceLocation(nbt.getString("item"))) ?: return null
if (item == Items.AIR)
return null
val id = nbt.getUUID("id")
val patternId = if (nbt.contains("patternId")) nbt.getUUID("patternId") else null
val inProgress = nbt.getInt("inProgress")
val finished = nbt.getInt("finished")
val required = nbt.getInt("required")
if (mutable) {
return MutableReplicationTask(id, patternId, item, inProgress, finished, required)
} else {
return ReplicationTask(id, patternId, item, inProgress, finished, required)
}
}
private fun read(buff: FriendlyByteBuf, mutable: Boolean): IReplicationTask<*>? {
val id = buff.readUUID()
val patternId: UUID? = if (buff.readBoolean()) buff.readUUID() else null
val item = buff.readItemType()
val inProgress = buff.readInt()
val finished = buff.readInt()
val required = buff.readInt()
item ?: return null
if (mutable) {
return MutableReplicationTask(id, patternId, item, inProgress, finished, required)
} else {
return ReplicationTask(id, patternId, item, inProgress, finished, required)
}
}
data class ReplicationTask(
override val id: UUID,
override val patternId: UUID?,
override val item: Item,
override val inProgress: Int,
override val finished: Int,
override val required: Int
) : IReplicationTask<ReplicationTask> {
override fun asMutable(): MutableReplicationTask {
return MutableReplicationTask(id, patternId, item, inProgress, finished, required)
}
override fun asImmutable(): ReplicationTask {
return this
}
override fun allocate(amount: Int): ReplicationTask {
return ReplicationTask(id, patternId, item, inProgress + amount, finished, required - amount)
}
override fun finish(amount: Int): ReplicationTask {
return ReplicationTask(id, patternId, item, inProgress - amount, finished + amount, required)
}
companion object {
fun deserializeNBT(nbt: Tag?): ReplicationTask? {
return deserializeNBT(nbt, false) as ReplicationTask?
}
fun read(buff: FriendlyByteBuf): ReplicationTask? {
return read(buff, false) as ReplicationTask?
}
}
}
data class MutableReplicationTask(
override val id: UUID,
override val patternId: UUID?,
override val item: Item,
override var inProgress: Int,
override var finished: Int,
override var required: Int
) : IReplicationTask<MutableReplicationTask> {
override fun asMutable(): MutableReplicationTask {
return this
}
override fun asImmutable(): ReplicationTask {
return ReplicationTask(id, patternId, item, inProgress, finished, required)
}
override fun allocate(amount: Int): MutableReplicationTask {
inProgress += amount
finished -= amount
return this
}
override fun finish(amount: Int): MutableReplicationTask {
finished += amount
inProgress -= amount
return this
}
companion object {
fun deserializeNBT(nbt: Tag?): MutableReplicationTask? {
return deserializeNBT(nbt, true) as MutableReplicationTask?
}
fun read(buff: FriendlyByteBuf): MutableReplicationTask? {
return read(buff, true) as MutableReplicationTask?
}
}
}
fun FriendlyByteBuf.writeReplicationTask(task: IReplicationTask<*>) = task.write(this)
fun FriendlyByteBuf.readReplicationTask() = ReplicationTask.read(this)
fun FriendlyByteBuf.readMutableReplicationTask() = MutableReplicationTask.read(this)

View File

@ -0,0 +1,53 @@
package ru.dbotthepony.mc.otm.client
import net.minecraft.client.gui.screens.inventory.InventoryScreen
import net.minecraftforge.client.event.MovementInputUpdateEvent
import net.minecraftforge.client.event.ScreenEvent
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.screen.ExoSuitInventoryScreen
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
object ClientEventHandler {
fun inputEvent(event: MovementInputUpdateEvent) {
val ply = event.entity
val input = event.input
val cap = ply.matteryPlayer ?: return
if (cap.hasFeature(AndroidFeatures.AIR_BAGS))
return
if (ply.abilities.mayfly) {
cap.lastJumpTicks = 14
} else {
if (ply.isInWater) {
if (ply.isOnGround) {
cap.lastJumpTicks = 14
}
if (ply.isSwimming) {
ply.isSwimming = false
}
if (cap.lastJumpTicks <= 0) {
input.jumping = false
input.up = false
} else {
cap.lastJumpTicks--
}
}
}
}
fun screenOpen(event: ScreenEvent.Opening) {
if (minecraft.player?.isCreative == true) {
return
}
val player = minecraft.player?.matteryPlayer ?: return
if (player.hasExoSuit && event.newScreen is InventoryScreen) {
event.newScreen = ExoSuitInventoryScreen(player.exoSuitMenu)
}
}
}

View File

@ -1,56 +0,0 @@
package ru.dbotthepony.mc.otm.client
import net.minecraft.client.gui.screens.inventory.InventoryScreen
import net.minecraftforge.client.event.MovementInputUpdateEvent
import net.minecraftforge.client.event.ScreenEvent
import net.minecraftforge.eventbus.api.SubscribeEvent
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.screen.ExoSuitInventoryScreen
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
@SubscribeEvent
@Suppress("unused")
fun inputEvent(event: MovementInputUpdateEvent) {
val ply = event.entity
val input = event.input
val cap = ply.matteryPlayer ?: return
if (cap.hasFeature(AndroidFeatures.AIR_BAGS))
return
if (ply.abilities.mayfly) {
cap.lastJumpTicks = 14
} else {
if (ply.isInWater) {
if (ply.isOnGround) {
cap.lastJumpTicks = 14
}
if (ply.isSwimming) {
ply.isSwimming = false
}
if (cap.lastJumpTicks <= 0) {
input.jumping = false
input.up = false
} else {
cap.lastJumpTicks--
}
}
}
}
@SubscribeEvent
@Suppress("unused")
fun screenOpen(event: ScreenEvent.Opening) {
if (minecraft.player?.isCreative == true) {
return
}
val player = minecraft.player?.matteryPlayer ?: return
if (player.hasExoSuit && event.newScreen is InventoryScreen) {
event.newScreen = ExoSuitInventoryScreen(player.exoSuitMenu)
}
}

View File

@ -2,6 +2,12 @@ package ru.dbotthepony.mc.otm.client
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.gui.Font import net.minecraft.client.gui.Font
import net.minecraft.client.resources.sounds.SimpleSoundInstance
import net.minecraft.sounds.SoundEvents
inline val minecraft: Minecraft get() = Minecraft.getInstance() inline val minecraft: Minecraft get() = Minecraft.getInstance()
inline val font: Font get() = minecraft.font inline val font: Font get() = minecraft.font
fun playGuiClickSound() {
minecraft.soundManager.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0f))
}

View File

@ -18,14 +18,13 @@ import net.minecraftforge.client.gui.overlay.GuiOverlayManager
import net.minecraftforge.eventbus.api.EventPriority import net.minecraftforge.eventbus.api.EventPriority
import net.minecraftforge.eventbus.api.SubscribeEvent import net.minecraftforge.eventbus.api.SubscribeEvent
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.TextComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.TranslatableComponent
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.* import ru.dbotthepony.mc.otm.client.render.*
import ru.dbotthepony.mc.otm.core.RGBAColor import ru.dbotthepony.mc.otm.core.RGBAColor
import ru.dbotthepony.mc.otm.ifPresentK import ru.dbotthepony.mc.otm.core.ifPresentK
import java.util.* import java.util.*
object MatteryGUI { object MatteryGUI {
@ -40,8 +39,6 @@ object MatteryGUI {
private val button_shaker = Random() private val button_shaker = Random()
@SubscribeEvent
@Suppress("unused")
fun onScreenRender(event: ScreenEvent.Render.Pre) { fun onScreenRender(event: ScreenEvent.Render.Pre) {
if (knownButtonScreen != null && knownButton == null) { if (knownButtonScreen != null && knownButton == null) {
for (widget in knownButtonScreen!!.renderables) { for (widget in knownButtonScreen!!.renderables) {
@ -88,8 +85,6 @@ object MatteryGUI {
} }
} }
@SubscribeEvent(priority = EventPriority.LOWEST)
@Suppress("unused")
fun onOpenGUIEvent(event: ScreenEvent.Opening) { fun onOpenGUIEvent(event: ScreenEvent.Opening) {
knownButtonX = -1 knownButtonX = -1
knownButtonY = -1 knownButtonY = -1
@ -199,14 +194,10 @@ object MatteryGUI {
popScissorRect() popScissorRect()
} }
@SubscribeEvent
@Suppress("unused")
fun onRenderGuiEvent(event: RenderGuiEvent.Post) { fun onRenderGuiEvent(event: RenderGuiEvent.Post) {
showIteration(event) showIteration(event)
} }
@SubscribeEvent(priority = EventPriority.HIGH)
@Suppress("unused")
fun onLayerRenderEvent(event: RenderGuiOverlayEvent.Pre) { fun onLayerRenderEvent(event: RenderGuiOverlayEvent.Pre) {
if (event.overlay != FOOD_LEVEL_ELEMENT && event.overlay != AIR_LEVEL_ELEMENT) { if (event.overlay != FOOD_LEVEL_ELEMENT && event.overlay != AIR_LEVEL_ELEMENT) {
return return

View File

@ -11,7 +11,7 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
import org.lwjgl.opengl.GL30 import org.lwjgl.opengl.GL30
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.GravitationStabilizerBlockEntity import ru.dbotthepony.mc.otm.block.entity.GravitationStabilizerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity
import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.capability.matteryPlayer

View File

@ -6,7 +6,7 @@ import net.minecraft.client.renderer.MultiBufferSource
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
import net.minecraft.core.Direction import net.minecraft.core.Direction
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.EnergyCounterBlock import ru.dbotthepony.mc.otm.block.EnergyCounterBlock
import ru.dbotthepony.mc.otm.block.entity.EnergyCounterBlockEntity import ru.dbotthepony.mc.otm.block.entity.EnergyCounterBlockEntity
import ru.dbotthepony.mc.otm.client.render.* import ru.dbotthepony.mc.otm.client.render.*

View File

@ -10,12 +10,12 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
import net.minecraft.client.renderer.texture.OverlayTexture import net.minecraft.client.renderer.texture.OverlayTexture
import net.minecraft.core.Direction import net.minecraft.core.Direction
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.BlackHoleBlock import ru.dbotthepony.mc.otm.block.BlackHoleBlock
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.GravitationStabilizerBlockEntity import ru.dbotthepony.mc.otm.block.entity.GravitationStabilizerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.client.render.* import ru.dbotthepony.mc.otm.client.render.*
import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.*
import kotlin.math.PI import kotlin.math.PI

View File

@ -7,16 +7,14 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction import it.unimi.dsi.fastutil.ints.Int2ObjectFunction
import net.minecraft.ChatFormatting import net.minecraft.ChatFormatting
import net.minecraft.client.Minecraft import net.minecraft.client.Minecraft
import net.minecraft.client.resources.sounds.SimpleSoundInstance
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.sounds.SoundEvents
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.android.AndroidResearch import ru.dbotthepony.mc.otm.android.AndroidResearch
import ru.dbotthepony.mc.otm.android.AndroidResearchType import ru.dbotthepony.mc.otm.android.AndroidResearchType
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.playGuiClickSound
import ru.dbotthepony.mc.otm.client.render.Widgets18 import ru.dbotthepony.mc.otm.client.render.Widgets18
import ru.dbotthepony.mc.otm.client.render.drawColor import ru.dbotthepony.mc.otm.client.render.drawColor
import ru.dbotthepony.mc.otm.client.render.drawLine import ru.dbotthepony.mc.otm.client.render.drawLine
@ -24,7 +22,7 @@ import ru.dbotthepony.mc.otm.client.render.drawRect
import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel
import ru.dbotthepony.mc.otm.core.RGBAColor import ru.dbotthepony.mc.otm.core.RGBAColor
import ru.dbotthepony.mc.otm.ifPresentK import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.menu.AndroidStationMenu import ru.dbotthepony.mc.otm.menu.AndroidStationMenu
import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel
import ru.dbotthepony.mc.otm.network.AndroidResearchRequestPacket import ru.dbotthepony.mc.otm.network.AndroidResearchRequestPacket
@ -383,7 +381,7 @@ private class AndroidResearchButton(
MatteryPlayerNetworkChannel.sendToServer(AndroidResearchRequestPacket(node.type)) MatteryPlayerNetworkChannel.sendToServer(AndroidResearchRequestPacket(node.type))
} }
minecraft.soundManager.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0f)) playGuiClickSound()
} }
return true return true
@ -479,6 +477,7 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean { override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
if (isPreview) { if (isPreview) {
playGuiClickSound()
openResearchTree() openResearchTree()
return true return true
} }

View File

@ -2,9 +2,8 @@ package ru.dbotthepony.mc.otm.client.screen
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel
import ru.dbotthepony.mc.otm.menu.ChemicalGeneratorMenu import ru.dbotthepony.mc.otm.menu.ChemicalGeneratorMenu

View File

@ -4,9 +4,10 @@ import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
import ru.dbotthepony.mc.otm.core.maxScrollDivision
import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem
import ru.dbotthepony.mc.otm.menu.DriveViewerMenu import ru.dbotthepony.mc.otm.menu.DriveViewerMenu
@ -51,15 +52,15 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp
val grid = GridPanel(this, frame, 28f, 16f, GRID_WIDTH * 18f, GRID_HEIGHT * 18f, GRID_WIDTH, GRID_HEIGHT) val grid = GridPanel(this, frame, 28f, 16f, GRID_WIDTH * 18f, GRID_HEIGHT * 18f, GRID_WIDTH, GRID_HEIGHT)
val scrollBar = ContinuousScrollBarPanel(this, frame, 192f, 14f, 92f) val scrollBar = DiscreteScrollBarPanel(this, frame, { maxScrollDivision(menu.networkedItemView.itemCount, GRID_WIDTH) }, { _, _, _ -> }, 192f, 14f, 92f)
scrollBar.setupRowMultiplier { menu.networkedItemView.itemCount / GRID_WIDTH }
views.add(grid) views.add(grid)
views.add(scrollBar) views.add(scrollBar)
for (i in 0 until GRID_WIDTH * GRID_HEIGHT) { for (i in 0 until GRID_WIDTH * GRID_HEIGHT) {
object : AbstractSlotPanel(this@DriveViewerScreen, grid, 0f, 0f) { object : AbstractSlotPanel(this@DriveViewerScreen, grid, 0f, 0f) {
override fun getItemStack(): ItemStack { override fun getItemStack(): ItemStack {
val index = i + scrollBar.getScroll(menu.networkedItemView.sortedView.size / GRID_WIDTH) val index = i + scrollBar.scroll * GRID_WIDTH
return menu.networkedItemView.sortedView.getOrNull(index)?.stack?.item ?: ItemStack.EMPTY return menu.networkedItemView.sortedView.getOrNull(index)?.stack?.item ?: ItemStack.EMPTY
} }
@ -68,7 +69,7 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp
} }
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean { override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
val index = i + scrollBar.getScroll(GRID_WIDTH) val index = i + scrollBar.scroll * GRID_WIDTH
menu.networkedItemView.mouseClick(index, button) menu.networkedItemView.mouseClick(index, button)
return true return true
} }
@ -81,7 +82,7 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp
override fun getItemStackTooltip(stack: ItemStack): List<Component> { override fun getItemStackTooltip(stack: ItemStack): List<Component> {
return super.getItemStackTooltip(stack).also { return super.getItemStackTooltip(stack).also {
it as MutableList<Component> it as MutableList<Component>
val index = i + scrollBar.getScroll(menu.networkedItemView.sortedView.size / GRID_WIDTH) val index = i + scrollBar.scroll * GRID_WIDTH
val realStack = menu.networkedItemView.sortedView.getOrNull(index)!!.stack val realStack = menu.networkedItemView.sortedView.getOrNull(index)!!.stack
it.add(TranslatableComponent("otm.gui.item_amount", realStack.count.toString())) it.add(TranslatableComponent("otm.gui.item_amount", realStack.count.toString()))
} }

View File

@ -2,7 +2,7 @@ package ru.dbotthepony.mc.otm.client.screen
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.core.formatPower import ru.dbotthepony.mc.otm.core.formatPower
import ru.dbotthepony.mc.otm.menu.EnergyCounterMenu import ru.dbotthepony.mc.otm.menu.EnergyCounterMenu

View File

@ -3,9 +3,8 @@ package ru.dbotthepony.mc.otm.client.screen
import com.mojang.blaze3d.vertex.PoseStack import com.mojang.blaze3d.vertex.PoseStack
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction import it.unimi.dsi.fastutil.ints.Int2ObjectFunction
import net.minecraft.client.gui.screens.inventory.InventoryScreen
import net.minecraft.world.inventory.Slot import net.minecraft.world.inventory.Slot
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.client.render.element import ru.dbotthepony.mc.otm.client.render.element
import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.menu.ExoSuitInventoryMenu import ru.dbotthepony.mc.otm.menu.ExoSuitInventoryMenu
@ -13,36 +12,6 @@ import ru.dbotthepony.mc.otm.network.ExoSuitMenuOpen
import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel
class ExoSuitInventoryScreen(menu: ExoSuitInventoryMenu) : MatteryScreen<ExoSuitInventoryMenu>(menu, TranslatableComponent("otm.gui.exosuit")) { class ExoSuitInventoryScreen(menu: ExoSuitInventoryMenu) : MatteryScreen<ExoSuitInventoryMenu>(menu, TranslatableComponent("otm.gui.exosuit")) {
private val slotRows = Int2ObjectAVLTreeMap<EditablePanel>()
private fun getSlotsRow(index: Int): EditablePanel {
return slotRows.computeIfAbsent(index, Int2ObjectFunction {
val canvas = object : EditablePanel(this@ExoSuitInventoryScreen, null, width = AbstractSlotPanel.SIZE * 9f, height = AbstractSlotPanel.SIZE) {
override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
return false
}
}
val offset = it * 9
if (menu.combinedInventorySlots.size <= offset) {
return@Int2ObjectFunction canvas
}
for (i in 0 .. (8).coerceAtMost(menu.combinedInventorySlots.size - offset - 1)) {
val slot = object : SlotPanel<Slot>(this@ExoSuitInventoryScreen, canvas, menu.combinedInventorySlots[offset + i]) {
override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
return false
}
}
slot.dock = Dock.LEFT
}
return@Int2ObjectFunction canvas
})
}
override fun makeMainFrame(): FramePanel { override fun makeMainFrame(): FramePanel {
val frame = FramePanel(this, width = 200f, height = 180f, title = this.title) val frame = FramePanel(this, width = 200f, height = 180f, title = this.title)
@ -53,16 +22,16 @@ class ExoSuitInventoryScreen(menu: ExoSuitInventoryMenu) : MatteryScreen<ExoSuit
var mainInventoryLine: EditablePanel? = null var mainInventoryLine: EditablePanel? = null
val scrollPanel = DiscreteScrollBarPanel(this, null, maxScroll = { ((menu.combinedInventorySlots.size - 27) + 8) / 9 }, val scrollPanel = DiscreteScrollBarPanel(this, null, maxScroll = { ((menu.playerCombinedInventorySlots.size - 27) + 8) / 9 },
scrollCallback = { scrollCallback = {
_, old, new -> _, old, new ->
for (i in old .. old + 2) { for (i in old .. old + 2) {
getSlotsRow(i).visible = false getInventorySlotsRow(i).visible = false
} }
for (i in new .. new + 2) { for (i in new .. new + 2) {
val row = getSlotsRow(i) val row = getInventorySlotsRow(i)
row.visible = true row.visible = true
row.y = (i - new) * AbstractSlotPanel.SIZE row.y = (i - new) * AbstractSlotPanel.SIZE
row.parent = mainInventoryLine row.parent = mainInventoryLine
@ -83,7 +52,7 @@ class ExoSuitInventoryScreen(menu: ExoSuitInventoryMenu) : MatteryScreen<ExoSuit
mainInventoryLine.dock = Dock.BOTTOM mainInventoryLine.dock = Dock.BOTTOM
for (slot in menu.hotbarSlots) { for (slot in menu.playerHotbarSlots) {
val panel = SlotPanel(this, toolbeltLine, slot) val panel = SlotPanel(this, toolbeltLine, slot)
panel.dock = Dock.LEFT panel.dock = Dock.LEFT
} }
@ -92,7 +61,7 @@ class ExoSuitInventoryScreen(menu: ExoSuitInventoryMenu) : MatteryScreen<ExoSuit
offhand.dock = Dock.RIGHT offhand.dock = Dock.RIGHT
for (i in scrollPanel.scroll .. scrollPanel.scroll + 2) { for (i in scrollPanel.scroll .. scrollPanel.scroll + 2) {
getSlotsRow(i).also { getInventorySlotsRow(i).also {
it.parent = mainInventoryLine it.parent = mainInventoryLine
it.y = AbstractSlotPanel.SIZE * (i - scrollPanel.scroll) it.y = AbstractSlotPanel.SIZE * (i - scrollPanel.scroll)
} }

View File

@ -8,13 +8,14 @@ import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
import ru.dbotthepony.mc.otm.client.render.Widgets8 import ru.dbotthepony.mc.otm.client.render.Widgets8
import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
import ru.dbotthepony.mc.otm.core.equalDownDivision import ru.dbotthepony.mc.otm.client.screen.widget.TallHorizontalPowerGaugePanel
import ru.dbotthepony.mc.otm.core.maxScrollDivision
import ru.dbotthepony.mc.otm.core.formatReadableNumber import ru.dbotthepony.mc.otm.core.formatReadableNumber
import ru.dbotthepony.mc.otm.core.formatSiComponent import ru.dbotthepony.mc.otm.core.formatSiComponent
import ru.dbotthepony.mc.otm.menu.ItemMonitorMenu import ru.dbotthepony.mc.otm.menu.ItemMonitorMenu
@ -24,7 +25,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
MatteryScreen<ItemMonitorMenu>(menu, inventory, title) { MatteryScreen<ItemMonitorMenu>(menu, inventory, title) {
override fun makeMainFrame(): FramePanel { override fun makeMainFrame(): FramePanel {
val frame = FramePanel(this@ItemMonitorScreen, null, 0f, 0f, FRAME_WIDTH, FRAME_HEIGHT, getTitle()) val frame = FramePanel(this@ItemMonitorScreen, null, 0f, 0f, 1f, 1f, getTitle())
val topPanel = EditablePanel(this, frame) val topPanel = EditablePanel(this, frame)
topPanel.height = ITEM_GRID_HEIGHT * 18f topPanel.height = ITEM_GRID_HEIGHT * 18f
@ -35,11 +36,13 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
bottomPanel.dock = Dock.TOP bottomPanel.dock = Dock.TOP
bottomPanel.setDockMargin(top = 6f) bottomPanel.setDockMargin(top = 6f)
frame.height = topPanel.height + bottomPanel.height + frame.dockPadding.top + frame.dockPadding.bottom + 6f frame.height = topPanel.height + bottomPanel.height + frame.dockPadding.top + frame.dockPadding.bottom + 26f
frame.width = 178f + frame.dockPadding.left + frame.dockPadding.right frame.width = 178f + frame.dockPadding.left + frame.dockPadding.right
val viewScrollBar = ContinuousScrollBarPanel(this, topPanel, 28f + ITEM_GRID_WIDTH * 18f + 2f, 16f, ITEM_GRID_HEIGHT * 18f) val viewScrollBar = DiscreteScrollBarPanel(this, topPanel,
viewScrollBar.setupRowMultiplier { equalDownDivision(menu.networkedItemView.itemCount, ITEM_GRID_WIDTH) } { maxScrollDivision(menu.networkedItemView.itemCount, ITEM_GRID_WIDTH) },
{ _, _, _ -> },
28f + ITEM_GRID_WIDTH * 18f + 2f, 16f, ITEM_GRID_HEIGHT * 18f)
viewScrollBar.dock = Dock.RIGHT viewScrollBar.dock = Dock.RIGHT
viewScrollBar.setDockMargin(left = 2f) viewScrollBar.setDockMargin(left = 2f)
@ -49,7 +52,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
for (i in 0 until ITEM_GRID_WIDTH * ITEM_GRID_HEIGHT) { for (i in 0 until ITEM_GRID_WIDTH * ITEM_GRID_HEIGHT) {
object : AbstractSlotPanel(this@ItemMonitorScreen, gridPanel) { object : AbstractSlotPanel(this@ItemMonitorScreen, gridPanel) {
private val index get() = i + viewScrollBar.getScroll(equalDownDivision(menu.networkedItemView.itemCount, ITEM_GRID_WIDTH)) * ITEM_GRID_WIDTH private val index get() = i + viewScrollBar.scroll * ITEM_GRID_WIDTH
override fun getItemStack(): ItemStack { override fun getItemStack(): ItemStack {
return menu.networkedItemView.sortedView.getOrNull(index)?.stack?.item ?: ItemStack.EMPTY return menu.networkedItemView.sortedView.getOrNull(index)?.stack?.item ?: ItemStack.EMPTY
@ -116,7 +119,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
arrowAndButtons.dock = Dock.LEFT arrowAndButtons.dock = Dock.LEFT
arrowAndButtons.setDockMargin(left = 4f) arrowAndButtons.setDockMargin(left = 4f)
val arrowLineTop = EditablePanel(this, arrowAndButtons, y = 0f, height = 8f, width = arrowAndButtons.width) EditablePanel(this, arrowAndButtons, y = 0f, height = 8f, width = arrowAndButtons.width)
val arrowLine = EditablePanel(this, arrowAndButtons, y = 38f, height = 8f, width = arrowAndButtons.width) val arrowLine = EditablePanel(this, arrowAndButtons, y = 38f, height = 8f, width = arrowAndButtons.width)
@ -168,7 +171,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
craftingHistory.dock = Dock.LEFT craftingHistory.dock = Dock.LEFT
craftingHistory.setDockMargin(left = 4f) craftingHistory.setDockMargin(left = 4f)
val craftingHistoryScroll = ContinuousScrollBarPanel(this, bottomPanel, 0f, 0f, 0f) val craftingHistoryScroll = DiscreteScrollBarPanel(this, bottomPanel, { 0 }, { _, _, _ -> })
craftingHistoryScroll.dock = Dock.LEFT craftingHistoryScroll.dock = Dock.LEFT
craftingHistoryScroll.setDockMargin(left = 2f) craftingHistoryScroll.setDockMargin(left = 2f)
@ -184,13 +187,23 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
} }
} }
val bottomStrip = EditablePanel(this, frame, height = AbstractSlotPanel.SIZE)
bottomStrip.dock = Dock.BOTTOM
BatterySlotPanel(this, bottomStrip, menu.batterySlot).also {
it.dock = Dock.LEFT
it.dockRight = 3f
}
TallHorizontalPowerGaugePanel(this, bottomStrip, menu.powerWidget).also {
it.dock = Dock.FILL
it.dockResize = DockResizeMode.NONE
}
return frame return frame
} }
companion object { companion object {
const val FRAME_WIDTH = 240f
const val FRAME_HEIGHT = 210f
const val ITEM_GRID_WIDTH = 9 const val ITEM_GRID_WIDTH = 9
const val ITEM_GRID_HEIGHT = 5 const val ITEM_GRID_HEIGHT = 5

View File

@ -2,7 +2,7 @@ package ru.dbotthepony.mc.otm.client.screen
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel

View File

@ -0,0 +1,295 @@
package ru.dbotthepony.mc.otm.client.screen
import net.minecraft.ChatFormatting
import net.minecraft.client.gui.components.EditBox
import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.capability.matter.IPatternState
import ru.dbotthepony.mc.otm.capability.matter.IReplicationTask
import ru.dbotthepony.mc.otm.capability.matter.PatternState
import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.maxScrollDivision
import ru.dbotthepony.mc.otm.menu.MatterPanelMenu
import ru.dbotthepony.mc.otm.menu.ReplicationRequestPacket
import ru.dbotthepony.mc.otm.network.MenuNetworkChannel
class MatterPanelScreen(
menu: MatterPanelMenu,
inventory: Inventory,
title: Component
) : MatteryScreen<MatterPanelMenu>(menu, inventory, title) {
override fun makeMainFrame(): FramePanel {
var isPatternView = true
val frame = FramePanel.padded(this, null, GRID_WIDTH * AbstractSlotPanel.SIZE + ScrollBarConstants.WIDTH + 4f, GRID_HEIGHT * AbstractSlotPanel.SIZE, title)
val scrollBar = DiscreteScrollBarPanel(this, frame, {
if (isPatternView) {
maxScrollDivision(menu.patterns.size, GRID_WIDTH)
} else {
maxScrollDivision(menu.tasks.size, GRID_WIDTH)
}
}, { _, _, _ -> })
scrollBar.dock = Dock.RIGHT
frame.addTab(FramePanel.Position.TOP, open = { isPatternView = true })
frame.addTab(FramePanel.Position.TOP, open = { isPatternView = false })
val canvas = object : EditablePanel(this@MatterPanelScreen, frame, width = GRID_WIDTH * AbstractSlotPanel.SIZE) {
init {
dock = Dock.LEFT
}
override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
return scrollBar.mouseScrolledInner(x, y, scroll)
}
}
for (row in 0 until GRID_HEIGHT) {
val rowCanvas = object : EditablePanel(this@MatterPanelScreen, canvas, height = AbstractSlotPanel.SIZE) {
init {
dock = Dock.TOP
}
override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
return false
}
}
for (i in 0 until GRID_WIDTH) {
object : AbstractSlotPanel(this@MatterPanelScreen, rowCanvas) {
init {
dock = Dock.LEFT
}
private val index: Int get() = (scrollBar.scroll + row) * GRID_WIDTH + i
override fun getItemStack(): ItemStack {
if (isPatternView) {
return menu.patterns.getOrNull(index)?.stack() ?: ItemStack.EMPTY
} else {
return menu.tasks.getOrNull(index)?.let { it.stack(it.required + it.inProgress) } ?: ItemStack.EMPTY
}
}
override fun getItemStackTooltip(stack: ItemStack): List<Component> {
val list = super.getItemStackTooltip(stack).toMutableList()
if (isPatternView) {
menu.patterns.getOrNull(index)?.let {
list.add(TranslatableComponent(
"otm.item.pattern.research",
String.format("%.2f", it.researchPercent * 100.0)
).withStyle(ChatFormatting.AQUA)) }
} else {
menu.tasks.getOrNull(index)?.let {
list.add(TranslatableComponent("otm.gui.matter_task.total", it.total).withStyle(ChatFormatting.GRAY))
list.add(TranslatableComponent("otm.gui.matter_task.required", it.required).withStyle(ChatFormatting.GRAY))
list.add(TranslatableComponent("otm.gui.matter_task.in_progress", it.inProgress).withStyle(ChatFormatting.GRAY))
list.add(TranslatableComponent("otm.gui.matter_task.finished", it.finished).withStyle(ChatFormatting.GRAY))
}
}
return list
}
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
if (isPatternView) {
menu.patterns.getOrNull(index)?.let(this@MatterPanelScreen::openPattern)
} else {
menu.tasks.getOrNull(index)?.let(this@MatterPanelScreen::openTask)
}
return true
}
override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
return false
}
}
}
}
return frame
}
private fun openTask(task: IReplicationTask<*>) {
val frame = FramePanel.padded(this, null, 170f, 20f, TranslatableComponent("otm.container.matter_panel.task"))
object : AbstractSlotPanel(this@MatterPanelScreen, frame) {
init {
dock = Dock.LEFT
}
override fun getItemStack(): ItemStack {
return menu.tasks.firstOrNull { it.id == task.id }?.let { it.stack((it.required + it.inProgress).coerceAtLeast(1)) } ?: task.stack((task.required + task.inProgress).coerceAtLeast(1))
}
override fun tick() {
super.tick()
if (!menu.tasks.any { it.id == task.id }) {
frame.remove()
}
}
}
ButtonPanel(this@MatterPanelScreen, frame, width = 40f, label = TranslatableComponent("otm.container.matter_panel.close"), onPress = frame::remove).also {
it.dock = Dock.RIGHT
it.dockLeft = 2f
}
ButtonPanel(this@MatterPanelScreen, frame, width = 80f, label = TranslatableComponent("otm.container.matter_panel.cancel_task"), onPress = {
menu.requestTaskCancel(task.id)
frame.remove()
}).also {
it.dock = Dock.RIGHT
it.dockLeft = 2f
}
addPanel(frame)
popup(frame)
frame.toScreenCenter()
}
private fun openPattern(pattern: IPatternState) {
val frame = FramePanel.padded(this, null, 213f, (ButtonPanel.HEIGHT + 3f) * 4f, TranslatableComponent("otm.container.matter_panel.task"))
val rowTop = EditablePanel(this, frame, height = ButtonPanel.HEIGHT)
val rowInput = EditablePanel(this, frame, height = ButtonPanel.HEIGHT)
val rowBottom = EditablePanel(this, frame, height = ButtonPanel.HEIGHT)
val rowControls = EditablePanel(this, frame, height = ButtonPanel.HEIGHT)
rowTop.dock = Dock.TOP
rowTop.dockTop = 3f
rowInput.dock = Dock.TOP
rowInput.dockTop = 3f
rowBottom.dock = Dock.TOP
rowBottom.dockTop = 3f
rowControls.dock = Dock.TOP
rowControls.dockTop = 3f
object : AbstractSlotPanel(this@MatterPanelScreen, rowInput) {
init {
dock = Dock.LEFT
dockRight = 2f
}
override fun getItemStack(): ItemStack {
return pattern.stack()
}
override fun getItemStackTooltip(stack: ItemStack): List<Component> {
return super.getItemStackTooltip(stack).toMutableList().also {
it.add(TranslatableComponent(
"otm.item.pattern.research",
String.format("%.2f", pattern.researchPercent * 100.0)
).withStyle(ChatFormatting.AQUA))
}
}
override fun tick() {
super.tick()
if (!menu.patterns.any { it.id == pattern.id }) {
frame.remove()
}
}
}
val input = object : EditBoxPanel(this@MatterPanelScreen, rowInput) {
init {
dock = Dock.FILL
}
override fun configureNew(widget: EditBox, recreation: Boolean) {
super.configureNew(widget, recreation)
widget.setMaxLength(6)
if (!recreation) {
widget.value = "1"
}
}
fun increase(amount: Int) {
var value = 1
try {
value = getOrCreateWidget().value.toInt()
} catch (_: NumberFormatException) {
}
if (value == 1 && amount > 0)
getOrCreateWidget().value = amount.toString()
else
getOrCreateWidget().value = 1.coerceAtLeast(99999.coerceAtMost(value + amount)).toString()
}
fun send() {
var value = 1
try {
value = getOrCreateWidget().value.toInt()
} catch (_: NumberFormatException) {
}
MenuNetworkChannel.sendToServer(ReplicationRequestPacket(pattern.id, value))
frame.remove()
}
}
ButtonPanel(this, rowTop, width = 40f, label = TranslatableComponent("otm.container.matter_panel.increase_by", 8), onPress = { input.increase(8) }).also {
it.dock = Dock.RIGHT
it.dockLeft = 2f
}
ButtonPanel(this, rowTop, width = 40f, label = TranslatableComponent("otm.container.matter_panel.increase_by", 64), onPress = { input.increase(64) }).also {
it.dock = Dock.RIGHT
it.dockLeft = 2f
}
ButtonPanel(this, rowTop, width = 40f, label = TranslatableComponent("otm.container.matter_panel.increase_by", 256), onPress = { input.increase(256) }).also {
it.dock = Dock.RIGHT
it.dockLeft = 2f
}
ButtonPanel(this, rowBottom, width = 40f, label = TranslatableComponent("otm.container.matter_panel.decrease_by", 8), onPress = { input.increase(-8) }).also {
it.dock = Dock.RIGHT
it.dockLeft = 2f
}
ButtonPanel(this, rowBottom, width = 40f, label = TranslatableComponent("otm.container.matter_panel.decrease_by", 64), onPress = { input.increase(-64) }).also {
it.dock = Dock.RIGHT
it.dockLeft = 2f
}
ButtonPanel(this, rowBottom, width = 40f, label = TranslatableComponent("otm.container.matter_panel.decrease_by", 256), onPress = { input.increase(-256) }).also {
it.dock = Dock.RIGHT
it.dockLeft = 2f
}
ButtonPanel(this, rowControls, width = 40f, label = TranslatableComponent("otm.container.matter_panel.cancel"), onPress = frame::remove).also {
it.dock = Dock.RIGHT
it.dockLeft = 2f
}
ButtonPanel(this, rowControls, width = 82f, label = TranslatableComponent("otm.container.matter_panel.send"), onPress = input::send).also {
it.dock = Dock.RIGHT
it.dockLeft = 2f
}
addPanel(frame)
popup(frame)
frame.toScreenCenter()
}
companion object {
const val GRID_HEIGHT = 8
const val GRID_WIDTH = 9
}
}

View File

@ -2,6 +2,8 @@ package ru.dbotthepony.mc.otm.client.screen
import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack import com.mojang.blaze3d.vertex.PoseStack
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction
import net.minecraft.ChatFormatting import net.minecraft.ChatFormatting
import net.minecraft.client.gui.Font import net.minecraft.client.gui.Font
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
@ -14,9 +16,8 @@ import net.minecraftforge.client.event.ContainerScreenEvent.Render.Foreground
import net.minecraftforge.common.MinecraftForge import net.minecraftforge.common.MinecraftForge
import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11
import org.lwjgl.opengl.GL13 import org.lwjgl.opengl.GL13
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.client.screen.panels.SlotPanel
import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.MatteryMenu
/** /**
@ -50,14 +51,106 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
val quickCraftingType get() = quickCraftingType val quickCraftingType get() = quickCraftingType
val isQuickCrafting get() = isQuickCrafting val isQuickCrafting get() = isQuickCrafting
private val inventorySlotsRows = Int2ObjectAVLTreeMap<EditablePanel>()
init { init {
if (menu.playerInventorySlots.isNotEmpty() && menu.autoCreateInventoryFrame) { if (menu.playerInventorySlots.isNotEmpty() && menu.autoCreateInventoryFrame) {
if (menu.playerExoSuitSlots.isEmpty()) {
inventoryFrame = FramePanel(this, null, 0f, 0f, INVENTORY_FRAME_WIDTH, INVENTORY_FRAME_HEIGHT, inventory.displayName).also(this::addPanel) inventoryFrame = FramePanel(this, null, 0f, 0f, INVENTORY_FRAME_WIDTH, INVENTORY_FRAME_HEIGHT, inventory.displayName).also(this::addPanel)
for (slot in menu.playerInventorySlots) { val hotbarStrip = EditablePanel(this, inventoryFrame, height = AbstractSlotPanel.SIZE)
SlotPanel(this, inventoryFrame, slot, slot.x.toFloat(), slot.y.toFloat()) hotbarStrip.dock = Dock.BOTTOM
for (slot in menu.playerHotbarSlots) {
SlotPanel(this, hotbarStrip, slot).also { it.dock = Dock.LEFT }
}
for (i in 0 .. 2) {
getInventorySlotsRow(i).also {
it.parent = inventoryFrame
it.y = i * AbstractSlotPanel.SIZE
} }
} }
} else {
inventoryFrame = FramePanel(this, null, 0f, 0f, INVENTORY_FRAME_WIDTH_EXTENDED, INVENTORY_FRAME_HEIGHT, inventory.displayName).also(this::addPanel)
var slotListCanvas: EditablePanel? = null
val scrollbar = DiscreteScrollBarPanel(this, inventoryFrame, { ((menu.playerCombinedInventorySlots.size - 27) + 8) / 9 }, {
_, old, new ->
for (i in old .. old + 2) {
getInventorySlotsRow(i).visible = false
}
for (i in new .. new + 2) {
getInventorySlotsRow(i).also {
it.visible = true
it.parent = slotListCanvas
it.y = (i - new) * AbstractSlotPanel.SIZE
}
}
menu.ply.matteryPlayer?.exoSuitMenu?.lastScroll = new
})
slotListCanvas = object : EditablePanel(this@MatteryScreen, inventoryFrame, height = AbstractSlotPanel.SIZE * 3f) {
override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
scrollbar.mouseScrolledInner(x, y, scroll)
return true
}
}
slotListCanvas.dock = Dock.TOP
val hotbarStrip = EditablePanel(this, inventoryFrame, height = AbstractSlotPanel.SIZE)
hotbarStrip.dock = Dock.BOTTOM
for (slot in menu.playerHotbarSlots) {
SlotPanel(this, hotbarStrip, slot).also { it.dock = Dock.LEFT }
}
scrollbar.parent = slotListCanvas
scrollbar.dock = Dock.RIGHT
scrollbar.scroll = menu.ply.matteryPlayer?.exoSuitMenu?.lastScroll ?: 0
for (i in scrollbar.scroll .. scrollbar.scroll + 2) {
getInventorySlotsRow(i).also {
it.parent = slotListCanvas
it.y = (i - scrollbar.scroll) * AbstractSlotPanel.SIZE
}
}
}
}
}
protected fun getInventorySlotsRow(index: Int): EditablePanel {
return inventorySlotsRows.computeIfAbsent(index, Int2ObjectFunction {
val canvas = object : EditablePanel(this@MatteryScreen, null, width = AbstractSlotPanel.SIZE * 9f, height = AbstractSlotPanel.SIZE) {
override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
return false
}
}
val offset = it * 9
if (menu.playerCombinedInventorySlots.size <= offset) {
return@Int2ObjectFunction canvas
}
for (i in 0 .. (8).coerceAtMost(menu.playerCombinedInventorySlots.size - offset - 1)) {
val slot = object : SlotPanel<Slot>(this@MatteryScreen, canvas, menu.playerCombinedInventorySlots[offset + i]) {
override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
return false
}
}
slot.dock = Dock.LEFT
}
return@Int2ObjectFunction canvas
})
} }
override fun init() { override fun init() {
@ -102,7 +195,7 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
require(indexOf != -1) { "No such panel $panel" } require(indexOf != -1) { "No such panel $panel" }
if (indexOf == panels.size - 1) { if (indexOf == 0) {
return return
} }
@ -354,10 +447,13 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
} }
companion object { companion object {
const val DEFAULT_FRAME_WIDTH = 18f * 9f + 16f const val DEFAULT_FRAME_WIDTH = AbstractSlotPanel.SIZE * 9f + 16f
const val DEFAULT_FRAME_HEIGHT = 100f const val DEFAULT_FRAME_HEIGHT = 100f
const val INVENTORY_FRAME_WIDTH = DEFAULT_FRAME_WIDTH const val INVENTORY_FRAME_WIDTH = DEFAULT_FRAME_WIDTH
const val INVENTORY_FRAME_HEIGHT = 3f * 18f + 18f + 24f const val INVENTORY_FRAME_WIDTH_EXTENDED = DEFAULT_FRAME_WIDTH + ScrollBarConstants.WIDTH + 2f
const val INVENTORY_FRAME_HEIGHT = 3f * AbstractSlotPanel.SIZE + AbstractSlotPanel.SIZE + 24f
const val GAUGE_TOP_WITH_SLOT = 17f const val GAUGE_TOP_WITH_SLOT = 17f
const val GAUGE_TOP_WITHOUT_SLOT = 26f const val GAUGE_TOP_WITHOUT_SLOT = 26f
const val SLOT_TOP_UNDER_GAUGE = 70f const val SLOT_TOP_UNDER_GAUGE = 70f

View File

@ -2,9 +2,8 @@ package ru.dbotthepony.mc.otm.client.screen
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel
import ru.dbotthepony.mc.otm.menu.StorageBusMenu import ru.dbotthepony.mc.otm.menu.StorageBusMenu

View File

@ -2,9 +2,8 @@ package ru.dbotthepony.mc.otm.client.screen
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel
import ru.dbotthepony.mc.otm.menu.StorageExporterMenu import ru.dbotthepony.mc.otm.menu.StorageExporterMenu

View File

@ -2,9 +2,8 @@ package ru.dbotthepony.mc.otm.client.screen
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel
import ru.dbotthepony.mc.otm.menu.StorageImporterMenu import ru.dbotthepony.mc.otm.menu.StorageImporterMenu

View File

@ -2,10 +2,9 @@ package ru.dbotthepony.mc.otm.client.screen
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.HorizontalPowerGaugePanel
import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel
import ru.dbotthepony.mc.otm.core.formatPower import ru.dbotthepony.mc.otm.core.formatPower
import ru.dbotthepony.mc.otm.menu.StoragePowerSupplierMenu import ru.dbotthepony.mc.otm.menu.StoragePowerSupplierMenu
@ -13,12 +12,32 @@ import ru.dbotthepony.mc.otm.menu.StoragePowerSupplierMenu
class StoragePowerSupplierScreen(menu: StoragePowerSupplierMenu, inventory: Inventory, title: Component) : class StoragePowerSupplierScreen(menu: StoragePowerSupplierMenu, inventory: Inventory, title: Component) :
MatteryScreen<StoragePowerSupplierMenu>(menu, inventory, title) { MatteryScreen<StoragePowerSupplierMenu>(menu, inventory, title) {
override fun makeMainFrame(): FramePanel { override fun makeMainFrame(): FramePanel {
val frame = super.makeMainFrame()!! val frame = FramePanel(this, width = 200f, height = 60f, title)
WidePowerGaugePanel(this, frame, menu.powerWidget, LEFT_MARGIN, GAUGE_TOP_WITH_SLOT) HorizontalPowerGaugePanel(this, frame, menu.powerWidget).also {
BatterySlotPanel(this, frame, menu.batterySlot, LEFT_MARGIN, SLOT_TOP_UNDER_GAUGE) it.dock = Dock.BOTTOM
it.dockResize = DockResizeMode.NONE
}
val topStrip = EditablePanel(this, frame, height = AbstractSlotPanel.SIZE)
topStrip.dock = Dock.TOP
topStrip.dockTop = 3f
BatterySlotPanel(this, topStrip, menu.batterySlot).also {
it.dock = Dock.LEFT
it.dockRight = 3f
}
val labels = EditablePanel(this, topStrip)
labels.dock = Dock.FILL
object : Label(this@StoragePowerSupplierScreen, labels) {
init {
dock = Dock.TOP
}
object : Label(this@StoragePowerSupplierScreen, frame, 28f, 17f, width = 140f) {
override fun tick() { override fun tick() {
super.tick() super.tick()
@ -29,6 +48,21 @@ class StoragePowerSupplierScreen(menu: StoragePowerSupplierMenu, inventory: Inve
} }
} }
object : Label(this@StoragePowerSupplierScreen, labels) {
init {
dock = Dock.TOP
}
override fun tick() {
super.tick()
text = TranslatableComponent(
"otm.gui.power_supplier.active_nodes",
menu.activeNodes
)
}
}
return frame return frame
} }
} }

View File

@ -23,9 +23,8 @@ abstract class AbstractSlotPanel @JvmOverloads constructor(
) : EditablePanel( ) : EditablePanel(
screen, parent, x, y, width, height screen, parent, x, y, width, height
) { ) {
protected open fun renderSlotBackground(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float) { protected open fun renderSlotBackground(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {
RenderSystem.setShaderTexture(0, WidgetLocation.WIDGETS) SLOT_BACKGROUND.render(stack, width = width, height = height)
drawTexturedRectAuto(stack, 0f, 0f, 18f, 18f, 0f, 96f, 256f, 256f)
} }
protected open fun renderRegular(stack: PoseStack, itemstack: ItemStack, count_override: String? = null) { protected open fun renderRegular(stack: PoseStack, itemstack: ItemStack, count_override: String? = null) {
@ -119,10 +118,9 @@ abstract class AbstractSlotPanel @JvmOverloads constructor(
} }
companion object { companion object {
@JvmField
val SLOT_HIGHLIGHT = RGBAColor(255, 255, 255, 100) val SLOT_HIGHLIGHT = RGBAColor(255, 255, 255, 100)
@JvmField
val SLOT_HIGHLIGHT_DRAG = RGBAColor(200, 200, 200, 150) val SLOT_HIGHLIGHT_DRAG = RGBAColor(200, 200, 200, 150)
const val SIZE = 18f const val SIZE = 18f
val SLOT_BACKGROUND = WidgetLocation.WIDGETS.element(0f, 0f, SIZE, SIZE)
} }
} }

View File

@ -5,15 +5,13 @@ import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.ChatFormatting import net.minecraft.ChatFormatting
import net.minecraft.client.gui.components.Button import net.minecraft.client.gui.components.Button
import net.minecraft.client.gui.components.Button.OnPress import net.minecraft.client.gui.components.Button.OnPress
import net.minecraft.client.resources.sounds.SimpleSoundInstance
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.sounds.SoundEvents import ru.dbotthepony.mc.otm.client.playGuiClickSound
import ru.dbotthepony.mc.otm.TextComponent import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.render.* import ru.dbotthepony.mc.otm.client.render.*
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.next import ru.dbotthepony.mc.otm.core.next
import ru.dbotthepony.mc.otm.prev import ru.dbotthepony.mc.otm.core.prev
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.reflect.KMutableProperty0 import kotlin.reflect.KMutableProperty0
@ -24,10 +22,22 @@ open class ButtonPanel(
x: Float = 0f, x: Float = 0f,
y: Float = 0f, y: Float = 0f,
width: Float = 40f, width: Float = 40f,
height: Float = 20f, height: Float = HEIGHT,
label: Component label: Component
) : MinecraftWidgetPanel<Button>(screen, parent, x, y, width, height) { ) : MinecraftWidgetPanel<Button>(screen, parent, x, y, width, height) {
constructor(screen: MatteryScreen<*>, parent: EditablePanel?, label: Component) : this(screen, parent, x = 0f, label = label) constructor(screen: MatteryScreen<*>, parent: EditablePanel?, label: Component) : this(screen, parent, x = 0f, label = label)
constructor(
screen: MatteryScreen<*>,
parent: EditablePanel?,
x: Float = 0f,
y: Float = 0f,
width: Float = 40f,
height: Float = HEIGHT,
label: Component,
onPress: Runnable
) : this(screen, parent, x, y, width, height, label) {
this.callback = onPress
}
var label = label var label = label
set(value) { set(value) {
@ -55,6 +65,10 @@ open class ButtonPanel(
protected open fun onPress() { protected open fun onPress() {
callback?.run() callback?.run()
} }
companion object {
const val HEIGHT = 20f
}
} }
@Suppress("PropertyName") @Suppress("PropertyName")
@ -105,7 +119,7 @@ abstract class SquareButtonPanel(
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean { override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
if (!isDisabled) { if (!isDisabled) {
if (!pressed) { if (!pressed) {
minecraft.soundManager.play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0f)) playGuiClickSound()
} }
pressed = true pressed = true

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