From b87a36caa4fe959562f5305949b34dffbcd10e48 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Mon, 22 Mar 2021 22:01:33 -0400 Subject: [PATCH] Add TechReborn plugin --- build.gradle | 4 +- plugin/techreborn/build.gradle | 24 ++++++ plugin/techreborn/gradle.properties | 4 + .../phycon/plugin/techreborn/PhyConTR.kt | 31 +++++++ .../plugin/techreborn/StorageUnitWrapper.kt | 81 +++++++++++++++++++ .../src/main/resources/fabric.mod.json | 38 +++++++++ settings.gradle | 1 + .../networking/C2STerminalRequestItem.kt | 8 +- .../S2CTerminalUpdateDisplayedItems.kt | 6 +- .../shadowfacts/phycon/util/PacketByteBuf.kt | 37 +++++++++ 10 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 plugin/techreborn/build.gradle create mode 100644 plugin/techreborn/gradle.properties create mode 100644 plugin/techreborn/src/main/kotlin/net/shadowfacts/phycon/plugin/techreborn/PhyConTR.kt create mode 100644 plugin/techreborn/src/main/kotlin/net/shadowfacts/phycon/plugin/techreborn/StorageUnitWrapper.kt create mode 100644 plugin/techreborn/src/main/resources/fabric.mod.json create mode 100644 src/main/kotlin/net/shadowfacts/phycon/util/PacketByteBuf.kt diff --git a/build.gradle b/build.gradle index 908cb37..11b06a2 100644 --- a/build.gradle +++ b/build.gradle @@ -74,7 +74,7 @@ repositories { dependencies { // PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. // You may need to force-disable transitiveness on them. - modImplementation "alexiil.mc.lib:libblockattributes-all:${project.libblockattributes_version}" + modCompile "alexiil.mc.lib:libblockattributes-all:${project.libblockattributes_version}" include "alexiil.mc.lib:libblockattributes-core:${project.libblockattributes_version}" include "alexiil.mc.lib:libblockattributes-items:${project.libblockattributes_version}" @@ -85,6 +85,8 @@ dependencies { include project(":plugin:mousewheelie") runtimeOnly project(":plugin:rei") include project(":plugin:rei") + runtimeOnly project(":plugin:techreborn") + include project(":plugin:techreborn") modRuntime("io.github.cottonmc:cotton-resources:${project.cotton_resources_version}") { exclude group: "net.fabricmc.fabric-api" diff --git a/plugin/techreborn/build.gradle b/plugin/techreborn/build.gradle new file mode 100644 index 0000000..c14e6a4 --- /dev/null +++ b/plugin/techreborn/build.gradle @@ -0,0 +1,24 @@ +plugins { + id "fabric-loom" + id "org.jetbrains.kotlin.jvm" +} + +archivesBaseName = project.archives_base_name +version = project.mod_version +group = project.maven_group + +repositories { + maven { + url = "https://maven.modmuss50.me/" + } + jcenter() +} + +dependencies { + implementation project(":") + + modImplementation("TechReborn:TechReborn-1.16:${project.techreborn_version}") { + exclude group: "net.fabricmc.fabric-api" + } +} + diff --git a/plugin/techreborn/gradle.properties b/plugin/techreborn/gradle.properties new file mode 100644 index 0000000..ce4dd7d --- /dev/null +++ b/plugin/techreborn/gradle.properties @@ -0,0 +1,4 @@ +archives_base_name=PhyCon-Plugin-TechReborn + +techreborn_version=3.8.2+build.222 + diff --git a/plugin/techreborn/src/main/kotlin/net/shadowfacts/phycon/plugin/techreborn/PhyConTR.kt b/plugin/techreborn/src/main/kotlin/net/shadowfacts/phycon/plugin/techreborn/PhyConTR.kt new file mode 100644 index 0000000..5958a5f --- /dev/null +++ b/plugin/techreborn/src/main/kotlin/net/shadowfacts/phycon/plugin/techreborn/PhyConTR.kt @@ -0,0 +1,31 @@ +package net.shadowfacts.phycon.plugin.techreborn + +import alexiil.mc.lib.attributes.AttributeList +import alexiil.mc.lib.attributes.AttributeSourceType +import alexiil.mc.lib.attributes.item.GroupedItemInv +import alexiil.mc.lib.attributes.item.ItemAttributes +import net.fabricmc.api.ModInitializer +import net.minecraft.block.BlockState +import net.minecraft.util.math.BlockPos +import net.minecraft.world.World +import techreborn.blockentity.storage.item.StorageUnitBaseBlockEntity +import techreborn.init.TRContent + +/** + * @author shadowfacts + */ +object PhyConTR: ModInitializer { + + override fun onInitialize() { + TRContent.StorageUnit.values().forEach { + ItemAttributes.GROUPED_INV.setBlockAdder(AttributeSourceType.COMPAT_WRAPPER, it.block, ::addStorageUnitGroupedInv) + } + } + + private fun addStorageUnitGroupedInv(world: World, pos: BlockPos, state: BlockState, to: AttributeList) { + (world.getBlockEntity(pos) as? StorageUnitBaseBlockEntity)?.also { su -> + to.offer(StorageUnitWrapper(su)) + } + } + +} diff --git a/plugin/techreborn/src/main/kotlin/net/shadowfacts/phycon/plugin/techreborn/StorageUnitWrapper.kt b/plugin/techreborn/src/main/kotlin/net/shadowfacts/phycon/plugin/techreborn/StorageUnitWrapper.kt new file mode 100644 index 0000000..84ad1d4 --- /dev/null +++ b/plugin/techreborn/src/main/kotlin/net/shadowfacts/phycon/plugin/techreborn/StorageUnitWrapper.kt @@ -0,0 +1,81 @@ +package net.shadowfacts.phycon.plugin.techreborn + +import alexiil.mc.lib.attributes.Simulation +import alexiil.mc.lib.attributes.item.GroupedItemInv +import alexiil.mc.lib.attributes.item.GroupedItemInvView +import alexiil.mc.lib.attributes.item.ItemStackCollections +import alexiil.mc.lib.attributes.item.ItemStackUtil +import alexiil.mc.lib.attributes.item.filter.ItemFilter +import net.minecraft.item.ItemStack +import net.shadowfacts.phycon.util.copyWithCount +import techreborn.blockentity.storage.item.StorageUnitBaseBlockEntity +import kotlin.math.min + +/** + * @author shadowfacts + */ +class StorageUnitWrapper( + val be: StorageUnitBaseBlockEntity, +): GroupedItemInv { + + override fun getStoredStacks(): Set { + val set = ItemStackCollections.set() + if (!be.storedStack.isEmpty) { + set.add(be.storedStack) + } + return set + } + + override fun getTotalCapacity(): Int { + return be.maxCapacity + } + + override fun getStatistics(filter: ItemFilter): GroupedItemInvView.ItemInvStatistic { + // todo: should spaceAddable really be zero? that's what SimpleGroupedItemInv does + return if (be.storedStack.isEmpty) { + GroupedItemInvView.ItemInvStatistic(filter, 0, 0, totalCapacity) + } else if (filter.matches(be.storedStack)) { + // don't use the storedAmount field, it's only used on the client for rendering + val amount = be.getStoredAmount() + GroupedItemInvView.ItemInvStatistic(filter, amount, 0, totalCapacity - amount) + } else { + GroupedItemInvView.ItemInvStatistic(filter, 0, 0, 0) + } + } + + override fun attemptInsertion(filter: ItemStack, simulation: Simulation): ItemStack { + if (simulation.isAction) { + return be.processInput(filter) + } + + if (be.storedStack.isEmpty) { + return ItemStack.EMPTY + } + + if (!ItemStackUtil.areEqualIgnoreAmounts(be.storedStack, filter)) { + return filter + } + + val availableCapacity = totalCapacity - be.getStoredAmount() + return if (availableCapacity >= filter.count) { + ItemStack.EMPTY + } else { + filter.copyWithCount(filter.count - availableCapacity) + } + } + + override fun attemptExtraction(filter: ItemFilter, maxAmount: Int, simulation: Simulation): ItemStack { + if (be.storedStack.isEmpty || !filter.matches(be.storedStack)) { + return ItemStack.EMPTY + } + + val extracted = min(maxAmount, be.getStoredAmount()) + + if (simulation.isAction) { + be.storedStack.decrement(extracted) + } + + return be.storedStack.copyWithCount(extracted) + } + +} diff --git a/plugin/techreborn/src/main/resources/fabric.mod.json b/plugin/techreborn/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..ad87bae --- /dev/null +++ b/plugin/techreborn/src/main/resources/fabric.mod.json @@ -0,0 +1,38 @@ +{ + "schemaVersion": 1, + "id": "phycon_techreborn", + "version": "${version}", + + "name": "PhyCon TechReborn Integration", + "description": "", + "authors": [ + "Shadowfacts" + ], + "contact": { + "homepage": "https://git.shadowfacts.net/minecraft/PhysicalConnectivity" + }, + "license": "LGPL-3.0", + "environment": "client", + "entrypoints": { + "main": [ + { + "adapter": "kotlin", + "value": "net.shadowfacts.phycon.plugin.techreborn.PhyConTR" + } + ] + }, + "mixins": [ + ], + "depends": { + "fabricloader": ">=0.4.0", + "fabric": "*", + "fabric-language-kotlin": ">=1.3.50", + "phycon": "*", + "techreborn": "*" + }, + + "custom": { + "modmenu:parent": "phycon" + } +} + diff --git a/settings.gradle b/settings.gradle index d0d36ac..91f2cfd 100644 --- a/settings.gradle +++ b/settings.gradle @@ -12,3 +12,4 @@ pluginManagement { include("kiwi-java") include("plugin:mousewheelie") include("plugin:rei") +include("plugin:techreborn") diff --git a/src/main/kotlin/net/shadowfacts/phycon/networking/C2STerminalRequestItem.kt b/src/main/kotlin/net/shadowfacts/phycon/networking/C2STerminalRequestItem.kt index 4a7442d..b9fca5d 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/networking/C2STerminalRequestItem.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/networking/C2STerminalRequestItem.kt @@ -15,6 +15,8 @@ import net.minecraft.util.registry.RegistryKey import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity import net.shadowfacts.phycon.util.copyWithCount +import net.shadowfacts.phycon.util.readItemStackWithoutCount +import net.shadowfacts.phycon.util.writeItemStackWithoutCount /** * @author shadowfacts @@ -28,10 +30,10 @@ object C2STerminalRequestItem: ServerReceiver { buf.writeIdentifier(terminal.world!!.registryKey.value) buf.writeBlockPos(terminal.pos) - // Force the count of the stack to be 1 before serializing for the network because + // Don't send the count of the fake stack when sending over the network because // PacketByteBuf serializes the stack count as a byte. Otherwise counts > 127 will result in // an overflow and be negative on the receiving side. - buf.writeItemStack(stack.copyWithCount(1)) + buf.writeItemStackWithoutCount(stack) buf.writeVarInt(amount) return ClientPlayNetworking.createC2SPacket(CHANNEL, buf) @@ -40,7 +42,7 @@ object C2STerminalRequestItem: ServerReceiver { override fun receive(server: MinecraftServer, player: ServerPlayerEntity, handler: ServerPlayNetworkHandler, buf: PacketByteBuf, responseSender: PacketSender) { val dimID = buf.readIdentifier() val pos = buf.readBlockPos() - val stack = buf.readItemStack() + val stack = buf.readItemStackWithoutCount() val amount = buf.readVarInt() server.execute { diff --git a/src/main/kotlin/net/shadowfacts/phycon/networking/S2CTerminalUpdateDisplayedItems.kt b/src/main/kotlin/net/shadowfacts/phycon/networking/S2CTerminalUpdateDisplayedItems.kt index 042d109..4a95ad2 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/networking/S2CTerminalUpdateDisplayedItems.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/networking/S2CTerminalUpdateDisplayedItems.kt @@ -10,6 +10,8 @@ import net.minecraft.network.PacketByteBuf import net.shadowfacts.phycon.block.terminal.TerminalBlockEntity import net.shadowfacts.phycon.block.terminal.TerminalScreenHandler import net.shadowfacts.phycon.util.SortMode +import net.shadowfacts.phycon.util.readItemStackWithoutCount +import net.shadowfacts.phycon.util.writeItemStackWithoutCount /** * @author shadowfacts @@ -25,7 +27,7 @@ object S2CTerminalUpdateDisplayedItems: ClientReceiver { buf.writeVarInt(entries.size) for (e in entries) { - buf.writeItemStack(e.stack) + buf.writeItemStackWithoutCount(e.stack) buf.writeVarInt(e.amount) } @@ -43,7 +45,7 @@ object S2CTerminalUpdateDisplayedItems: ClientReceiver { val entryCount = buf.readVarInt() val entries = ArrayList(entryCount) for (i in 0 until entryCount) { - entries.add(TerminalScreenHandler.Entry(buf.readItemStack(), buf.readVarInt())) + entries.add(TerminalScreenHandler.Entry(buf.readItemStackWithoutCount(), buf.readVarInt())) } val query = buf.readString() val sortMode = SortMode.values()[buf.readVarInt()] diff --git a/src/main/kotlin/net/shadowfacts/phycon/util/PacketByteBuf.kt b/src/main/kotlin/net/shadowfacts/phycon/util/PacketByteBuf.kt new file mode 100644 index 0000000..0bb691e --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/util/PacketByteBuf.kt @@ -0,0 +1,37 @@ +package net.shadowfacts.phycon.util + +import net.minecraft.item.Item +import net.minecraft.item.ItemStack +import net.minecraft.nbt.CompoundTag +import net.minecraft.network.PacketByteBuf + +/** + * @author shadowfacts + */ +fun PacketByteBuf.writeItemStackWithoutCount(stack: ItemStack) { + if (stack.isEmpty) { + writeBoolean(false) + } else { + writeBoolean(true) + writeVarInt(Item.getRawId(stack.item)) + val tag: CompoundTag? = + if (stack.item.isDamageable || stack.item.shouldSyncTagToClient()) { + stack.tag + } else { + null + } + writeCompoundTag(tag) + } +} + +fun PacketByteBuf.readItemStackWithoutCount(): ItemStack { + return if (!readBoolean()) { + ItemStack.EMPTY + } else { + val id = readVarInt() + val count = 1 + val stack = ItemStack(Item.byRawId(id), count) + stack.tag = readCompoundTag() + stack + } +}