diff options
Diffstat (limited to 'mod/src/main/kotlin')
88 files changed, 4324 insertions, 0 deletions
diff --git a/mod/src/main/kotlin/moe/nea/ledger/ConfigCommand.kt b/mod/src/main/kotlin/moe/nea/ledger/ConfigCommand.kt new file mode 100644 index 0000000..5b964c8 --- /dev/null +++ b/mod/src/main/kotlin/moe/nea/ledger/ConfigCommand.kt @@ -0,0 +1,31 @@ +package moe.nea.ledger + +import io.github.notenoughupdates.moulconfig.common.IMinecraft +import net.minecraft.command.CommandBase +import net.minecraft.command.ICommandSender + +class ConfigCommand : CommandBase() { + override fun canCommandSenderUseCommand(sender: ICommandSender?): Boolean { + return true + } + + override fun getCommandName(): String { + return "ledgerconfig" + } + + override fun getCommandUsage(sender: ICommandSender?): String { + return "" + } + + override fun processCommand(sender: ICommandSender?, args: Array<out String>) { + val editor = Ledger.managedConfig.getEditor() + editor.search(args.joinToString(" ")) + Ledger.runLater { + IMinecraft.instance.openWrappedScreen(editor) + } + } + + override fun getCommandAliases(): List<String> { + return listOf("moneyledger") + } +}
\ No newline at end of file diff --git a/mod/src/main/kotlin/moe/nea/ledger/DebouncedValue.kt b/mod/src/main/kotlin/moe/nea/ledger/DebouncedValue.kt new file mode 100644 index 0000000..66fba8d --- /dev/null +++ b/mod/src/main/kotlin/moe/nea/ledger/DebouncedValue.kt @@ -0,0 +1,38 @@ +package moe.nea.ledger + +import kotlin.time.Duration +import kotlin.time.Duration.Companion.nanoseconds +import kotlin.time.Duration.Companion.seconds + +class DebouncedValue<T>(private val value: T) { + companion object { + fun <T> farFuture(): DebouncedValue<T> { + val value = DebouncedValue(Unit) + value.take() + @Suppress("UNCHECKED_CAST") + return value as DebouncedValue<T> + } + } + + val lastSeenAt = System.nanoTime() + val age get() = (System.nanoTime() - lastSeenAt).nanoseconds + var taken = false + private set + + fun get(debounce: Duration): T? { + return if (!taken && age >= debounce) value + else null + } + + fun replace(): T? { + return consume(0.seconds) + } + + fun consume(debounce: Duration): T? { + return get(debounce)?.also { take() } + } + + fun take() { + taken = true + } +}
\ No newline at end of file diff --git a/mod/src/main/kotlin/moe/nea/ledger/DebugDataCommand.kt b/mod/src/main/kotlin/moe/nea/ledger/DebugDataCommand.kt new file mode 100644 index 0000000..bab0a78 --- /dev/null +++ b/mod/src/main/kotlin/moe/nea/ledger/DebugDataCommand.kt @@ -0,0 +1,34 @@ +package moe.nea.ledger + +import moe.nea.ledger.events.SupplyDebugInfo +import moe.nea.ledger.utils.di.Inject +import net.minecraft.command.CommandBase +import net.minecraft.command.ICommandSender +import net.minecraftforge.common.MinecraftForge + +class DebugDataCommand : CommandBase() { + + override fun canCommandSenderUseCommand(sender: ICommandSender?): Boolean { + return true + } + + override fun getCommandName(): String { + return "ledgerdebug" + } + + override fun getCommandUsage(sender: ICommandSender?): String { + return "" + } + + @Inject + lateinit var logger: LedgerLogger + + override fun processCommand(sender: ICommandSender?, args: Array<out String>?) { + val debugInfo = SupplyDebugInfo() + MinecraftForge.EVENT_BUS.post(debugInfo) + logger.printOut("Collected debug info:") + debugInfo.data.forEach { + logger.printOut("${it.first}: ${it.second}") + } + } +}
\ No newline at end of file diff --git a/mod/src/main/kotlin/moe/nea/ledger/DevUtil.kt b/mod/src/main/kotlin/moe/nea/ledger/DevUtil.kt new file mode 100644 index 0000000..d0dd653 --- /dev/null +++ b/mod/src/main/kotlin/moe/nea/ledger/DevUtil.kt @@ -0,0 +1,7 @@ +package moe.nea.ledger + +import net.minecraft.launchwrapper.Launch + +object DevUtil { + val isDevEnv = Launch.blackboard["fml.deobfuscatedEnvironment"] as Boolean +}
\ No newline at end of file diff --git a/mod/src/main/kotlin/moe/nea/ledger/ExpiringValue.kt b/mod/src/main/kotlin/moe/nea/ledger/ExpiringValue.kt new file mode 100644 index 0000000..b50b14e --- /dev/null +++ b/mod/src/main/kotlin/moe/nea/ledger/ExpiringValue.kt @@ -0,0 +1,30 @@ +package moe.nea.ledger + +import kotlin.time.Duration +import kotlin.time.Duration.Companion.nanoseconds + +class ExpiringValue<T>(private val value: T) { + val lastSeenAt: Long = System.nanoTime() + val age get() = (System.nanoTime() - lastSeenAt).nanoseconds + var taken = false + private set + + fun get(expiry: Duration): T? { + return if (!taken && age < expiry) value + else null + } + + companion object { + fun <T> empty(): ExpiringValue<T> { + val value = ExpiringValue(Unit) + value.take() + @Suppress("UNCHECKED_CAST") + return value as ExpiringValue<T> + } + } + + fun consume(expiry: Duration): T? = get(expiry)?.also { take() } + fun take() { + taken = true + } +}
\ No newline at end of file diff --git a/mod/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt b/mod/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt new file mode 100644 index 0000000..ff2c691 --- /dev/null +++ b/mod/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt @@ -0,0 +1,188 @@ +package moe.nea.ledger + +import moe.nea.ledger.events.BeforeGuiAction +import moe.nea.ledger.events.ExtraSupplyIdEvent +import moe.nea.ledger.events.RegistrationFinishedEvent +import moe.nea.ledger.events.SupplyDebugInfo +import moe.nea.ledger.gen.ItemIds +import moe.nea.ledger.modules.ExternalDataProvider +import net.minecraft.client.Minecraft +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraftforge.client.event.GuiScreenEvent +import net.minecraftforge.common.MinecraftForge +import net.minecraftforge.fml.common.eventhandler.EventPriority +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import org.lwjgl.input.Mouse + +class ItemIdProvider { + + @SubscribeEvent + fun onMouseInput(event: GuiScreenEvent.MouseInputEvent.Pre) { + if (Mouse.getEventButton() == -1) return + BeforeGuiAction(event.gui).post() + } + + @SubscribeEvent + fun onKeyInput(event: GuiScreenEvent.KeyboardInputEvent.Pre) { + BeforeGuiAction(event.gui).post() + } + + private val knownNames = mutableMapOf<String, ItemId>() + + fun createLookupTagFromDisplayName(itemName: String): String { + return itemName.unformattedString().trim().lowercase() + } + + fun saveKnownItem(itemName: String, itemId: ItemId) { + knownNames[createLookupTagFromDisplayName(itemName)] = itemId + } + + @SubscribeEvent + fun onDataLoaded(event: ExternalDataProvider.DataLoaded) { + event.provider.itemNames.forEach { (itemId, itemName) -> + saveKnownItem(itemName, ItemId(itemId)) + } + } + + @SubscribeEvent + fun onRegistrationFinished(event: RegistrationFinishedEvent) { + MinecraftForge.EVENT_BUS.post(ExtraSupplyIdEvent(::saveKnownItem)) + } + + @SubscribeEvent(priority = EventPriority.HIGH) + fun savePlayerInventoryIds(event: BeforeGuiAction) { + val player = Minecraft.getMinecraft().thePlayer ?: return + val inventory = player.inventory ?: return + inventory.mainInventory?.forEach { saveFromSlot(it) } + inventory.armorInventory?.forEach { saveFromSlot(it) } + } + + @SubscribeEvent + fun onDebugData(event: SupplyDebugInfo) { + event.record("knownItemNames", knownNames.size) + } + + fun saveFromSlot(stack: ItemStack?, preprocessName: (String) -> String = { it }) { + if (stack == null) return + val nbt = stack.tagCompound ?: NBTTagCompound() + val display = nbt.getCompoundTag("display") + var name = display.getString("Name").unformattedString() + name = preprocessName(name) + name = name.trim() + val id = stack.getInternalId() + if (id != null && name.isNotBlank()) { + saveKnownItem(name, id) + } + } + + @SubscribeEvent(priority = EventPriority.HIGH) + fun saveChestInventoryIds(event: BeforeGuiAction) { + val slots = event.chestSlots ?: return + val chestName = slots.lowerChestInventory.name.unformattedString() + val isOrderMenu = chestName == "Your Bazaar Orders" || chestName == "Co-op Bazaar Orders" + val preprocessor: (String) -> String = if (isOrderMenu) { + { it.removePrefix("BUY ").removePrefix("SELL ") } + } else { + { it } + } + slots.inventorySlots.forEach { + saveFromSlot(it?.stack, preprocessor) + } + } + + // TODO: make use of colour + fun findForName(name: String, fallbackToGenerated: Boolean = true): ItemId? { + var id = knownNames[createLookupTagFromDisplayName(name)] + if (id == null && fallbackToGenerated) { + id = generateName(name) + } + return id + } + + fun generateName(name: String): ItemId { + return ItemId(name.uppercase().replace(" ", "_")) + } + + private val coinRegex = "(?<amount>$SHORT_NUMBER_PATTERN) Coins?".toPattern() + private val stackedItemRegex = "(?<name>.*) x(?<count>$SHORT_NUMBER_PATTERN)".toPattern() + private val reverseStackedItemRegex = "(?<count>$SHORT_NUMBER_PATTERN)x (?<name>.*)".toPattern() |
