diff --git a/gradle.properties b/gradle.properties index bfaf34e..3f125a1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ org.gradle.jvmargs=-Xmx3G # Mod Properties mod_id = betterp2p -mod_version = 1.1.2 +mod_version = 1.2.0 mod_group = com.projecturanus.betterp2p # Minecraft & Forge diff --git a/src/main/java/com/projecturanus/betterp2p/BetterP2P.kt b/src/main/java/com/projecturanus/betterp2p/BetterP2P.kt index ced4869..53d9f23 100644 --- a/src/main/java/com/projecturanus/betterp2p/BetterP2P.kt +++ b/src/main/java/com/projecturanus/betterp2p/BetterP2P.kt @@ -15,5 +15,7 @@ object BetterP2P { fun preInit(event: FMLPreInitializationEvent) { logger = event.modLog ModNetwork.registerNetwork() + + } } diff --git a/src/main/java/com/projecturanus/betterp2p/client/gui/GuiBetterMemoryCard.kt b/src/main/java/com/projecturanus/betterp2p/client/gui/GuiBetterMemoryCard.kt index 9c2dc20..7061bf7 100644 --- a/src/main/java/com/projecturanus/betterp2p/client/gui/GuiBetterMemoryCard.kt +++ b/src/main/java/com/projecturanus/betterp2p/client/gui/GuiBetterMemoryCard.kt @@ -1,5 +1,6 @@ package com.projecturanus.betterp2p.client.gui +import com.projecturanus.betterp2p.BetterP2P import com.projecturanus.betterp2p.MODID import com.projecturanus.betterp2p.capability.MemoryInfo import com.projecturanus.betterp2p.client.ClientCache @@ -183,11 +184,11 @@ class GuiBetterMemoryCard(msg: S2CListP2P) : GuiScreen(), TextureBound { if (selectedIndex == -1) return when (mode) { BetterMemoryCardModes.INPUT -> { - println("Bind ${info.index} as input") + BetterP2P.logger.debug("Bind ${info.index} as input") ModNetwork.channel.sendToServer(C2SLinkP2P(info.index, selectedIndex)) } BetterMemoryCardModes.OUTPUT -> { - println("Bind ${info.index} as output") + BetterP2P.logger.debug("Bind ${info.index} as output") ModNetwork.channel.sendToServer(C2SLinkP2P(selectedIndex, info.index)) } BetterMemoryCardModes.COPY -> { diff --git a/src/main/java/com/projecturanus/betterp2p/config/BetterP2PConfig.kt b/src/main/java/com/projecturanus/betterp2p/config/BetterP2PConfig.kt new file mode 100644 index 0000000..80bc982 --- /dev/null +++ b/src/main/java/com/projecturanus/betterp2p/config/BetterP2PConfig.kt @@ -0,0 +1,16 @@ +package com.projecturanus.betterp2p.config + +import net.minecraftforge.common.config.Configuration + +object BetterP2PConfig { + val client = ClientConfig() + + fun loadConfig(config: Configuration) { + config.load() + client.autoRefresh = config.getBoolean("autoRefresh", "client", true, "Auto refresh the P2P status") + } + + class ClientConfig { + var autoRefresh: Boolean = true + } +} diff --git a/src/main/java/com/projecturanus/betterp2p/network/ServerLinkP2PHandler.kt b/src/main/java/com/projecturanus/betterp2p/network/ServerLinkP2PHandler.kt index c9f4d09..01ab224 100644 --- a/src/main/java/com/projecturanus/betterp2p/network/ServerLinkP2PHandler.kt +++ b/src/main/java/com/projecturanus/betterp2p/network/ServerLinkP2PHandler.kt @@ -3,18 +3,28 @@ package com.projecturanus.betterp2p.network import com.projecturanus.betterp2p.util.p2p.P2PCache import com.projecturanus.betterp2p.util.p2p.getInfo import com.projecturanus.betterp2p.util.p2p.linkP2P +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import net.minecraftforge.fml.common.network.simpleimpl.IMessage import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler import net.minecraftforge.fml.common.network.simpleimpl.MessageContext -class ServerLinkP2PHandler : IMessageHandler { - override fun onMessage(message: C2SLinkP2P, ctx: MessageContext): S2CRefreshInfo? { +class ServerLinkP2PHandler : IMessageHandler { + override fun onMessage(message: C2SLinkP2P, ctx: MessageContext): IMessage? { if (!P2PCache.statusMap.containsKey(ctx.serverHandler.player.uniqueID)) return null val status = P2PCache.statusMap[ctx.serverHandler.player.uniqueID]!! - val input = status.listP2P[message.input] - val output = status.listP2P[message.output] - if (linkP2P(ctx.serverHandler.player, input, output)) { - return S2CRefreshInfo(listOf(input.getInfo(message.input), output.getInfo(message.output))) + val result = linkP2P(ctx.serverHandler.player, message.input, message.output, status) + if (result != null) { + status.listP2P[message.input] = result.first + status.listP2P[message.output] = result.second + GlobalScope.launch { + ModNetwork.channel.sendTo(S2CRefreshInfo(listOf(result.first.getInfo(message.input), result.second.getInfo(message.output))), ctx.serverHandler.player) + // It takes time before a channel is assigned to the new tunnel + delay(2000) + ModNetwork.channel.sendTo(S2CRefreshInfo(listOf(result.first.getInfo(message.input), result.second.getInfo(message.output))), ctx.serverHandler.player) + } } return null } diff --git a/src/main/java/com/projecturanus/betterp2p/util/p2p/P2PCache.kt b/src/main/java/com/projecturanus/betterp2p/util/p2p/P2PCache.kt index 8dc67a6..4405855 100644 --- a/src/main/java/com/projecturanus/betterp2p/util/p2p/P2PCache.kt +++ b/src/main/java/com/projecturanus/betterp2p/util/p2p/P2PCache.kt @@ -6,5 +6,5 @@ import java.util.* * Cache P2P status for client to use */ object P2PCache { - val statusMap: MutableMap = Collections.synchronizedMap(WeakHashMap()) + val statusMap: MutableMap = Collections.synchronizedMap(WeakHashMap()) } diff --git a/src/main/java/com/projecturanus/betterp2p/util/p2p/P2PStatus.kt b/src/main/java/com/projecturanus/betterp2p/util/p2p/P2PStatus.kt index 6b00cdd..c7a15c9 100644 --- a/src/main/java/com/projecturanus/betterp2p/util/p2p/P2PStatus.kt +++ b/src/main/java/com/projecturanus/betterp2p/util/p2p/P2PStatus.kt @@ -7,5 +7,5 @@ import com.projecturanus.betterp2p.util.listTargetGridP2P import net.minecraft.entity.player.EntityPlayer class P2PStatus(player: EntityPlayer, val id: Int, val grid: IGrid, val targetP2P: PartP2PTunnel<*>? = null) { - val listP2P: List> = listTargetGridP2P(grid, player, targetP2P?.javaClass ?: PartP2PTunnelME::class.java) + val listP2P: MutableList> = listTargetGridP2P(grid, player, targetP2P?.javaClass ?: PartP2PTunnelME::class.java).toMutableList() } diff --git a/src/main/java/com/projecturanus/betterp2p/util/p2p/P2PUtil.kt b/src/main/java/com/projecturanus/betterp2p/util/p2p/P2PUtil.kt index fdfa41a..7760a28 100644 --- a/src/main/java/com/projecturanus/betterp2p/util/p2p/P2PUtil.kt +++ b/src/main/java/com/projecturanus/betterp2p/util/p2p/P2PUtil.kt @@ -1,51 +1,101 @@ package com.projecturanus.betterp2p.util.p2p import appeng.api.config.SecurityPermissions +import appeng.api.networking.IGrid +import appeng.api.networking.IGridConnection +import appeng.api.networking.IGridNode import appeng.api.networking.security.ISecurityGrid +import appeng.api.parts.IPart +import appeng.api.parts.PartItemStack import appeng.api.util.AEColor +import appeng.api.util.AEPartLocation +import appeng.me.GridAccessException +import appeng.me.GridNode import appeng.parts.p2p.PartP2PTunnel import appeng.util.Platform import com.projecturanus.betterp2p.network.P2PInfo import net.minecraft.entity.player.EntityPlayer +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound val PartP2PTunnel<*>.colorCode: Array get() = Platform.p2p().toColors(this.frequency) -fun linkP2P(player: EntityPlayer, input: PartP2PTunnel<*>, output: PartP2PTunnel<*>) : Boolean { - val grid = input.gridNode.grid +fun linkP2P(player: EntityPlayer, inputIndex: Int, outputIndex: Int, status: P2PStatus) : Pair, PartP2PTunnel<*>>? { + val input = status.listP2P[inputIndex] + val output = status.listP2P[outputIndex] + + val grid: IGrid? = input.gridNode?.grid if (grid is ISecurityGrid) { if (!grid.hasPermission(player, SecurityPermissions.BUILD)) { - return false + return null } } // TODO Change to exception if (input.javaClass != output.javaClass) { // Cannot pair two different type of P2P - return false + return null } if (input == output) { // Network loop - return false + return null } + var frequency = input.frequency val cache = input.proxy.p2P // TODO reduce changes if (input.frequency.toInt() == 0 || input.isOutput) { - cache.updateFreq(input, cache.newFrequency()) - input.onTunnelConfigChange() - output.onTunnelNetworkChange() - } - if (cache.getInput(input.frequency) != null) { - val originalInput = cache.getInput(input.frequency) - originalInput.outputProperty = false - originalInput.onTunnelConfigChange() - originalInput.onTunnelNetworkChange() - } - input.outputProperty = false - output.outputProperty = true - cache.updateFreq(output, input.frequency) - output.onTunnelConfigChange() - output.onTunnelNetworkChange() - return true + frequency = cache.newFrequency() + updateP2P(input, frequency, false) + } + if (cache.getInput(frequency) != null) { + val originalInput = cache.getInput(frequency) + if (originalInput != input) + updateP2P(originalInput, frequency, true) + } + + return updateP2P(input, frequency, false) to updateP2P(output, frequency, true) +} + +/** + * Due to Applied Energistics' limit + */ +fun updateP2P(tunnel: PartP2PTunnel<*>, frequency: Short, output: Boolean): PartP2PTunnel<*> { + tunnel.host.removePart(tunnel.side, true) + + val data = NBTTagCompound() + val p2pItem: ItemStack = tunnel.getItemStack(PartItemStack.WRENCH) + val type: String = p2pItem.translationKey + tunnel.outputProperty = output + + p2pItem.writeToNBT(data) + data.setShort("freq", frequency) + + val colors = Platform.p2p().toColors(frequency) + val colorCode = intArrayOf( + colors[0].ordinal, colors[0].ordinal, colors[1].ordinal, colors[1].ordinal, + colors[2].ordinal, colors[2].ordinal, colors[3].ordinal, colors[3].ordinal + ) + + data.setIntArray("colorCode", colorCode) + + val newType = ItemStack(data) + val dir: AEPartLocation = tunnel.host.addPart(newType, tunnel.side, null, null) + val newBus: IPart = tunnel.host.getPart(dir) + + if (newBus is PartP2PTunnel<*>) { + val newTunnel = newBus + newTunnel.outputProperty = output + try { + val p2p = newTunnel.proxy.p2P + p2p.updateFreq(newTunnel, frequency) + } catch (e: GridAccessException) { + // :P + } + newTunnel.onTunnelNetworkChange() + return newTunnel + } else { + throw RuntimeException("Cannot bind") + } } var PartP2PTunnel<*>.outputProperty @@ -56,6 +106,13 @@ var PartP2PTunnel<*>.outputProperty field.setBoolean(this, value) } +val IGridNode.connectionList: java.util.List + get() { + val field = GridNode::class.java.getDeclaredField("connections") + field.isAccessible = true + return field.get(this as GridNode) as java.util.List + } + val PartP2PTunnel<*>.hasChannel get() = isPowered && isActive