mirror of
https://github.com/GTNewHorizons/BetterP2P.git
synced 2026-10-26 14:24:05 +00:00
Add refresh button, and prevent excessive packet spam.
Packets are sent only once every 250 ms to avoid DDOSing someone. Accomplishes this by adding a new scheduled executor.
This commit is contained in:
1 parent
10781e4362
commit
d7f40e33af
12 files changed
+108
-54
No files matched your search
@@ -7,6 +7,7 @@ import cpw.mods.fml.common.Mod
|
||||
import cpw.mods.fml.common.SidedProxy
|
||||
import cpw.mods.fml.common.event.FMLPostInitializationEvent
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent
|
||||
import cpw.mods.fml.common.event.FMLServerStoppedEvent
|
||||
import cpw.mods.fml.common.registry.GameRegistry
|
||||
import net.minecraftforge.common.config.Configuration
|
||||
import org.apache.logging.log4j.Logger
|
||||
@@ -37,4 +38,9 @@ object BetterP2P {
|
||||
fun postInit(event: FMLPostInitializationEvent) {
|
||||
proxy.postInit()
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
fun onServerStopped(event: FMLServerStoppedEvent) {
|
||||
ModNetwork.stop()
|
||||
}
|
||||
}
|
||||
@@ -60,10 +60,10 @@ class GuiAdvancedMemoryCard(msg: S2CListP2P) : GuiScreen(), TextureBound {
|
||||
private val modeButton: WidgetButton
|
||||
|
||||
private var type: ClientTunnelInfo? = BetterP2P.proxy.getP2PFromIndex(msg.memoryInfo.type) as? ClientTunnelInfo
|
||||
private var typeCooldown: Long = System.currentTimeMillis()
|
||||
private var typeUpdateReady: Boolean = true
|
||||
private val typeButton: WidgetButton
|
||||
|
||||
private val refreshButton: WidgetButton
|
||||
|
||||
private val scrollBar: WidgetScrollBar
|
||||
private val searchBar: MEGuiTextField
|
||||
|
||||
@@ -208,7 +208,7 @@ class GuiAdvancedMemoryCard(msg: S2CListP2P) : GuiScreen(), TextureBound {
|
||||
(hoverText as MutableList)[0] =
|
||||
I18n.format("gui.advanced_memory_card.types.filtered", "§a" + type!!.stack.displayName)
|
||||
}
|
||||
requestRefresh()
|
||||
ModNetwork.channel.sendToServer(C2SRefreshP2PList(type?.index ?: TUNNEL_ANY))
|
||||
super.func_146113_a(mc.soundHandler)
|
||||
}
|
||||
}
|
||||
@@ -241,6 +241,14 @@ class GuiAdvancedMemoryCard(msg: S2CListP2P) : GuiScreen(), TextureBound {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
refreshButton = object: WidgetButton(this, 0, 0, 32, 32) {
|
||||
override fun mousePressed(mouseX: Int, mouseY: Int, button: Int) {
|
||||
if (super.mousePressed(mc, mouseX, mouseY)) {
|
||||
ModNetwork.channel.sendToServer(C2SRefreshP2PList(type?.index ?: TUNNEL_ANY))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,9 +289,12 @@ class GuiAdvancedMemoryCard(msg: S2CListP2P) : GuiScreen(), TextureBound {
|
||||
buttonList.add(modeButton)
|
||||
|
||||
typeButton.setPosition(guiLeft - 32, guiTop + 66)
|
||||
typeButton.setTexCoords(0.0, 200.0)
|
||||
buttonList.add(typeButton)
|
||||
|
||||
refreshButton.setPosition(guiLeft - 32, guiTop + 98)
|
||||
refreshButton.setTexCoords(32 * 5.0, 200.0)
|
||||
buttonList.add(refreshButton)
|
||||
|
||||
infos.refresh()
|
||||
checkInfo()
|
||||
refreshOverlay()
|
||||
@@ -291,26 +302,13 @@ class GuiAdvancedMemoryCard(msg: S2CListP2P) : GuiScreen(), TextureBound {
|
||||
}
|
||||
|
||||
private fun checkInfo() {
|
||||
infos.filtered.forEach { it.error = false }
|
||||
// A P2P entry is considered "errored" if it is an output, and has no inputs.
|
||||
infos.filtered.groupBy { it.frequency }
|
||||
.filter { it.value.none { x -> !x.output } }
|
||||
.forEach { it.value.forEach {
|
||||
info -> info.error = true
|
||||
} }
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a refresh from C->S.
|
||||
* TODO: Implement
|
||||
*/
|
||||
fun requestRefresh() {
|
||||
// Let's make sure the server only gets the last request in the last 250 ms, so we don't get spammed.
|
||||
val time = System.currentTimeMillis()
|
||||
typeCooldown = time + 250
|
||||
if (typeUpdateReady && time < typeCooldown) {
|
||||
ModNetwork.channel.sendToServer(C2SRefreshP2PList(type?.index ?: TUNNEL_ANY))
|
||||
typeUpdateReady = false
|
||||
infos.filtered.forEach {
|
||||
it.error = it.frequency != 0L && if (it.output) {
|
||||
col.findInput(it.frequency) == null
|
||||
} else {
|
||||
col.findOutput(it.frequency) == null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,10 +367,6 @@ class GuiAdvancedMemoryCard(msg: S2CListP2P) : GuiScreen(), TextureBound {
|
||||
col.mouseHovered(mouseX, mouseY)
|
||||
}
|
||||
}
|
||||
if (!typeUpdateReady && System.currentTimeMillis() > typeCooldown) {
|
||||
typeUpdateReady = true
|
||||
ModNetwork.channel.sendToServer(C2SRefreshP2PList(type?.index ?: TUNNEL_ANY))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -405,9 +399,9 @@ class GuiAdvancedMemoryCard(msg: S2CListP2P) : GuiScreen(), TextureBound {
|
||||
override fun mouseClicked(mouseX: Int, mouseY: Int, mouseButton: Int) {
|
||||
col.mouseClicked(mouseX, mouseY, mouseButton)
|
||||
scrollBar.click(mouseX, mouseY)
|
||||
modeButton.mousePressed(mouseX, mouseY, mouseButton)
|
||||
resizeButton.mousePressed(mouseX, mouseY, mouseButton)
|
||||
typeButton.mousePressed(mouseX, mouseY, mouseButton)
|
||||
buttonList.forEach {it as WidgetButton
|
||||
it.mousePressed(mouseX, mouseY, mouseButton)
|
||||
}
|
||||
searchBar.mouseClicked(mouseX, mouseY, mouseButton)
|
||||
if (mouseButton == 1 && searchBar.isMouseIn(mouseX, mouseY)) {
|
||||
this.searchBar.text = ""
|
||||
|
||||
@@ -97,7 +97,7 @@ class InfoList (initList: Collection<InfoWrapper>,
|
||||
}
|
||||
-(hits * hits) + name.length
|
||||
}
|
||||
else -> it.frequency + Short.MAX_VALUE
|
||||
else -> it.frequency + Short.MAX_VALUE - (if (it.output) 0 else 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,9 +125,12 @@ class WidgetP2PColumn(private val gui: GuiAdvancedMemoryCard,
|
||||
}
|
||||
}
|
||||
|
||||
private fun findInput(frequency: Long?) =
|
||||
fun findInput(frequency: Long?) =
|
||||
infos.filtered.find { it.frequency == frequency && !it.output }
|
||||
|
||||
fun findOutput(frequency: Long?) =
|
||||
infos.filtered.find { it.frequency == frequency && it.output }
|
||||
|
||||
fun mouseClicked(mouseX: Int, mouseY: Int, mouseButton: Int) {
|
||||
var clickRenameButton = false
|
||||
for ((index, widget) in entries.withIndex()) {
|
||||
|
||||
@@ -16,7 +16,6 @@ import com.projecturanus.betterp2p.util.getPart
|
||||
import com.projecturanus.betterp2p.util.p2p.P2PCache
|
||||
import com.projecturanus.betterp2p.util.p2p.P2PStatus
|
||||
import com.projecturanus.betterp2p.util.p2p.getTypeIndex
|
||||
import com.projecturanus.betterp2p.util.p2p.toInfo
|
||||
import cpw.mods.fml.relauncher.Side
|
||||
import cpw.mods.fml.relauncher.SideOnly
|
||||
import net.minecraft.client.renderer.texture.IIconRegister
|
||||
@@ -45,9 +44,7 @@ object ItemAdvancedMemoryCard : Item() {
|
||||
|
||||
private fun sendStatus(status: P2PStatus, info: MemoryInfo, player: EntityPlayerMP) {
|
||||
P2PCache.statusMap[player.uniqueID] = status
|
||||
ModNetwork.channel.sendTo(
|
||||
S2CListP2P(status.refresh(info.type).map { it.toInfo() }, info),
|
||||
player)
|
||||
ModNetwork.channel.sendTo(S2CListP2P(status.refresh(info.type), info), player)
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.projecturanus.betterp2p.capability.TUNNEL_ANY
|
||||
import com.projecturanus.betterp2p.util.listAllGridP2P
|
||||
import com.projecturanus.betterp2p.util.listTargetGridP2P
|
||||
import com.projecturanus.betterp2p.util.p2p.P2PCache
|
||||
import com.projecturanus.betterp2p.util.p2p.toInfo
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler
|
||||
import cpw.mods.fml.common.network.simpleimpl.MessageContext
|
||||
@@ -29,7 +28,7 @@ class C2SRefreshP2PList(var type: Int = TUNNEL_ANY): IMessage {
|
||||
* Client -> C2SRefreshP2P -> Server
|
||||
* Handler on server side
|
||||
*/
|
||||
class ServerRefreshP2PListHandler : IMessageHandler<C2SRefreshP2PList, S2CListP2P?> {
|
||||
class ServerRefreshP2PListHandler : IMessageHandler<C2SRefreshP2PList, IMessage?> {
|
||||
override fun onMessage(message: C2SRefreshP2PList, ctx: MessageContext): S2CListP2P? {
|
||||
if (!P2PCache.statusMap.containsKey(ctx.serverHandler.playerEntity.uniqueID)) return null
|
||||
val status = P2PCache.statusMap[ctx.serverHandler.playerEntity.uniqueID]!!
|
||||
@@ -40,6 +39,7 @@ class ServerRefreshP2PListHandler : IMessageHandler<C2SRefreshP2PList, S2CListP2
|
||||
} else {
|
||||
listAllGridP2P(status.grid, status.player)
|
||||
}
|
||||
return S2CListP2P(status.refresh(status.lastP2PType).map { it.toInfo() })
|
||||
ModNetwork.queueP2PListUpdate(status, ctx.serverHandler.playerEntity)
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import com.projecturanus.betterp2p.capability.TUNNEL_ANY
|
||||
import com.projecturanus.betterp2p.util.listAllGridP2P
|
||||
import com.projecturanus.betterp2p.util.listTargetGridP2P
|
||||
import com.projecturanus.betterp2p.util.p2p.P2PCache
|
||||
import com.projecturanus.betterp2p.util.p2p.toInfo
|
||||
import com.projecturanus.betterp2p.util.p2p.unlinkP2P
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler
|
||||
@@ -43,6 +42,7 @@ class ServerUnlinkP2PHandler : IMessageHandler<C2SUnlinkP2P, S2CListP2P?> {
|
||||
} else {
|
||||
listAllGridP2P(status.grid, status.player)
|
||||
}
|
||||
return S2CListP2P(status.refresh(status.lastP2PType).map { it.toInfo() })
|
||||
ModNetwork.queueP2PListUpdate(status, ctx.serverHandler.playerEntity)
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,22 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import com.projecturanus.betterp2p.MODID
|
||||
import com.projecturanus.betterp2p.capability.MemoryInfo
|
||||
import com.projecturanus.betterp2p.util.p2p.P2PStatus
|
||||
import cpw.mods.fml.common.network.NetworkRegistry
|
||||
import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper
|
||||
import cpw.mods.fml.relauncher.Side
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.entity.player.EntityPlayerMP
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor
|
||||
import java.util.concurrent.ThreadFactory
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
object ModNetwork {
|
||||
val channel: SimpleNetworkWrapper = NetworkRegistry.INSTANCE.newSimpleChannel(MODID)
|
||||
private var netCache: MutableMap<UUID, NetworkState> = mutableMapOf()
|
||||
private lateinit var networkWorker: ScheduledThreadPoolExecutor
|
||||
|
||||
fun registerNetwork() {
|
||||
channel.registerMessage(ClientOpenGuiHandler::class.java, S2CListP2P::class.java, 0, Side.CLIENT)
|
||||
@@ -18,5 +28,52 @@ object ModNetwork {
|
||||
channel.registerMessage(ServerRenameP2PTunnel::class.java, C2SP2PTunnelInfo::class.java, 6, Side.SERVER)
|
||||
channel.registerMessage(ServerRefreshP2PListHandler::class.java, C2SRefreshP2PList::class.java, 7, Side.SERVER)
|
||||
channel.registerMessage(ServerUnlinkP2PHandler::class.java, C2SUnlinkP2P::class.java, 8, Side.SERVER)
|
||||
networkWorker = ScheduledThreadPoolExecutor(1, ThreadFactory {
|
||||
val th = Thread(it)
|
||||
th.name = "BetterP2P-NetworkWorker"
|
||||
th.isDaemon = true
|
||||
th.priority = Thread.MIN_PRIORITY
|
||||
th
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function that asks for a p2p update. Multiple requests are bundled into 1.
|
||||
*/
|
||||
fun queueP2PListUpdate(status: P2PStatus, player: EntityPlayer, info: MemoryInfo? = null) {
|
||||
synchronized(netCache) {
|
||||
val state = netCache.getOrPut(player.uniqueID) { NetworkState() }
|
||||
if (state.updateReady + NETWORK_CD < System.currentTimeMillis()) {
|
||||
channel.sendTo(S2CListP2P(status.refresh(status.lastP2PType)), player as EntityPlayerMP)
|
||||
state.updateReady = System.currentTimeMillis() + NETWORK_CD
|
||||
} else if (!state.updatePending) {
|
||||
state.updatePending = true
|
||||
networkWorker.schedule({
|
||||
if (info == null) {
|
||||
channel.sendTo(S2CListP2P(status.refresh(status.lastP2PType)), player as EntityPlayerMP)
|
||||
} else {
|
||||
channel.sendTo(S2CListP2P(status.refresh(status.lastP2PType), info), player as EntityPlayerMP)
|
||||
}
|
||||
synchronized(netCache) {
|
||||
state.updatePending = false
|
||||
}
|
||||
}, state.updateReady - System.currentTimeMillis(), TimeUnit.MILLISECONDS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
networkWorker.shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
internal data class NetworkState(
|
||||
internal var updatePending: Boolean = false,
|
||||
internal var updateReady: Long = System.currentTimeMillis()
|
||||
)
|
||||
|
||||
/**
|
||||
* Network cooldown time in milliseconds
|
||||
*/
|
||||
const val NETWORK_CD = 250L
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import com.projecturanus.betterp2p.util.p2p.P2PCache
|
||||
import com.projecturanus.betterp2p.util.p2p.toInfo
|
||||
import com.projecturanus.betterp2p.util.p2p.linkP2P
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler
|
||||
@@ -15,7 +14,7 @@ class ServerLinkP2PHandler : IMessageHandler<C2SLinkP2P, IMessage?> {
|
||||
if (result != null) {
|
||||
status.listP2P[message.input] = result.first
|
||||
status.listP2P[message.output] = result.second
|
||||
return S2CRefreshInfo(status.refresh(status.lastP2PType).map { it.toInfo() })
|
||||
ModNetwork.queueP2PListUpdate(status, ctx.serverHandler.playerEntity)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -4,11 +4,9 @@ import appeng.api.parts.IPartHost
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
import com.projecturanus.betterp2p.item.ItemAdvancedMemoryCard
|
||||
import com.projecturanus.betterp2p.util.p2p.P2PCache
|
||||
import com.projecturanus.betterp2p.util.p2p.toInfo
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler
|
||||
import cpw.mods.fml.common.network.simpleimpl.MessageContext
|
||||
import net.minecraft.entity.player.EntityPlayerMP
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.common.DimensionManager
|
||||
@@ -25,10 +23,7 @@ class ServerRenameP2PTunnel : IMessageHandler<C2SP2PTunnelInfo, IMessage?> {
|
||||
if (te is IGridHost && te.getGridNode(ForgeDirection.getOrientation(message.info.side)) != null) {
|
||||
val p = (te as IPartHost).getPart(ForgeDirection.getOrientation(message.info.side)) as PartP2PTunnel<*>
|
||||
p.customName = message.info.name
|
||||
ModNetwork.channel.sendTo(
|
||||
S2CListP2P(cache.refresh(cache.lastP2PType).map { it.toInfo() },
|
||||
ItemAdvancedMemoryCard.getInfo(cache.player.heldItem)),
|
||||
cache.player as EntityPlayerMP)
|
||||
ModNetwork.queueP2PListUpdate(cache, ctx.serverHandler.playerEntity, ItemAdvancedMemoryCard.getInfo(cache.player.heldItem))
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import appeng.api.networking.IGrid
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
import com.projecturanus.betterp2p.BetterP2P
|
||||
import com.projecturanus.betterp2p.capability.TUNNEL_ANY
|
||||
import com.projecturanus.betterp2p.network.P2PInfo
|
||||
import com.projecturanus.betterp2p.network.hashP2P
|
||||
import com.projecturanus.betterp2p.util.listAllGridP2P
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
@@ -38,14 +39,16 @@ class P2PStatus(val grid: IGrid, val player: EntityPlayer, type: Int) {
|
||||
* @param type if TUNNEL_ANY or invalid, returns the full list; else
|
||||
* filters the list to the targeted type
|
||||
*/
|
||||
fun refresh(type: Int): List<PartP2PTunnel<*>> {
|
||||
fun refresh(type: Int): List<P2PInfo> {
|
||||
rebuildList()
|
||||
return if (type == TUNNEL_ANY) {
|
||||
listP2P.values.toList()
|
||||
listP2P.values.map { it.toInfo() }
|
||||
} else {
|
||||
listP2P.values.filter {
|
||||
(BetterP2P.proxy.getP2PFromClass(it.javaClass)?.index ?: TUNNEL_ANY) == type
|
||||
}.toList()
|
||||
listP2P.values.mapNotNull {
|
||||
if ((BetterP2P.proxy.getP2PFromClass(it.javaClass)?.index ?: TUNNEL_ANY) == type) {
|
||||
it.toInfo()
|
||||
} else null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.8 KiB |
Reference in new issue
Block a user