mirror of
https://github.com/GTNewHorizons/BetterP2P.git
synced 2026-10-26 14:24:05 +00:00
Rewrite the entire netcode
Almost all netcode has been touched in some way or form to try to fix some bugs with hashing. Removed all unused classes. Still needs more code cleanup (imports, etc.) but this works.
This commit is contained in:
1 parent
2e0a69441c
commit
a96851988e
50 files changed
+1312
-1105
No files matched your search
@@ -1,7 +1,18 @@
|
||||
package com.projecturanus.betterp2p
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.crafting.ShapelessRecipes
|
||||
import net.minecraft.util.IIcon
|
||||
|
||||
import com.glodblock.github.common.parts.PartFluidP2PInterface
|
||||
import com.glodblock.github.loader.ItemAndBlockHolder
|
||||
import com.projecturanus.betterp2p.client.render.RenderHandler
|
||||
import com.projecturanus.betterp2p.item.ItemAdvancedMemoryCard
|
||||
import com.projecturanus.betterp2p.network.ServerPlayerDisconnectHandler
|
||||
import com.projecturanus.betterp2p.util.p2p.ClientTunnelInfo
|
||||
import com.projecturanus.betterp2p.util.p2p.TunnelInfo
|
||||
|
||||
import appeng.api.AEApi
|
||||
import appeng.api.config.TunnelType
|
||||
import appeng.api.definitions.IItemDefinition
|
||||
import appeng.parts.p2p.PartP2PGT5Power
|
||||
import appeng.parts.p2p.PartP2PIC2Power
|
||||
@@ -15,18 +26,8 @@ import appeng.parts.p2p.PartP2PRFPower
|
||||
import appeng.parts.p2p.PartP2PRedstone
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
import appeng.parts.p2p.PartP2PTunnelME
|
||||
import com.glodblock.github.common.parts.PartFluidP2PInterface
|
||||
import com.glodblock.github.loader.ItemAndBlockHolder
|
||||
import com.projecturanus.betterp2p.client.render.RenderHandler
|
||||
import com.projecturanus.betterp2p.item.ItemAdvancedMemoryCard
|
||||
import com.projecturanus.betterp2p.network.ServerPlayerDisconnectHandler
|
||||
import com.projecturanus.betterp2p.util.p2p.ClientTunnelInfo
|
||||
import com.projecturanus.betterp2p.util.p2p.TunnelInfo
|
||||
import cpw.mods.fml.common.Loader
|
||||
import cpw.mods.fml.common.registry.GameRegistry
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.crafting.ShapelessRecipes
|
||||
import net.minecraft.util.IIcon
|
||||
|
||||
/**
|
||||
* A proxy for the server
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
package com.projecturanus.betterp2p.capability
|
||||
|
||||
import com.projecturanus.betterp2p.client.gui.widget.GuiScale
|
||||
import com.projecturanus.betterp2p.item.BetterMemoryCardModes
|
||||
import com.projecturanus.betterp2p.network.NONE_SELECTED
|
||||
|
||||
const val TUNNEL_ANY: Int = -1
|
||||
data class MemoryInfo(var selectedEntry: Long = NONE_SELECTED,
|
||||
var frequency: Long = 0,
|
||||
var mode: BetterMemoryCardModes = BetterMemoryCardModes.OUTPUT,
|
||||
var gui: GuiScale = GuiScale.DYNAMIC,
|
||||
var type: Int = TUNNEL_ANY)
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.projecturanus.betterp2p.capability
|
||||
|
||||
data class P2PTunnelInfo(
|
||||
var posX: Int = 0,
|
||||
var posY: Int = 0,
|
||||
var posZ: Int = 0,
|
||||
var world: Int = 0,
|
||||
var side: Int = 0,
|
||||
var name:String? = null
|
||||
)
|
||||
@@ -1,36 +1,43 @@
|
||||
package com.projecturanus.betterp2p.client.gui
|
||||
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.FontRenderer
|
||||
import net.minecraft.client.gui.GuiScreen
|
||||
import net.minecraft.client.renderer.Tessellator
|
||||
import net.minecraft.client.resources.I18n
|
||||
import net.minecraft.util.ResourceLocation
|
||||
|
||||
import com.projecturanus.betterp2p.BetterP2P
|
||||
import com.projecturanus.betterp2p.MODID
|
||||
import com.projecturanus.betterp2p.network.data.MemoryInfo
|
||||
import com.projecturanus.betterp2p.network.data.TUNNEL_ANY
|
||||
import com.projecturanus.betterp2p.client.ClientCache
|
||||
import com.projecturanus.betterp2p.client.TextureBound
|
||||
import com.projecturanus.betterp2p.client.gui.widget.*
|
||||
import com.projecturanus.betterp2p.item.BetterMemoryCardModes
|
||||
import com.projecturanus.betterp2p.item.MAX_TOOLTIP_LENGTH
|
||||
import com.projecturanus.betterp2p.network.*
|
||||
import com.projecturanus.betterp2p.network.data.P2PInfo
|
||||
import com.projecturanus.betterp2p.network.data.P2PLocation
|
||||
import com.projecturanus.betterp2p.network.packet.C2SCloseGui
|
||||
import com.projecturanus.betterp2p.network.packet.C2SRefreshP2PList
|
||||
import com.projecturanus.betterp2p.network.packet.C2SUpdateMemoryInfo
|
||||
import com.projecturanus.betterp2p.network.packet.S2COpenGui
|
||||
import com.projecturanus.betterp2p.util.p2p.ClientTunnelInfo
|
||||
|
||||
import appeng.client.gui.widgets.MEGuiTextField
|
||||
import appeng.parts.p2p.PartP2PGT5Power
|
||||
import appeng.parts.p2p.PartP2PInterface
|
||||
import appeng.parts.p2p.PartP2PLiquids
|
||||
import appeng.parts.p2p.PartP2PRedstone
|
||||
import appeng.parts.p2p.PartP2PTunnelME
|
||||
import com.projecturanus.betterp2p.BetterP2P
|
||||
import com.projecturanus.betterp2p.MODID
|
||||
import com.projecturanus.betterp2p.capability.MemoryInfo
|
||||
import com.projecturanus.betterp2p.capability.TUNNEL_ANY
|
||||
import com.projecturanus.betterp2p.client.ClientCache
|
||||
import com.projecturanus.betterp2p.client.TextureBound
|
||||
import com.projecturanus.betterp2p.client.gui.widget.*
|
||||
import com.projecturanus.betterp2p.item.BetterMemoryCardModes
|
||||
import com.projecturanus.betterp2p.item.MAX_TOOLTIP_LENGTH
|
||||
import com.projecturanus.betterp2p.network.*
|
||||
import com.projecturanus.betterp2p.util.p2p.ClientTunnelInfo
|
||||
import com.projecturanus.betterp2p.util.p2p.TunnelInfo
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.FontRenderer
|
||||
import net.minecraft.client.gui.GuiScreen
|
||||
import net.minecraft.client.renderer.Tessellator
|
||||
import net.minecraft.client.resources.I18n
|
||||
import net.minecraft.util.ResourceLocation
|
||||
import org.lwjgl.input.Keyboard
|
||||
import org.lwjgl.input.Mouse
|
||||
import org.lwjgl.opengl.GL11
|
||||
|
||||
const val GUI_WIDTH = 288
|
||||
const val GUI_TEX_HEIGHT = 264
|
||||
class GuiAdvancedMemoryCard(msg: S2CListP2P) : GuiScreen(), TextureBound {
|
||||
class GuiAdvancedMemoryCard(msg: S2COpenGui) : GuiScreen(), TextureBound {
|
||||
|
||||
private var guiLeft: Int = 0
|
||||
|
||||
@@ -51,7 +58,7 @@ class GuiAdvancedMemoryCard(msg: S2CListP2P) : GuiScreen(), TextureBound {
|
||||
_ySize = lazy { value }
|
||||
}
|
||||
|
||||
private var scale = msg.memoryInfo.gui
|
||||
private var scale = msg.memoryInfo.guiScale
|
||||
private val resizeButton: WidgetButton
|
||||
|
||||
private var mode = msg.memoryInfo.mode
|
||||
@@ -386,14 +393,20 @@ class GuiAdvancedMemoryCard(msg: S2CListP2P) : GuiScreen(), TextureBound {
|
||||
}
|
||||
|
||||
fun refreshInfo(infos: List<P2PInfo>) {
|
||||
this.infos.rebuild(infos.map(::InfoWrapper))
|
||||
this.infos.rebuild(infos.map(::InfoWrapper), scrollBar, scale.size(height - 75))
|
||||
checkInfo()
|
||||
refreshOverlay()
|
||||
}
|
||||
|
||||
fun updateInfo(infos: List<P2PInfo>) {
|
||||
this.infos.update(infos.map(::InfoWrapper), scrollBar, scale.size(height - 75))
|
||||
checkInfo()
|
||||
refreshOverlay()
|
||||
}
|
||||
|
||||
private fun syncMemoryInfo() {
|
||||
ModNetwork.channel.sendToServer(
|
||||
C2SUpdateInfo(MemoryInfo(infos.selectedEntry, selectedInfo?.frequency ?: 0, mode, scale, type?.index ?: TUNNEL_ANY)))
|
||||
C2SUpdateMemoryInfo(MemoryInfo(infos.selectedEntry, selectedInfo?.frequency ?: 0, mode, scale, type?.index ?: TUNNEL_ANY)))
|
||||
}
|
||||
|
||||
override fun onGuiClosed() {
|
||||
@@ -450,8 +463,8 @@ class GuiAdvancedMemoryCard(msg: S2CListP2P) : GuiScreen(), TextureBound {
|
||||
* Selects the info with the hashCode, if it exists. Otherwise,
|
||||
* deselect the entry.
|
||||
*/
|
||||
fun selectInfo(hash: Long) {
|
||||
infos.select(hash)
|
||||
fun selectInfo(which: P2PLocation?) {
|
||||
infos.select(which)
|
||||
syncMemoryInfo()
|
||||
refreshOverlay()
|
||||
}
|
||||
@@ -462,15 +475,15 @@ class GuiAdvancedMemoryCard(msg: S2CListP2P) : GuiScreen(), TextureBound {
|
||||
ClientCache.selectedFacing = null
|
||||
}
|
||||
else {
|
||||
ClientCache.selectedPosition = arrayListOf(selectedInfo?.posX, selectedInfo?.posY, selectedInfo?.posZ)
|
||||
ClientCache.selectedFacing = selectedInfo?.facing
|
||||
ClientCache.selectedPosition = arrayListOf(selectedInfo?.loc?.x, selectedInfo?.loc?.y, selectedInfo?.loc?.z)
|
||||
ClientCache.selectedFacing = selectedInfo?.loc?.facing
|
||||
}
|
||||
ClientCache.positions.clear()
|
||||
ClientCache.positions.addAll(infos.sorted.filter {
|
||||
it.frequency == selectedInfo?.frequency &&
|
||||
it != selectedInfo &&
|
||||
it.dim == mc.thePlayer.dimension
|
||||
}.map { arrayListOf(it.posX, it.posY, it.posZ) to it.facing })
|
||||
it.loc.dim == mc.thePlayer.dimension
|
||||
}.map { arrayListOf(it.loc.x, it.loc.y, it.loc.z) to it.loc.facing })
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Int, mouseY: Int, mouseButton: Int) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.projecturanus.betterp2p.client.gui
|
||||
|
||||
import com.projecturanus.betterp2p.network.NONE_SELECTED
|
||||
import com.projecturanus.betterp2p.client.gui.widget.WidgetScrollBar
|
||||
import com.projecturanus.betterp2p.network.data.P2PLocation
|
||||
import kotlin.reflect.KProperty0
|
||||
|
||||
/**
|
||||
@@ -17,7 +18,7 @@ class InfoList (initList: Collection<InfoWrapper>,
|
||||
* The master map, acts as the source of truth for all items
|
||||
* in this list.
|
||||
*/
|
||||
private val masterMap: HashMap<Long, InfoWrapper> = hashMapOf()
|
||||
private val masterMap: HashMap<P2PLocation, InfoWrapper> = hashMapOf()
|
||||
|
||||
/**
|
||||
* Sorted view of the master map. This is resorted whenever
|
||||
@@ -39,20 +40,26 @@ class InfoList (initList: Collection<InfoWrapper>,
|
||||
get() = search.get()
|
||||
|
||||
val selectedInfo: InfoWrapper?
|
||||
get() = masterMap[selectedEntry]
|
||||
get() {
|
||||
return if (selectedEntry == null) {
|
||||
null
|
||||
} else {
|
||||
masterMap[selectedEntry]
|
||||
}
|
||||
}
|
||||
|
||||
var selectedEntry: Long = NONE_SELECTED
|
||||
var selectedEntry: P2PLocation? = null
|
||||
|
||||
val size: Int
|
||||
get() = masterMap.size
|
||||
|
||||
init {
|
||||
initList.forEach { masterMap[it.code] = it }
|
||||
initList.forEach { masterMap[it.loc] = it }
|
||||
}
|
||||
|
||||
fun resort() {
|
||||
sorted.sortBy {
|
||||
if (it.code == selectedEntry) {
|
||||
if (it.loc == selectedEntry) {
|
||||
-2 // Put the selected p2p at the front
|
||||
// Non-Zero frequencies
|
||||
} else if (it.frequency != 0L && it.frequency == selectedInfo?.frequency && !it.output) {
|
||||
@@ -72,7 +79,7 @@ class InfoList (initList: Collection<InfoWrapper>,
|
||||
fun refilter() {
|
||||
filter.updateFilter(searchStr.lowercase())
|
||||
filtered = sorted.filter {
|
||||
if (it.code == selectedEntry) {
|
||||
if (it.loc == selectedEntry) {
|
||||
return@filter true
|
||||
}
|
||||
for ((f, strs) in filter.activeFilters) {
|
||||
@@ -83,7 +90,7 @@ class InfoList (initList: Collection<InfoWrapper>,
|
||||
true
|
||||
}.sortedBy {
|
||||
when {
|
||||
it.code == selectedEntry -> Long.MIN_VALUE + 1
|
||||
it.loc == selectedEntry -> Long.MIN_VALUE + 1
|
||||
it.frequency != 0L && it.frequency == selectedInfo?.frequency && !it.output -> Long.MIN_VALUE
|
||||
// Put the same frequency to the front
|
||||
it.frequency != 0.toLong() && it.frequency == selectedInfo?.frequency -> Long.MIN_VALUE + 2
|
||||
@@ -116,33 +123,31 @@ class InfoList (initList: Collection<InfoWrapper>,
|
||||
/**
|
||||
* Completely refresh the master list.
|
||||
*/
|
||||
fun rebuild(updateList: Collection<InfoWrapper>) {
|
||||
fun rebuild(updateList: Collection<InfoWrapper>, scrollbar: WidgetScrollBar, numEntries: Int) {
|
||||
masterMap.clear()
|
||||
updateList.forEach { masterMap[it.code] = it }
|
||||
updateList.forEach { masterMap[it.loc] = it }
|
||||
sorted.clear()
|
||||
sorted.addAll(masterMap.values)
|
||||
resort()
|
||||
// TODO: Extend the filtering mechanism.
|
||||
refilter()
|
||||
scrollbar.setRange(0, masterMap.size.coerceIn(0, (masterMap.size - numEntries).coerceAtLeast(0)), 23)
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the master list and sends the changes downstream to sorted/filtered.
|
||||
*/
|
||||
fun update(updateList: Collection<InfoWrapper>) {
|
||||
updateList.forEach { masterMap[it.code] = it }
|
||||
fun update(updateList: Collection<InfoWrapper>, scrollbar: WidgetScrollBar, numEntries: Int) {
|
||||
updateList.forEach { masterMap[it.loc] = it }
|
||||
sorted.clear()
|
||||
sorted.addAll(masterMap.values)
|
||||
resort()
|
||||
// TODO: Extend the filtering mechanism.
|
||||
refilter()
|
||||
scrollbar.setRange(0, masterMap.size.coerceIn(0, (masterMap.size - numEntries).coerceAtLeast(0)), 23)
|
||||
}
|
||||
|
||||
fun select(hashCode: Long) {
|
||||
if (masterMap.containsKey(hashCode)) {
|
||||
selectedEntry = hashCode
|
||||
} else {
|
||||
selectedEntry = NONE_SELECTED
|
||||
}
|
||||
fun select(which: P2PLocation?) {
|
||||
selectedEntry = masterMap.getOrDefault(which, null)?.loc
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,18 @@
|
||||
package com.projecturanus.betterp2p.client.gui
|
||||
|
||||
import com.projecturanus.betterp2p.BetterP2P
|
||||
import com.projecturanus.betterp2p.network.P2PInfo
|
||||
import com.projecturanus.betterp2p.network.hashP2P
|
||||
import com.projecturanus.betterp2p.network.data.P2PInfo
|
||||
import com.projecturanus.betterp2p.network.data.P2PLocation
|
||||
import com.projecturanus.betterp2p.util.p2p.ClientTunnelInfo
|
||||
import cpw.mods.fml.relauncher.Side
|
||||
import cpw.mods.fml.relauncher.SideOnly
|
||||
import net.minecraft.client.gui.GuiButton
|
||||
import net.minecraft.client.resources.I18n
|
||||
import net.minecraft.util.IIcon
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
class InfoWrapper(info: P2PInfo) {
|
||||
// Basic information
|
||||
val code: Long by lazy {
|
||||
hashP2P(posX, posY, posZ, facing.ordinal, dim)
|
||||
}
|
||||
var frequency: Long = info.frequency
|
||||
set(value) {
|
||||
if (error || value == 0L) {
|
||||
@@ -25,11 +24,7 @@ class InfoWrapper(info: P2PInfo) {
|
||||
}
|
||||
|
||||
val hasChannel = info.hasChannel
|
||||
val posX: Int = info.posX
|
||||
val posY: Int = info.posY
|
||||
val posZ: Int = info.posZ
|
||||
val dim: Int = info.world
|
||||
val facing: ForgeDirection = info.facing
|
||||
val loc: P2PLocation = P2PLocation(info.posX, info.posY, info.posZ, info.facing, info.dim)
|
||||
val output: Boolean = info.output
|
||||
val type: Int = info.type
|
||||
|
||||
@@ -96,7 +91,7 @@ class InfoWrapper(info: P2PInfo) {
|
||||
"§bP2P - ${p2pType.dispName}",
|
||||
"§e" + I18n.format("gui.advanced_memory_card.pos", info.posX, info.posY, info.posZ),
|
||||
"§e" + I18n.format("gui.advanced_memory_card.side", info.facing.name),
|
||||
"§e" + I18n.format("gui.advanced_memory_card.dim", info.world)
|
||||
"§e" + I18n.format("gui.advanced_memory_card.dim", info.dim)
|
||||
)
|
||||
if (error || frequency == 0L) {
|
||||
hoverInfo.add("§c" + I18n.format("gui.advanced_memory_card.p2p_status.unbound"))
|
||||
@@ -107,19 +102,15 @@ class InfoWrapper(info: P2PInfo) {
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return code.hashCode()
|
||||
return loc.hashCode()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return if (other is InfoWrapper) {
|
||||
this.posX == other.posX &&
|
||||
this.posY == other.posY &&
|
||||
this.posZ == other.posZ &&
|
||||
this.dim == other.dim &&
|
||||
this.facing == other.facing
|
||||
} else {
|
||||
false
|
||||
}
|
||||
if (this === other) return true
|
||||
if (this.javaClass != other?.javaClass) return false
|
||||
other as InfoWrapper
|
||||
|
||||
return this.loc == other.loc
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,14 +2,15 @@ package com.projecturanus.betterp2p.client.gui.widget
|
||||
|
||||
import appeng.core.localization.GuiColors
|
||||
import com.projecturanus.betterp2p.BetterP2P
|
||||
import com.projecturanus.betterp2p.capability.P2PTunnelInfo
|
||||
import com.projecturanus.betterp2p.client.gui.GuiAdvancedMemoryCard
|
||||
import com.projecturanus.betterp2p.client.gui.InfoList
|
||||
import com.projecturanus.betterp2p.client.gui.InfoWrapper
|
||||
import com.projecturanus.betterp2p.item.BetterMemoryCardModes
|
||||
import com.projecturanus.betterp2p.network.*
|
||||
import com.projecturanus.betterp2p.network.ModNetwork
|
||||
import com.projecturanus.betterp2p.network.packet.C2SLinkP2P
|
||||
import com.projecturanus.betterp2p.network.packet.C2SRenameP2P
|
||||
import com.projecturanus.betterp2p.network.packet.C2SUnlinkP2P
|
||||
import net.minecraft.client.gui.GuiTextField
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
import org.lwjgl.input.Keyboard
|
||||
import kotlin.reflect.KProperty0
|
||||
|
||||
@@ -59,9 +60,10 @@ class WidgetP2PColumn(private val gui: GuiAdvancedMemoryCard,
|
||||
widget.renderNameTextField = true
|
||||
}
|
||||
if(renameBar.info != null && renameBar.text.isNotEmpty() && renameBar.info.name != renameBar.text){
|
||||
val info:InfoWrapper = renameBar.info
|
||||
val info: InfoWrapper = renameBar.info
|
||||
|
||||
renameBar.text = renameBar.text.trim()
|
||||
ModNetwork.channel.sendToServer(C2SP2PTunnelInfo(P2PTunnelInfo(info.posX,info.posY,info.posZ,info.dim, ForgeDirection.valueOf(info.facing.name).ordinal,renameBar.text)))
|
||||
ModNetwork.channel.sendToServer(C2SRenameP2P(info.loc, renameBar.text))
|
||||
}
|
||||
renameBar.isVisible = false
|
||||
renameBar.text = ""
|
||||
@@ -86,26 +88,26 @@ class WidgetP2PColumn(private val gui: GuiAdvancedMemoryCard,
|
||||
if (mouseButton == 1) {
|
||||
gui.openTypeSelector(widget, false)
|
||||
} else if (selectedInfo.get() != info) {
|
||||
gui.selectInfo(info.code)
|
||||
gui.selectInfo(info.loc)
|
||||
}
|
||||
info.bindButton.func_146113_a(gui.mc.soundHandler)
|
||||
}
|
||||
|
||||
private fun onBindButtonClicked(info: InfoWrapper) {
|
||||
if (infos.selectedEntry == NONE_SELECTED) return
|
||||
if (infos.selectedEntry == null) return
|
||||
when (mode()) {
|
||||
BetterMemoryCardModes.INPUT -> {
|
||||
BetterP2P.logger.debug("Bind ${info.code} as input")
|
||||
ModNetwork.channel.sendToServer(C2SLinkP2P(info.code, infos.selectedEntry))
|
||||
BetterP2P.logger.debug("Bind ${info.loc} as input")
|
||||
ModNetwork.channel.sendToServer(C2SLinkP2P(info.loc, infos.selectedEntry))
|
||||
}
|
||||
BetterMemoryCardModes.OUTPUT -> {
|
||||
BetterP2P.logger.debug("Bind ${info.code} as output")
|
||||
ModNetwork.channel.sendToServer(C2SLinkP2P(infos.selectedEntry, info.code))
|
||||
BetterP2P.logger.debug("Bind ${info.loc} as output")
|
||||
ModNetwork.channel.sendToServer(C2SLinkP2P(infos.selectedEntry, info.loc))
|
||||
}
|
||||
BetterMemoryCardModes.COPY -> {
|
||||
val input = findInput(infos.selectedInfo?.frequency)
|
||||
if (input != null)
|
||||
ModNetwork.channel.sendToServer(C2SLinkP2P(input.code, info.code))
|
||||
ModNetwork.channel.sendToServer(C2SLinkP2P(input.loc, info.loc))
|
||||
}
|
||||
else -> {
|
||||
BetterP2P.logger.debug("Somehow bind button was pressed while in UNBIND mode.")
|
||||
@@ -116,7 +118,7 @@ class WidgetP2PColumn(private val gui: GuiAdvancedMemoryCard,
|
||||
|
||||
private fun onUnbindButtonClicked(info: InfoWrapper) {
|
||||
if (info.frequency != 0L) {
|
||||
ModNetwork.channel.sendToServer(C2SUnlinkP2P(info.code, gui.getTypeID()))
|
||||
ModNetwork.channel.sendToServer(C2SUnlinkP2P(info.loc, gui.getTypeID()))
|
||||
info.frequency = 0L
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.projecturanus.betterp2p.client.gui.widget
|
||||
|
||||
import com.projecturanus.betterp2p.capability.TUNNEL_ANY
|
||||
import com.projecturanus.betterp2p.network.data.TUNNEL_ANY
|
||||
import com.projecturanus.betterp2p.client.gui.*
|
||||
import com.projecturanus.betterp2p.item.BetterMemoryCardModes
|
||||
import com.projecturanus.betterp2p.network.C2STypeChange
|
||||
import com.projecturanus.betterp2p.network.packet.C2STypeChange
|
||||
import com.projecturanus.betterp2p.network.ModNetwork
|
||||
import com.projecturanus.betterp2p.util.p2p.ClientTunnelInfo
|
||||
import com.projecturanus.betterp2p.util.p2p.TunnelInfo
|
||||
import net.minecraft.client.gui.GuiScreen
|
||||
import net.minecraft.client.renderer.Tessellator
|
||||
import net.minecraft.client.resources.I18n
|
||||
@@ -58,7 +57,7 @@ class WidgetP2PDevice(private val selectedInfoProperty: KProperty0<InfoWrapper?>
|
||||
} else {
|
||||
// Other modes:
|
||||
// Bind allowed only if currently not selected && selected is unbound; OR not bound to selected
|
||||
info.bindButton.enabled = info.code != selectedInfo!!.code &&
|
||||
info.bindButton.enabled = info.loc != selectedInfo!!.loc &&
|
||||
(selectedInfo!!.frequency == 0L ||
|
||||
info.frequency != selectedInfo!!.frequency)
|
||||
info.unbindButton.enabled = false
|
||||
@@ -69,7 +68,7 @@ class WidgetP2PDevice(private val selectedInfoProperty: KProperty0<InfoWrapper?>
|
||||
val info = infoSupplier()
|
||||
if (info != null) {
|
||||
// Draw the background first
|
||||
if (selectedInfo?.code == info.code)
|
||||
if (selectedInfo?.loc == info.loc)
|
||||
GuiScreen.drawRect(x, y, x + P2PEntryConstants.WIDTH, y + P2PEntryConstants.HEIGHT, P2PEntryConstants.SELECTED_COLOR)
|
||||
else if (info.error) {
|
||||
// P2P output without an input, or unbound
|
||||
@@ -138,7 +137,7 @@ class WidgetP2PDevice(private val selectedInfoProperty: KProperty0<InfoWrapper?>
|
||||
}
|
||||
|
||||
override fun accept(type: ClientTunnelInfo?) {
|
||||
ModNetwork.channel.sendToServer(C2STypeChange(type?.index ?: TUNNEL_ANY, infoSupplier()!!.code))
|
||||
ModNetwork.channel.sendToServer(C2STypeChange(type?.index ?: TUNNEL_ANY, infoSupplier()!!.loc))
|
||||
gui.closeTypeSelector()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
package com.projecturanus.betterp2p.item
|
||||
|
||||
import appeng.api.config.SecurityPermissions
|
||||
import appeng.api.networking.IGridHost
|
||||
import appeng.api.networking.security.ISecurityGrid
|
||||
import appeng.core.CreativeTab
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
import com.projecturanus.betterp2p.MODID
|
||||
import com.projecturanus.betterp2p.capability.MemoryInfo
|
||||
import com.projecturanus.betterp2p.capability.TUNNEL_ANY
|
||||
import com.projecturanus.betterp2p.client.ClientCache
|
||||
import com.projecturanus.betterp2p.client.gui.widget.GuiScale
|
||||
import com.projecturanus.betterp2p.network.ModNetwork
|
||||
import com.projecturanus.betterp2p.network.NONE_SELECTED
|
||||
import com.projecturanus.betterp2p.network.S2CListP2P
|
||||
import com.projecturanus.betterp2p.network.hashP2P
|
||||
import com.projecturanus.betterp2p.network.data.MemoryInfo
|
||||
import com.projecturanus.betterp2p.network.data.TUNNEL_ANY
|
||||
import com.projecturanus.betterp2p.network.data.readP2PLocation
|
||||
import com.projecturanus.betterp2p.network.data.toLoc
|
||||
import com.projecturanus.betterp2p.network.data.writeP2PLocation
|
||||
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 cpw.mods.fml.relauncher.Side
|
||||
import cpw.mods.fml.relauncher.SideOnly
|
||||
import net.minecraft.client.renderer.texture.IIconRegister
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.entity.player.EntityPlayerMP
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
@@ -42,11 +41,6 @@ object ItemAdvancedMemoryCard : Item() {
|
||||
super.onUpdate(stack, worldIn, entityIn, itemSlot, isSelected)
|
||||
}
|
||||
|
||||
private fun sendStatus(status: P2PStatus, info: MemoryInfo, player: EntityPlayerMP) {
|
||||
P2PCache.statusMap[player.uniqueID] = status
|
||||
ModNetwork.channel.sendTo(S2CListP2P(status.refresh(info.type), info), player)
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override fun addInformation(stack: ItemStack, player: EntityPlayer, tooltip: MutableList<Any?>, boolean: Boolean) {
|
||||
val info = getInfo(stack)
|
||||
@@ -70,29 +64,27 @@ object ItemAdvancedMemoryCard : Item() {
|
||||
val te = w.getTileEntity(x, y, z)
|
||||
if (te is IGridHost && te.getGridNode(ForgeDirection.getOrientation(side)) != null) {
|
||||
val part = getPart(w, x, y, z, hx, hy, hz)
|
||||
val grid = part?.gridNode?.grid ?: return false
|
||||
|
||||
if (grid is ISecurityGrid && !grid.hasPermission(player, SecurityPermissions.BUILD)) {
|
||||
// Check security grid permissions. Only BUILD is required.
|
||||
return false
|
||||
}
|
||||
|
||||
val stack = player.heldItem
|
||||
val info = getInfo(stack)
|
||||
val type: Int
|
||||
val status: P2PStatus
|
||||
|
||||
if (part is PartP2PTunnel<*>) {
|
||||
type = part.getTypeIndex()
|
||||
status = P2PStatus(part.gridNode.grid, player, type)
|
||||
info.selectedEntry = hashP2P(part)
|
||||
info.selectedEntry = part.toLoc()
|
||||
} else {
|
||||
type = TUNNEL_ANY
|
||||
status = if (part != null) {
|
||||
// If we have a PartP2PTunnelME, it looks at the P2P grid node,
|
||||
// so we should use the part instead.
|
||||
P2PStatus(part.gridNode.grid, player, type)
|
||||
} else {
|
||||
// Fall back to the tile entity.
|
||||
P2PStatus(te.getGridNode(ForgeDirection.getOrientation(side)).grid, player, type)
|
||||
}
|
||||
info.selectedEntry = NONE_SELECTED
|
||||
info.selectedEntry = null
|
||||
}
|
||||
info.type = type
|
||||
writeInfo(stack, info)
|
||||
sendStatus(status, info, player as EntityPlayerMP)
|
||||
ModNetwork.initConnection(player, grid, info)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -110,12 +102,22 @@ object ItemAdvancedMemoryCard : Item() {
|
||||
|
||||
fun getInfo(stack: ItemStack): MemoryInfo {
|
||||
if (stack.item != this) throw ClassCastException("Cannot cast ${stack.item.javaClass.name} to ${javaClass.name}")
|
||||
|
||||
if (stack.tagCompound == null) stack.tagCompound = NBTTagCompound()
|
||||
// Initialize NBT if it isn't already a thing
|
||||
if (stack.tagCompound == null) {
|
||||
stack.tagCompound = NBTTagCompound()
|
||||
}
|
||||
val compound = stack.tagCompound!!
|
||||
if (!compound.hasKey("gui")) compound.setByte("gui", GuiScale.DYNAMIC.ordinal.toByte())
|
||||
if (!compound.hasKey("selectedIndex", Constants.NBT.TAG_LONG)) compound.setLong("selectedIndex", NONE_SELECTED)
|
||||
return MemoryInfo(compound.getLong("selectedIndex"), compound.getLong("frequency"), BetterMemoryCardModes.values()[compound.getInteger("mode")], GuiScale.values()[compound.getByte("gui").toInt()])
|
||||
if (!compound.hasKey("gui")) {
|
||||
compound.setByte("gui", GuiScale.DYNAMIC.ordinal.toByte())
|
||||
}
|
||||
if (!compound.hasKey("selectedIndex", Constants.NBT.TAG_COMPOUND)) {
|
||||
compound.setTag("selectedIndex", NBTTagCompound())
|
||||
}
|
||||
return MemoryInfo(
|
||||
selectedEntry = readP2PLocation(compound.getCompoundTag("selectedIndex")),
|
||||
frequency = compound.getLong("frequency"),
|
||||
mode = BetterMemoryCardModes.values()[compound.getInteger("mode")],
|
||||
guiScale = GuiScale.values()[compound.getByte("gui").toInt()])
|
||||
}
|
||||
|
||||
fun writeInfo(stack: ItemStack, info: MemoryInfo) {
|
||||
@@ -123,9 +125,9 @@ object ItemAdvancedMemoryCard : Item() {
|
||||
|
||||
if (stack.tagCompound == null) stack.tagCompound = NBTTagCompound()
|
||||
val compound = stack.tagCompound!!
|
||||
compound.setLong("selectedIndex", info.selectedEntry)
|
||||
compound.setTag("selectedIndex", writeP2PLocation(info.selectedEntry))
|
||||
compound.setLong("frequency", info.frequency)
|
||||
compound.setInteger("mode", info.mode.ordinal)
|
||||
compound.setByte("gui", info.gui.ordinal.toByte())
|
||||
compound.setByte("gui", info.guiScale.ordinal.toByte())
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
||||
class AEPartLocationMessage(var x: Int = 0, var y: Int = 0, var z: Int = 0, var hitX: Float = 0f, var hitY: Float = 0f, var hitZ: Float = 0f): IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
x = buf.readInt()
|
||||
y = buf.readInt()
|
||||
z = buf.readInt()
|
||||
hitX = buf.readFloat()
|
||||
hitY = buf.readFloat()
|
||||
hitZ = buf.readFloat()
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
buf.writeInt(x)
|
||||
buf.writeInt(y)
|
||||
buf.writeInt(z)
|
||||
buf.writeFloat(hitX)
|
||||
buf.writeFloat(hitY)
|
||||
buf.writeFloat(hitZ)
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
||||
class C2SCloseGui : IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
||||
class C2SLinkP2P(var input: Long = NONE_SELECTED, var output: Long = NONE_SELECTED): IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
input = buf.readLong()
|
||||
output = buf.readLong()
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
buf.writeLong(input)
|
||||
buf.writeLong(output)
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import com.projecturanus.betterp2p.capability.P2PTunnelInfo
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
||||
fun readP2PTunnelInfo(buf: ByteBuf): P2PTunnelInfo {
|
||||
return P2PTunnelInfo(buf.readInt(),buf.readInt(),buf.readInt(),buf.readInt(),buf.readInt(), buf.readBytes(buf.readInt()).toString(Charsets.UTF_8))
|
||||
}
|
||||
|
||||
fun writeP2PTunnelInfo(buf: ByteBuf,info: P2PTunnelInfo) {
|
||||
buf.writeInt(info.posX)
|
||||
buf.writeInt(info.posY)
|
||||
buf.writeInt(info.posZ)
|
||||
buf.writeInt(info.world)
|
||||
buf.writeInt(info.side)
|
||||
if(info.name ==null) {
|
||||
buf.writeInt(0)
|
||||
}else{
|
||||
val arr = info.name?.toByteArray(Charsets.UTF_8)
|
||||
arr?.let { buf.writeInt(it.size) }
|
||||
buf.writeBytes(arr)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class C2SP2PTunnelInfo(var info: P2PTunnelInfo = P2PTunnelInfo()): IMessage {
|
||||
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
info = readP2PTunnelInfo(buf)
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
writeP2PTunnelInfo(buf,info)
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import com.projecturanus.betterp2p.BetterP2P
|
||||
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 cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler
|
||||
import cpw.mods.fml.common.network.simpleimpl.MessageContext
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
||||
/**
|
||||
* Send a request to the server to refresh the p2p list with the
|
||||
* given type.
|
||||
*/
|
||||
class C2SRefreshP2PList(var type: Int = TUNNEL_ANY): IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
type = buf.readByte().toInt()
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
buf.writeByte(type)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Client -> C2SRefreshP2P -> Server
|
||||
* Handler on server side
|
||||
*/
|
||||
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]!!
|
||||
status.lastP2PType = message.type
|
||||
val tunnelType = BetterP2P.proxy.getP2PFromIndex(message.type)
|
||||
if (tunnelType != null) {
|
||||
listTargetGridP2P(status.grid, status.player, tunnelType.clazz)
|
||||
} else {
|
||||
listAllGridP2P(status.grid, status.player)
|
||||
}
|
||||
ModNetwork.queueP2PListUpdate(status, ctx.serverHandler.playerEntity)
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
import com.projecturanus.betterp2p.capability.P2PTunnelInfo
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
||||
class C2STransportPlayer(var info: P2PTunnelInfo = P2PTunnelInfo()):IMessage{
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
info = readP2PTunnelInfo(buf)
|
||||
}
|
||||
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
writeP2PTunnelInfo(buf,info)
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import com.projecturanus.betterp2p.BetterP2P
|
||||
import com.projecturanus.betterp2p.capability.TUNNEL_ANY
|
||||
import com.projecturanus.betterp2p.util.p2p.P2PCache
|
||||
import com.projecturanus.betterp2p.util.p2p.changeAllP2Ps
|
||||
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 io.netty.buffer.ByteBuf
|
||||
|
||||
class C2STypeChange(var newType: Int = TUNNEL_ANY, var p2p: Long = NONE_SELECTED): IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
newType = buf.readByte().toInt()
|
||||
p2p = buf.readLong()
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
buf.writeByte(newType)
|
||||
buf.writeLong(p2p)
|
||||
}
|
||||
}
|
||||
|
||||
class ServerTypeChangeHandler : IMessageHandler<C2STypeChange, S2CListP2P?> {
|
||||
override fun onMessage(message: C2STypeChange, ctx: MessageContext): S2CListP2P? {
|
||||
if (message.newType == TUNNEL_ANY) return null
|
||||
val status = P2PCache.statusMap[ctx.serverHandler.playerEntity.uniqueID] ?: return null
|
||||
val tunnel = status.listP2P[message.p2p] ?: return null
|
||||
val type = BetterP2P.proxy.getP2PFromIndex(message.newType) ?: return null
|
||||
val newTunnel = changeAllP2Ps(tunnel, type, ctx.serverHandler.playerEntity)
|
||||
if (newTunnel) {
|
||||
ModNetwork.queueP2PListUpdate(status, ctx.serverHandler.playerEntity)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import com.projecturanus.betterp2p.BetterP2P
|
||||
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.unlinkP2P
|
||||
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 io.netty.buffer.ByteBuf
|
||||
|
||||
/**
|
||||
* Unlink input from outputs message (set freq to 0)
|
||||
*/
|
||||
class C2SUnlinkP2P(var p2pId: Long = NONE_SELECTED, var type: Int = TUNNEL_ANY): IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
p2pId = buf.readLong()
|
||||
type = buf.readByte().toInt()
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
buf.writeLong(p2pId)
|
||||
buf.writeByte(type)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Client -> C2SUnlinkP2P -> Server
|
||||
* Handler on server side
|
||||
*/
|
||||
class ServerUnlinkP2PHandler : IMessageHandler<C2SUnlinkP2P, S2CListP2P?> {
|
||||
override fun onMessage(message: C2SUnlinkP2P, ctx: MessageContext): S2CListP2P? {
|
||||
val status = P2PCache.statusMap[ctx.serverHandler.playerEntity.uniqueID] ?: return null
|
||||
|
||||
unlinkP2P(ctx.serverHandler.playerEntity, message.p2pId, status)
|
||||
status.lastP2PType = message.type
|
||||
val tunnelType = BetterP2P.proxy.getP2PFromIndex(message.type)
|
||||
if (tunnelType != null) {
|
||||
listTargetGridP2P(status.grid, status.player, tunnelType.clazz)
|
||||
} else {
|
||||
listAllGridP2P(status.grid, status.player)
|
||||
}
|
||||
ModNetwork.queueP2PListUpdate(status, ctx.serverHandler.playerEntity)
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import com.projecturanus.betterp2p.capability.MemoryInfo
|
||||
import com.projecturanus.betterp2p.client.gui.widget.GuiScale
|
||||
import com.projecturanus.betterp2p.item.BetterMemoryCardModes
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
||||
fun writeMemoryInfo(buf: ByteBuf, info: MemoryInfo) {
|
||||
buf.writeLong(info.selectedEntry)
|
||||
buf.writeLong(info.frequency)
|
||||
buf.writeInt(info.mode.ordinal)
|
||||
buf.writeByte(info.gui.ordinal)
|
||||
buf.writeByte(info.type)
|
||||
}
|
||||
|
||||
fun readMemoryInfo(buf: ByteBuf): MemoryInfo {
|
||||
val selectedEntry = buf.readLong()
|
||||
val frequency = buf.readLong()
|
||||
val mode = try {
|
||||
BetterMemoryCardModes.values()[buf.readInt()]
|
||||
} catch (e: Exception) {
|
||||
BetterMemoryCardModes.OUTPUT
|
||||
}
|
||||
val gui = try {
|
||||
GuiScale.values()[buf.readByte().toInt()]
|
||||
} catch (e: ArrayIndexOutOfBoundsException) {
|
||||
GuiScale.DYNAMIC
|
||||
}
|
||||
val type = buf.readByte().toInt()
|
||||
return MemoryInfo(selectedEntry, frequency, mode, gui, type)
|
||||
}
|
||||
|
||||
/**
|
||||
* Request from client -> server
|
||||
*/
|
||||
class C2SUpdateInfo(var info: MemoryInfo = MemoryInfo()) : IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
info = readMemoryInfo(buf)
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
writeMemoryInfo(buf, info)
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import com.projecturanus.betterp2p.client.gui.GuiAdvancedMemoryCard
|
||||
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 cpw.mods.fml.relauncher.Side
|
||||
import cpw.mods.fml.relauncher.SideOnly
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
class ClientOpenGuiHandler : IMessageHandler<S2CListP2P, IMessage?> {
|
||||
@SideOnly(Side.CLIENT)
|
||||
override fun onMessage(message: S2CListP2P, ctx: MessageContext): IMessage? {
|
||||
val gui = Minecraft.getMinecraft().currentScreen
|
||||
if(gui is GuiAdvancedMemoryCard){
|
||||
gui.refreshInfo(message.infos)
|
||||
}else {
|
||||
Minecraft.getMinecraft().displayGuiScreen(GuiAdvancedMemoryCard(message))
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import com.projecturanus.betterp2p.client.gui.GuiAdvancedMemoryCard
|
||||
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 cpw.mods.fml.relauncher.Side
|
||||
import cpw.mods.fml.relauncher.SideOnly
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
class ClientRefreshInfoHandler : IMessageHandler<S2CRefreshInfo, IMessage?> {
|
||||
@SideOnly(Side.CLIENT)
|
||||
override fun onMessage(message: S2CRefreshInfo, ctx: MessageContext): IMessage? {
|
||||
val gui = Minecraft.getMinecraft().currentScreen
|
||||
if (gui is GuiAdvancedMemoryCard) {
|
||||
gui.refreshInfo(message.infos)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,71 @@
|
||||
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
|
||||
import java.util.Collections
|
||||
import java.util.UUID
|
||||
import java.util.WeakHashMap
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.entity.player.EntityPlayerMP
|
||||
|
||||
import com.projecturanus.betterp2p.MODID
|
||||
import com.projecturanus.betterp2p.network.data.GridServerCache
|
||||
import com.projecturanus.betterp2p.network.data.MemoryInfo
|
||||
import com.projecturanus.betterp2p.network.packet.C2SCloseGui
|
||||
import com.projecturanus.betterp2p.network.packet.C2SLinkP2P
|
||||
import com.projecturanus.betterp2p.network.packet.C2SRefreshP2PList
|
||||
import com.projecturanus.betterp2p.network.packet.C2SRenameP2P
|
||||
import com.projecturanus.betterp2p.network.packet.C2STypeChange
|
||||
import com.projecturanus.betterp2p.network.packet.C2SUnlinkP2P
|
||||
import com.projecturanus.betterp2p.network.packet.C2SUpdateMemoryInfo
|
||||
import com.projecturanus.betterp2p.network.packet.ClientOpenGuiHandler
|
||||
import com.projecturanus.betterp2p.network.packet.ClientUpdateP2PHandler
|
||||
import com.projecturanus.betterp2p.network.packet.S2COpenGui
|
||||
import com.projecturanus.betterp2p.network.packet.S2CUpdateP2P
|
||||
import com.projecturanus.betterp2p.network.packet.ServerCloseGuiHandler
|
||||
import com.projecturanus.betterp2p.network.packet.ServerLinkP2PHandler
|
||||
import com.projecturanus.betterp2p.network.packet.ServerRefreshP2PListHandler
|
||||
import com.projecturanus.betterp2p.network.packet.ServerRenameP2PTunnel
|
||||
import com.projecturanus.betterp2p.network.packet.ServerTypeChangeHandler
|
||||
import com.projecturanus.betterp2p.network.packet.ServerUnlinkP2PHandler
|
||||
import com.projecturanus.betterp2p.network.packet.ServerUpdateInfoHandler
|
||||
|
||||
|
||||
import appeng.api.networking.IGrid
|
||||
import cpw.mods.fml.common.network.NetworkRegistry
|
||||
import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper
|
||||
import cpw.mods.fml.relauncher.Side
|
||||
|
||||
/**
|
||||
* Network cooldown time in milliseconds
|
||||
*/
|
||||
const val NETWORK_CD = 250L
|
||||
|
||||
/**
|
||||
* Mod network manager. Handles server <-> client communication.
|
||||
*/
|
||||
object ModNetwork {
|
||||
val channel: SimpleNetworkWrapper = NetworkRegistry.INSTANCE.newSimpleChannel(MODID)
|
||||
private var netCache: MutableMap<UUID, NetworkState> = mutableMapOf()
|
||||
|
||||
/** For client requests (changing viewed p2p) */
|
||||
val playerState: MutableMap<UUID, PlayerRequest> = Collections.synchronizedMap(WeakHashMap())
|
||||
|
||||
/** Network thread. */
|
||||
private lateinit var networkWorker: ScheduledThreadPoolExecutor
|
||||
|
||||
fun registerNetwork() {
|
||||
channel.registerMessage(ClientOpenGuiHandler::class.java, S2CListP2P::class.java, 0, Side.CLIENT)
|
||||
channel.registerMessage(ClientRefreshInfoHandler::class.java, S2CRefreshInfo::class.java, 1, Side.CLIENT)
|
||||
channel.registerMessage(ServerLinkP2PHandler::class.java, C2SLinkP2P::class.java, 2, Side.SERVER)
|
||||
channel.registerMessage(ServerCloseGuiHandler::class.java, C2SCloseGui::class.java, 3, Side.SERVER)
|
||||
channel.registerMessage(ServerUpdateInfoHandler::class.java, C2SUpdateInfo::class.java, 4, Side.SERVER)
|
||||
channel.registerMessage(ServerTransportHandler::class.java, C2STransportPlayer::class.java, 5, Side.SERVER)
|
||||
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)
|
||||
channel.registerMessage(ServerTypeChangeHandler::class.java, C2STypeChange::class.java, 9, Side.SERVER)
|
||||
var id = 0
|
||||
channel.registerMessage(ClientOpenGuiHandler::class.java, S2COpenGui::class.java, id++, Side.CLIENT)
|
||||
channel.registerMessage(ClientUpdateP2PHandler::class.java, S2CUpdateP2P::class.java, id++, Side.CLIENT)
|
||||
channel.registerMessage(ServerLinkP2PHandler::class.java, C2SLinkP2P::class.java, id++, Side.SERVER)
|
||||
channel.registerMessage(ServerCloseGuiHandler::class.java, C2SCloseGui::class.java, id++, Side.SERVER)
|
||||
channel.registerMessage(ServerUpdateInfoHandler::class.java, C2SUpdateMemoryInfo::class.java, id++, Side.SERVER)
|
||||
channel.registerMessage(ServerRenameP2PTunnel::class.java, C2SRenameP2P::class.java, id++, Side.SERVER)
|
||||
channel.registerMessage(ServerRefreshP2PListHandler::class.java, C2SRefreshP2PList::class.java, id++, Side.SERVER)
|
||||
channel.registerMessage(ServerUnlinkP2PHandler::class.java, C2SUnlinkP2P::class.java, id++, Side.SERVER)
|
||||
channel.registerMessage(ServerTypeChangeHandler::class.java, C2STypeChange::class.java, id, Side.SERVER)
|
||||
networkWorker = ScheduledThreadPoolExecutor(1, ThreadFactory {
|
||||
val th = Thread(it)
|
||||
th.name = "BetterP2P-NetworkWorker"
|
||||
@@ -39,42 +76,78 @@ object ModNetwork {
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function that asks for a p2p update. Multiple requests are bundled into 1.
|
||||
* Utility function that asks for a full refresh of a specific p2p type.
|
||||
*/
|
||||
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
|
||||
fun requestP2PList(player: EntityPlayer, type: Int) {
|
||||
synchronized(playerState) {
|
||||
val playerState = playerState[player.uniqueID] ?: return
|
||||
val cache = playerState.gridCache
|
||||
|
||||
cache.type = type
|
||||
if (playerState.updateReady + NETWORK_CD < System.currentTimeMillis()) {
|
||||
channel.sendTo(S2CUpdateP2P(cache.retrieveP2PList(), true), player as EntityPlayerMP)
|
||||
playerState.updateReady = System.currentTimeMillis() + NETWORK_CD
|
||||
println("Sending now")
|
||||
} else if (!playerState.updatePending) {
|
||||
playerState.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(ModNetwork.playerState) {
|
||||
channel.sendTo(S2CUpdateP2P(cache.retrieveP2PList(), true), player as EntityPlayerMP)
|
||||
playerState.updatePending = false
|
||||
}
|
||||
synchronized(netCache) {
|
||||
state.updatePending = false
|
||||
}
|
||||
}, state.updateReady - System.currentTimeMillis(), TimeUnit.MILLISECONDS)
|
||||
}, playerState.updateReady - System.currentTimeMillis(), TimeUnit.MILLISECONDS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function that asks for a p2p update. Multiple requests are bundled into 1.
|
||||
* If dirty, only an incremental update is sent.
|
||||
*/
|
||||
fun requestP2PUpdate(player: EntityPlayer) {
|
||||
synchronized(playerState) {
|
||||
val playerState = playerState[player.uniqueID] ?: return
|
||||
val cache = playerState.gridCache
|
||||
|
||||
if (playerState.updateReady + NETWORK_CD < System.currentTimeMillis()) {
|
||||
channel.sendTo(S2CUpdateP2P(cache.getP2PUpdates()), player as EntityPlayerMP)
|
||||
playerState.updateReady = System.currentTimeMillis() + NETWORK_CD
|
||||
} else if (!playerState.updatePending) {
|
||||
playerState.updatePending = true
|
||||
networkWorker.schedule({
|
||||
synchronized(ModNetwork.playerState) {
|
||||
channel.sendTo(S2CUpdateP2P(cache.getP2PUpdates()), player as EntityPlayerMP)
|
||||
playerState.updatePending = false
|
||||
}
|
||||
}, playerState.updateReady - System.currentTimeMillis(), TimeUnit.MILLISECONDS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a connection.
|
||||
*/
|
||||
fun initConnection(player: EntityPlayer, grid: IGrid, info: MemoryInfo) {
|
||||
val cache = GridServerCache(grid, player, info.type)
|
||||
|
||||
playerState[player.uniqueID] = PlayerRequest(gridCache = cache)
|
||||
channel.sendTo(S2COpenGui(cache.retrieveP2PList(), info), player as EntityPlayerMP)
|
||||
}
|
||||
|
||||
fun removeConnection(player: EntityPlayer) {
|
||||
playerState.remove(player.uniqueID)
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
networkWorker.shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
internal data class NetworkState(
|
||||
internal var updatePending: Boolean = false,
|
||||
internal var updateReady: Long = System.currentTimeMillis()
|
||||
)
|
||||
|
||||
/**
|
||||
* Network cooldown time in milliseconds
|
||||
* Keeps track of when to send network updates.
|
||||
*/
|
||||
const val NETWORK_CD = 250L
|
||||
|
||||
data class PlayerRequest (
|
||||
internal var updatePending: Boolean = false,
|
||||
internal var updateReady: Long = System.currentTimeMillis(),
|
||||
val gridCache: GridServerCache,
|
||||
)
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import com.projecturanus.betterp2p.client.gui.InfoWrapper
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
class P2PInfo(val frequency: Long,
|
||||
val posX: Int,
|
||||
val posY: Int,
|
||||
val posZ: Int,
|
||||
val world: Int,
|
||||
val facing: ForgeDirection,
|
||||
val name: String,
|
||||
val output: Boolean,
|
||||
val hasChannel: Boolean,
|
||||
// # of channels if ME P2P, or -1 else
|
||||
val channels: Int,
|
||||
// type of p2p, corresponds to registry in proxy
|
||||
val type: Int) {
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return hashP2P(posX, posY, posZ, facing.ordinal, world).hashCode()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return if (other is InfoWrapper) {
|
||||
this.posX == other.posX &&
|
||||
this.posY == other.posY &&
|
||||
this.posZ == other.posZ &&
|
||||
this.facing == other.facing
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import com.projecturanus.betterp2p.capability.MemoryInfo
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
||||
class S2CListP2P(var infos: List<P2PInfo> = emptyList(),
|
||||
var memoryInfo: MemoryInfo = MemoryInfo()) : IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
val length = buf.readInt()
|
||||
val list = ArrayList<P2PInfo>(length)
|
||||
for (i in 0 until length) {
|
||||
list += readInfo(buf)
|
||||
}
|
||||
infos = list
|
||||
memoryInfo = readMemoryInfo(buf)
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
buf.writeInt(infos.size)
|
||||
for (info in infos) {
|
||||
writeInfo(buf, info)
|
||||
}
|
||||
writeMemoryInfo(buf, memoryInfo)
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import io.netty.buffer.ByteBuf
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
fun readInfo(buf: ByteBuf): P2PInfo {
|
||||
val freq = buf.readLong()
|
||||
val posX = buf.readInt()
|
||||
val posY = buf.readInt()
|
||||
val posZ = buf.readInt()
|
||||
val world = buf.readInt()
|
||||
val facing = ForgeDirection.values()[buf.readInt()]
|
||||
val nameLength = buf.readShort() - 1
|
||||
var name = ""
|
||||
for (i in 0..nameLength) {
|
||||
name += buf.readChar()
|
||||
}
|
||||
val output = buf.readBoolean()
|
||||
val hasChannel = buf.readBoolean()
|
||||
val channels = buf.readByte().toInt()
|
||||
val type = buf.readByte().toInt()
|
||||
return P2PInfo(freq, posX, posY, posZ,world, facing, name, output, hasChannel, channels, type)
|
||||
}
|
||||
|
||||
fun writeInfo(buf: ByteBuf, info: P2PInfo) {
|
||||
buf.writeLong(info.frequency)
|
||||
buf.writeInt(info.posX)
|
||||
buf.writeInt(info.posY)
|
||||
buf.writeInt(info.posZ)
|
||||
buf.writeInt(info.world)
|
||||
buf.writeInt(info.facing.ordinal)
|
||||
buf.writeShort(info.name.length)
|
||||
for (c in info.name) {
|
||||
buf.writeChar(c.code)
|
||||
}
|
||||
buf.writeBoolean(info.output)
|
||||
buf.writeBoolean(info.hasChannel)
|
||||
buf.writeByte(info.channels)
|
||||
buf.writeByte(info.type)
|
||||
}
|
||||
|
||||
class S2CRefreshInfo(var infos: List<P2PInfo> = emptyList()) : IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
val length = buf.readInt()
|
||||
val list = ArrayList<P2PInfo>(length)
|
||||
for (i in 0 until length) {
|
||||
list += readInfo(buf)
|
||||
}
|
||||
infos = list
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
buf.writeInt(infos.size)
|
||||
for (info in infos) {
|
||||
writeInfo(buf, info)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import com.projecturanus.betterp2p.util.p2p.P2PCache
|
||||
import com.projecturanus.betterp2p.util.p2p.linkP2P
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler
|
||||
import cpw.mods.fml.common.network.simpleimpl.MessageContext
|
||||
|
||||
class ServerLinkP2PHandler : IMessageHandler<C2SLinkP2P, IMessage?> {
|
||||
override fun onMessage(message: C2SLinkP2P, ctx: MessageContext): IMessage? {
|
||||
val status = P2PCache.statusMap[ctx.serverHandler.playerEntity.uniqueID] ?: return null
|
||||
val result = linkP2P(ctx.serverHandler.playerEntity, message.input, message.output, status)
|
||||
|
||||
if (result != null) {
|
||||
status.listP2P[message.input] = result.first
|
||||
status.listP2P[message.output] = result.second
|
||||
ModNetwork.queueP2PListUpdate(status, ctx.serverHandler.playerEntity)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,21 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import com.projecturanus.betterp2p.util.p2p.P2PCache
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
|
||||
import cpw.mods.fml.common.FMLCommonHandler
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent
|
||||
import cpw.mods.fml.common.gameevent.PlayerEvent
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
|
||||
object ServerPlayerDisconnectHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
fun onLoggedOut(event: PlayerEvent.PlayerLoggedOutEvent) {
|
||||
P2PCache.statusMap.remove(event.player.uniqueID)
|
||||
ModNetwork.removeConnection(event.player)
|
||||
}
|
||||
|
||||
fun register() {
|
||||
val handler = ServerPlayerDisconnectHandler
|
||||
|
||||
MinecraftForge.EVENT_BUS.register(handler)
|
||||
FMLCommonHandler.instance().bus().register(handler)
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
import appeng.api.networking.IGridHost
|
||||
import appeng.api.parts.IPartHost
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
import com.projecturanus.betterp2p.item.ItemAdvancedMemoryCard
|
||||
import com.projecturanus.betterp2p.util.p2p.P2PCache
|
||||
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.tileentity.TileEntity
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.common.DimensionManager
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
/**
|
||||
* Handler for renaming p2p tunnels.
|
||||
*/
|
||||
class ServerRenameP2PTunnel : IMessageHandler<C2SP2PTunnelInfo, IMessage?> {
|
||||
override fun onMessage(message: C2SP2PTunnelInfo, ctx: MessageContext): IMessage? {
|
||||
val world: World = DimensionManager.getWorld(message.info.world)
|
||||
val te: TileEntity = world.getTileEntity(message.info.posX, message.info.posY, message.info.posZ)
|
||||
val cache = P2PCache.statusMap[ctx.serverHandler.playerEntity.uniqueID] ?: return null
|
||||
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.queueP2PListUpdate(cache, ctx.serverHandler.playerEntity, ItemAdvancedMemoryCard.getInfo(cache.player.heldItem))
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
|
||||
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.server.MinecraftServer
|
||||
import net.minecraft.util.ChatComponentText
|
||||
|
||||
class ServerTransportHandler : IMessageHandler<C2STransportPlayer, IMessage?> {
|
||||
|
||||
override fun onMessage(message: C2STransportPlayer, ctx: MessageContext): IMessage? {
|
||||
val player:EntityPlayerMP = ctx.serverHandler.playerEntity
|
||||
val op = MinecraftServer.getServer().configurationManager.func_152596_g(player.gameProfile)
|
||||
if(!op){
|
||||
player.addChatMessage(ChatComponentText("You are not OP"))
|
||||
}else{
|
||||
if(player.worldObj.provider.dimensionId!= message.info.world)
|
||||
player.travelToDimension(message.info.world)
|
||||
player.setPositionAndUpdate(message.info.posX.toDouble(), message.info.posY.toDouble(), message.info.posZ.toDouble())
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
|
||||
import com.projecturanus.betterp2p.item.ItemAdvancedMemoryCard
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler
|
||||
import cpw.mods.fml.common.network.simpleimpl.MessageContext
|
||||
|
||||
class ServerUpdateInfoHandler : IMessageHandler<C2SUpdateInfo, IMessage?> {
|
||||
override fun onMessage(message: C2SUpdateInfo, ctx: MessageContext): IMessage? {
|
||||
val player = ctx.serverHandler.playerEntity
|
||||
val stack = player.heldItem
|
||||
if (stack.item is ItemAdvancedMemoryCard) {
|
||||
ItemAdvancedMemoryCard.writeInfo(stack, message.info)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,354 @@
|
||||
package com.projecturanus.betterp2p.network.data
|
||||
|
||||
import java.lang.IllegalStateException
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.util.ChatComponentTranslation
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
import com.projecturanus.betterp2p.BetterP2P
|
||||
import com.projecturanus.betterp2p.util.p2p.TunnelInfo
|
||||
import com.projecturanus.betterp2p.util.p2p.outputProperty
|
||||
import com.projecturanus.betterp2p.util.p2p.getTypeIndex
|
||||
|
||||
import appeng.api.config.SecurityPermissions
|
||||
import appeng.api.networking.IGrid
|
||||
import appeng.api.networking.security.ISecurityGrid
|
||||
import appeng.api.parts.IPart
|
||||
import appeng.api.parts.PartItemStack
|
||||
import appeng.helpers.IInterfaceHost
|
||||
import appeng.me.GridAccessException
|
||||
import appeng.me.cache.P2PCache
|
||||
import appeng.parts.automation.UpgradeInventory
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
import appeng.parts.p2p.PartP2PTunnelStatic
|
||||
import appeng.tile.inventory.AppEngInternalInventory
|
||||
import appeng.util.Platform
|
||||
|
||||
/**
|
||||
* When the player uses the adv memory card, this is cached on the server side
|
||||
* to provide access to the Grid when the player performs actions in the GUI
|
||||
* Each player has a list of p2ps that will be sent. These are tracked in [listP2P].
|
||||
*/
|
||||
class GridServerCache(private val grid: IGrid, val player: EntityPlayer, var type: Int) {
|
||||
/**
|
||||
* The P2P list. On init, this is the full list.
|
||||
*/
|
||||
private val listP2P: MutableMap<P2PLocation, PartP2PTunnel<*>> = mutableMapOf()
|
||||
|
||||
/**
|
||||
* The dirty P2P list. Updates are accumulated here and sent altogether.
|
||||
*/
|
||||
private val dirtyP2P: MutableSet<P2PLocation> = mutableSetOf()
|
||||
|
||||
init {
|
||||
rebuildList(type)
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the global p2p list
|
||||
*/
|
||||
private fun rebuildList(type: Int) {
|
||||
synchronized(listP2P) {
|
||||
listP2P.clear()
|
||||
dirtyP2P.clear()
|
||||
grid.machinesClasses.forEach {
|
||||
// Find all P2P tunnels...
|
||||
if (it.superclass.superclass == PartP2PTunnel::class.java &&
|
||||
(type == TUNNEL_ANY || BetterP2P.proxy.getP2PFromIndex(type)?.clazz == it)) {
|
||||
grid.getMachines(it).forEach { gridNode ->
|
||||
val p2p = gridNode.machine as PartP2PTunnel<*>
|
||||
listP2P[p2p.toLoc()] = p2p
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes and gets the p2p list of the targeted type
|
||||
* If [type] is [TUNNEL_ANY] or invalid, returns the full list; else filters the list to the
|
||||
* targeted type
|
||||
*/
|
||||
fun retrieveP2PList(): List<P2PInfo> {
|
||||
if (grid is ISecurityGrid && !grid.hasPermission(player, SecurityPermissions.BUILD)) {
|
||||
return emptyList()
|
||||
}
|
||||
rebuildList(type)
|
||||
|
||||
return listP2P.values.mapNotNull {
|
||||
val index = BetterP2P.proxy.getP2PFromClass(it.javaClass)?.index ?: TUNNEL_ANY
|
||||
if (type == TUNNEL_ANY || index == type) {
|
||||
it.toInfo()
|
||||
} else null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entry to the p2p tunnel and marks it as dirty to be sent in the next network update.
|
||||
* Only p2ps of the currently targeted type can be shown
|
||||
*/
|
||||
fun markDirty(key: P2PLocation, p2p: PartP2PTunnel<*>, force: Boolean = false) {
|
||||
synchronized(listP2P) {
|
||||
if (force || type == TUNNEL_ANY || p2p.getTypeIndex() == type) {
|
||||
listP2P[key] = p2p
|
||||
dirtyP2P.add(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of P2Ps that are currently marked dirty, and clears the dirty list.
|
||||
*/
|
||||
fun getP2PUpdates(): List<P2PInfo> {
|
||||
val result = dirtyP2P.mapNotNull {
|
||||
listP2P[it]?.toInfo()
|
||||
}
|
||||
|
||||
dirtyP2P.clear()
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link the two P2P tunnels together. Returns the pair of P2P tunnels on success, or null otherwise.
|
||||
*/
|
||||
fun linkP2P(inputIndex: P2PLocation, outputIndex: P2PLocation):
|
||||
Pair<PartP2PTunnel<*>, PartP2PTunnel<*>>? {
|
||||
// If these calls mess up we have bigger problems...
|
||||
val input = listP2P[inputIndex] ?: return null
|
||||
var output = listP2P[outputIndex] ?: return null
|
||||
|
||||
// Double check security permissions. In theory, the cache won't be set up in the first place
|
||||
// for intruders.
|
||||
if (grid is ISecurityGrid && !grid.hasPermission(player, SecurityPermissions.BUILD)) {
|
||||
return null
|
||||
}
|
||||
|
||||
//change type if necessary
|
||||
if (input.javaClass != output.javaClass) {
|
||||
output = changeP2PType(output, BetterP2P.proxy.getP2PFromClass(input.javaClass)!!) ?: return null
|
||||
}
|
||||
|
||||
// Network loop
|
||||
if (input == output) {
|
||||
return null
|
||||
}
|
||||
|
||||
var frequency = input.frequency
|
||||
val cache = input.proxy.p2P
|
||||
|
||||
// Generate a new frequency if needed
|
||||
if (input.frequency == 0L || input.isOutput) {
|
||||
frequency = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
// If tunnel was already bound, unbind that one
|
||||
if (cache.getInput(frequency) != null) {
|
||||
val originalInput = cache.getInput(frequency)
|
||||
if (originalInput != input) {
|
||||
updateP2P(originalInput.toLoc(), originalInput, frequency, true, input.customName)
|
||||
}
|
||||
}
|
||||
|
||||
// Perform the link
|
||||
val inputResult: PartP2PTunnel<*> = updateP2P(inputIndex, input, frequency, false, input.customName)
|
||||
val outputResult: PartP2PTunnel<*> = updateP2P(outputIndex, output, frequency, true, input.customName)
|
||||
|
||||
// Special case for interfaces
|
||||
if (input is IInterfaceHost && output is IInterfaceHost) {
|
||||
val drops = mutableListOf<ItemStack>()
|
||||
handleInterface(input, output, inputResult as IInterfaceHost, outputResult as IInterfaceHost, drops)
|
||||
Platform.spawnDrops(player.worldObj, output.location.x, output.location.y, output.location.z, drops)
|
||||
}
|
||||
|
||||
return inputResult to outputResult
|
||||
}
|
||||
|
||||
fun unlinkP2P(p2pIndex: P2PLocation): PartP2PTunnel<*>? {
|
||||
val tunnel = listP2P[p2pIndex] ?: return null
|
||||
val oldFreq = tunnel.frequency
|
||||
if (oldFreq == 0L) {
|
||||
return tunnel
|
||||
}
|
||||
|
||||
return updateP2P(p2pIndex, tunnel, 0L, false, tunnel.customName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the p2p tunnel to the frequency, output, and custom name. Removes the old one and replaces it, which lets
|
||||
* AE2 trigger the Grid refresh for us (though we need to update the tunnels ourselves)
|
||||
*/
|
||||
private fun updateP2P(key: P2PLocation, tunnel: PartP2PTunnel<*>, frequency: Long, output: Boolean, name: String): PartP2PTunnel<*> {
|
||||
val side = tunnel.side
|
||||
val data = NBTTagCompound()
|
||||
|
||||
tunnel.host.removePart(side, true)
|
||||
|
||||
val p2pItem: ItemStack = tunnel.getItemStack(PartItemStack.Wrench)
|
||||
|
||||
|
||||
p2pItem.writeToNBT(data)
|
||||
data.setLong("freq", frequency)
|
||||
|
||||
val newType = ItemStack.loadItemStackFromNBT(data)
|
||||
val dir: ForgeDirection = tunnel.host?.addPart(newType, side, player) ?: throw RuntimeException("Cannot bind")
|
||||
val newBus: IPart = tunnel.host.getPart(dir)
|
||||
if (newBus is PartP2PTunnel<*>) {
|
||||
newBus.outputProperty = output
|
||||
if (!name.isBlank()) {
|
||||
newBus.customName = name
|
||||
}
|
||||
try {
|
||||
val p2p = newBus.proxy.p2P
|
||||
p2p.updateFreq(newBus, frequency)
|
||||
} catch (e: GridAccessException) {
|
||||
// :P
|
||||
}
|
||||
newBus.onTunnelNetworkChange()
|
||||
markDirty(key, newBus)
|
||||
return newBus
|
||||
} else {
|
||||
throw IllegalStateException("Cannot bind")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts one P2P into the type
|
||||
*/
|
||||
private fun changeP2PType(tunnel: PartP2PTunnel<*>, newType: TunnelInfo): PartP2PTunnel<*>? {
|
||||
if (BetterP2P.proxy.getP2PFromClass(tunnel.javaClass) == newType) {
|
||||
player.addChatMessage(ChatComponentTranslation("gui.advanced_memory_card.error.same_type"))
|
||||
return null
|
||||
}
|
||||
// Change to a static P2P type = require p2p in inventory
|
||||
if (newType.clazz.superclass == PartP2PTunnelStatic::class.java) {
|
||||
var canConvert = false
|
||||
for ((i, stack) in player.inventory.mainInventory.withIndex()) {
|
||||
if (stack?.isItemEqual(newType.stack) == true) {
|
||||
player.inventory.decrStackSize(i, 1)
|
||||
canConvert = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!canConvert) {
|
||||
player.addChatMessage(ChatComponentTranslation("gui.advanced_memory_card.error.missing_items", 1, newType.stack.displayName))
|
||||
return null
|
||||
}
|
||||
}
|
||||
// Change from a static P2P type = give p2p back to the player
|
||||
if (tunnel is PartP2PTunnelStatic<*>) {
|
||||
val drop = ItemStack.copyItemStack(tunnel.itemStack)
|
||||
drop.stackSize = 1
|
||||
if (!player.inventory.addItemStackToInventory(drop)) {
|
||||
val drops = mutableListOf<ItemStack>(drop)
|
||||
tunnel.getDrops(drops, false)
|
||||
Platform.spawnDrops(player.worldObj, player.serverPosX, player.serverPosY, player.serverPosZ, drops)
|
||||
}
|
||||
}
|
||||
|
||||
val host = tunnel.host
|
||||
host.removePart(tunnel.side, false)
|
||||
val dir = host.addPart(newType.stack, tunnel.side, player)
|
||||
val newPart = host.getPart(dir)
|
||||
if (newPart is PartP2PTunnel<*>) {
|
||||
newPart.outputProperty = tunnel.isOutput
|
||||
try {
|
||||
markDirty(tunnel.toLoc(), newPart, true)
|
||||
val p2p: P2PCache = newPart.proxy.p2P
|
||||
p2p.updateFreq(newPart, tunnel.frequency)
|
||||
return newPart
|
||||
} catch (e: GridAccessException) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts all connected P2Ps to a new type
|
||||
*/
|
||||
fun changeAllP2Ps(p2p: P2PLocation, newType: TunnelInfo): Boolean {
|
||||
if (grid is ISecurityGrid && !grid.hasPermission(player, SecurityPermissions.BUILD)) {
|
||||
return false
|
||||
}
|
||||
|
||||
var tunnel = listP2P[p2p] ?: return false
|
||||
|
||||
try {
|
||||
if (tunnel.isOutput && tunnel.input != null) {
|
||||
tunnel = tunnel.input
|
||||
}
|
||||
|
||||
val outputs = tunnel.outputs.toMutableList()
|
||||
if (newType.clazz.superclass == PartP2PTunnelStatic::class.java) {
|
||||
val amt = outputs.size + 1
|
||||
var hasItems = 0
|
||||
for (stack in player.inventory.mainInventory) {
|
||||
if (stack?.isItemEqual(newType.stack) == true) {
|
||||
hasItems += stack.stackSize
|
||||
if (hasItems >= amt) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasItems < amt) {
|
||||
player.addChatMessage(ChatComponentTranslation("gui.advanced_memory_card.error.missing_items", amt, newType.stack.displayName))
|
||||
return false
|
||||
}
|
||||
}
|
||||
changeP2PType(tunnel, newType)
|
||||
for (o in outputs) {
|
||||
changeP2PType(o, newType)
|
||||
}
|
||||
return true
|
||||
} catch (e: GridAccessException) {
|
||||
// :P
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a p2p interface/dual interface case.
|
||||
*/
|
||||
private fun handleInterface(oldIn: IInterfaceHost, oldOut: IInterfaceHost,
|
||||
newIn: IInterfaceHost, newOut: IInterfaceHost,
|
||||
drops: MutableList<ItemStack>) {
|
||||
// For input and output, retain upgrades, items, and settings.
|
||||
val upgradesIn = oldIn.interfaceDuality.getInventoryByName("upgrades") as UpgradeInventory
|
||||
upgradesIn.forEachIndexed { index, stack ->
|
||||
(newIn.interfaceDuality.getInventoryByName("upgrades") as UpgradeInventory).setInventorySlotContents(index, stack)
|
||||
}
|
||||
val upgradesOut = oldOut.interfaceDuality.getInventoryByName("upgrades") as UpgradeInventory
|
||||
upgradesOut.forEachIndexed { index, stack ->
|
||||
(newOut.interfaceDuality.getInventoryByName("upgrades") as UpgradeInventory).setInventorySlotContents(index, stack)
|
||||
}
|
||||
val itemsIn = oldIn.interfaceDuality.storage as AppEngInternalInventory
|
||||
itemsIn.forEachIndexed { index, stack ->
|
||||
(newIn.interfaceDuality.storage as AppEngInternalInventory).setInventorySlotContents(index, stack)
|
||||
}
|
||||
val itemsOut = oldOut.interfaceDuality.storage as AppEngInternalInventory
|
||||
itemsOut.forEachIndexed { index, stack ->
|
||||
(newOut.interfaceDuality.storage as AppEngInternalInventory).setInventorySlotContents(index, stack)
|
||||
}
|
||||
val settingsIn = oldIn.interfaceDuality.configManager
|
||||
settingsIn.settings.forEach {
|
||||
newIn.configManager.putSetting(it, settingsIn.getSetting(it))
|
||||
}
|
||||
val settingsOut = oldOut.interfaceDuality.configManager
|
||||
settingsOut.settings.forEach {
|
||||
newOut.configManager.putSetting(it, settingsOut.getSetting(it))
|
||||
}
|
||||
|
||||
// For input, just copy the patterns over
|
||||
val patternsIn = oldIn.interfaceDuality.patterns as AppEngInternalInventory
|
||||
patternsIn.forEachIndexed { index, stack ->
|
||||
(newIn.interfaceDuality.patterns as AppEngInternalInventory).setInventorySlotContents(index, stack)
|
||||
}
|
||||
// For output, drop items
|
||||
val patternsOut = oldOut.interfaceDuality.patterns as AppEngInternalInventory
|
||||
drops.addAll(patternsOut)
|
||||
}
|
||||
}
|
||||
+3
-9
@@ -1,8 +1,7 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
package com.projecturanus.betterp2p.network.data
|
||||
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
|
||||
|
||||
/**
|
||||
* Generates a 64-bit hash code from X, Y, Z, Facing, and Dimension info.
|
||||
* bits 0-47: FashHash of (x, y, z) ->
|
||||
@@ -11,11 +10,11 @@ import appeng.parts.p2p.PartP2PTunnel
|
||||
* bit 63: Reserved
|
||||
*/
|
||||
fun hashP2P(x: Int, y: Int, z: Int, facing: Int, dim: Int): Long {
|
||||
var ret = facing.toULong() shl 61
|
||||
val ret = facing.toULong() shl 60
|
||||
val lo: ULong = x.toULong() or (y.toULong() shl 32)
|
||||
val hi: ULong = z.toULong() or (dim.toULong() shl 32)
|
||||
var hash = hashLen16(lo, hi)
|
||||
hash = hash xor (hash shr 60)
|
||||
hash = hash xor (hash shr 59)
|
||||
return (ret or hash).toLong()
|
||||
}
|
||||
|
||||
@@ -54,8 +53,3 @@ private fun hashLen16(lo: ULong, hi: ULong): ULong {
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
/**
|
||||
* Using `0x80000000` to represent none is selected (aka MSB set)
|
||||
*/
|
||||
const val NONE_SELECTED: Long = Long.MIN_VALUE
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.projecturanus.betterp2p.network.data
|
||||
|
||||
import com.projecturanus.betterp2p.client.gui.widget.GuiScale
|
||||
import com.projecturanus.betterp2p.item.BetterMemoryCardModes
|
||||
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
||||
/**
|
||||
* Using `-1` to represent any tunnel type.
|
||||
*/
|
||||
const val TUNNEL_ANY: Int = -1
|
||||
|
||||
/**
|
||||
* A data class for serializing p2p
|
||||
* @param selectedEntry Points to the index of the selected p2p in the list.
|
||||
* @param frequency Selected Frequency. 0 = not selected
|
||||
* @param mode The mode
|
||||
* @param guiScale The saved gui scale
|
||||
* @param type The P2P type, indexed in TunnelInfo.kt
|
||||
*/
|
||||
data class MemoryInfo(
|
||||
var selectedEntry: P2PLocation? = null,
|
||||
var frequency: Long = 0,
|
||||
var mode: BetterMemoryCardModes = BetterMemoryCardModes.OUTPUT,
|
||||
var guiScale: GuiScale = GuiScale.DYNAMIC,
|
||||
var type: Int = TUNNEL_ANY)
|
||||
fun readMemoryInfo(buf: ByteBuf): MemoryInfo {
|
||||
var selectedEntry: P2PLocation? = null
|
||||
if (buf.readBoolean()) {
|
||||
selectedEntry = readP2PLocation(buf)
|
||||
}
|
||||
val frequency = buf.readLong()
|
||||
val mode = try {
|
||||
BetterMemoryCardModes.values()[buf.readInt()]
|
||||
} catch (e: Exception) {
|
||||
BetterMemoryCardModes.OUTPUT
|
||||
}
|
||||
val guiScale = try {
|
||||
GuiScale.values()[buf.readByte().toInt()]
|
||||
} catch (e: ArrayIndexOutOfBoundsException) {
|
||||
GuiScale.DYNAMIC
|
||||
}
|
||||
val type = buf.readByte().toInt()
|
||||
return MemoryInfo(selectedEntry, frequency, mode, guiScale, type)
|
||||
}
|
||||
|
||||
fun writeMemoryInfo(buf: ByteBuf, info: MemoryInfo) {
|
||||
val hasSelected = info.selectedEntry != null
|
||||
|
||||
buf.writeBoolean(hasSelected)
|
||||
if (hasSelected) {
|
||||
writeP2PLocation(buf, info.selectedEntry!!)
|
||||
}
|
||||
buf.writeLong(info.frequency)
|
||||
buf.writeInt(info.mode.ordinal)
|
||||
buf.writeByte(info.guiScale.ordinal)
|
||||
buf.writeByte(info.type)
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.projecturanus.betterp2p.network.data
|
||||
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
import com.projecturanus.betterp2p.util.p2p.getTypeIndex
|
||||
import com.projecturanus.betterp2p.util.p2p.hasChannel
|
||||
|
||||
import appeng.me.GridNode
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
||||
/**
|
||||
* Sent over the network to clients.
|
||||
*/
|
||||
data class P2PInfo(
|
||||
val frequency: Long,
|
||||
val posX: Int,
|
||||
val posY: Int,
|
||||
val posZ: Int,
|
||||
val dim: Int,
|
||||
val facing: ForgeDirection,
|
||||
val name: String,
|
||||
val output: Boolean,
|
||||
val hasChannel: Boolean,
|
||||
// # of channels if ME P2P, or -1 else
|
||||
val channels: Int,
|
||||
// type of p2p, corresponds to registry in proxy
|
||||
val type: Int) {
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return hashP2P(posX, posY, posZ, facing.ordinal, dim).hashCode()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as P2PInfo
|
||||
if (this.posX != other.posX) return false
|
||||
if (this.posY != other.posY) return false
|
||||
if (this.posZ != other.posZ) return false
|
||||
if (facing != other.facing) return false
|
||||
return dim == other.dim
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize the P2P info over network traffic.
|
||||
*/
|
||||
fun readP2PInfo(buf: ByteBuf): P2PInfo? {
|
||||
try {
|
||||
val freq = buf.readLong()
|
||||
val posX = buf.readInt()
|
||||
val posY = buf.readInt()
|
||||
val posZ = buf.readInt()
|
||||
val world = buf.readInt()
|
||||
val facing = ForgeDirection.values()[buf.readInt()]
|
||||
val nameLength = buf.readShort() - 1
|
||||
val name: StringBuilder = StringBuilder()
|
||||
for (i in 0..nameLength) {
|
||||
name.append(buf.readChar())
|
||||
}
|
||||
val output = buf.readBoolean()
|
||||
val hasChannel = buf.readBoolean()
|
||||
val channels = buf.readByte().toInt()
|
||||
val type = buf.readByte().toInt()
|
||||
return P2PInfo(freq, posX, posY, posZ,world, facing, name.toString(), output, hasChannel, channels, type)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the P2P over the network
|
||||
*/
|
||||
fun writeP2PInfo(buf: ByteBuf, info: P2PInfo) {
|
||||
buf.writeLong(info.frequency)
|
||||
buf.writeInt(info.posX)
|
||||
buf.writeInt(info.posY)
|
||||
buf.writeInt(info.posZ)
|
||||
buf.writeInt(info.dim)
|
||||
buf.writeInt(info.facing.ordinal)
|
||||
buf.writeShort(info.name.length)
|
||||
for (c in info.name) {
|
||||
buf.writeChar(c.code)
|
||||
}
|
||||
buf.writeBoolean(info.output)
|
||||
buf.writeBoolean(info.hasChannel)
|
||||
buf.writeByte(info.channels)
|
||||
buf.writeByte(info.type)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to [P2PInfo] by extracting the necessary fields
|
||||
*/
|
||||
fun PartP2PTunnel<*>.toInfo() = P2PInfo(
|
||||
frequency,
|
||||
location.x,
|
||||
location.y,
|
||||
location.z,
|
||||
location.dimension,
|
||||
side,
|
||||
customName,
|
||||
isOutput,
|
||||
hasChannel,
|
||||
(externalFacingNode as? GridNode)?.usedChannels() ?: -1,
|
||||
getTypeIndex())
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Hi reviewer. If you see this message, you should make a comment about it and request changes to remove this ;)
|
||||
*/
|
||||
package com.projecturanus.betterp2p.network.data
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
||||
/**
|
||||
* A simplified version of P2PInfo that holds only location data. This distinction is useful for
|
||||
* client->server interactions
|
||||
*/
|
||||
data class P2PLocation(
|
||||
val x: Int,
|
||||
val y: Int,
|
||||
val z: Int,
|
||||
val facing: ForgeDirection,
|
||||
val dim: Int) {
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return hashP2P(x, y, z, facing.ordinal, dim).hashCode()
|
||||
}
|
||||
|
||||
/**
|
||||
* Autogenerated equals by IntelliJ
|
||||
*/
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as P2PLocation
|
||||
|
||||
if (x != other.x) return false
|
||||
if (y != other.y) return false
|
||||
if (z != other.z) return false
|
||||
if (facing != other.facing) return false
|
||||
return dim == other.dim
|
||||
}
|
||||
}
|
||||
|
||||
fun writeP2PLocation(buf: ByteBuf, loc: P2PLocation) {
|
||||
buf.writeInt(loc.x)
|
||||
buf.writeInt(loc.y)
|
||||
buf.writeInt(loc.z)
|
||||
buf.writeByte(loc.facing.ordinal)
|
||||
buf.writeInt(loc.dim)
|
||||
}
|
||||
|
||||
fun readP2PLocation(buf: ByteBuf): P2PLocation? {
|
||||
return try {
|
||||
P2PLocation(
|
||||
x = buf.readInt(),
|
||||
y = buf.readInt(),
|
||||
z = buf.readInt(),
|
||||
facing = ForgeDirection.values()[buf.readByte().toInt()],
|
||||
dim = buf.readInt())
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun writeP2PLocation(loc: P2PLocation?): NBTTagCompound {
|
||||
val nbt = NBTTagCompound()
|
||||
|
||||
if (loc != null) {
|
||||
nbt.setInteger("x", loc.x)
|
||||
nbt.setInteger("y", loc.y)
|
||||
nbt.setInteger("z", loc.z)
|
||||
nbt.setByte("f", loc.facing.ordinal.toByte())
|
||||
nbt.setInteger("d", loc.dim)
|
||||
}
|
||||
|
||||
return nbt
|
||||
}
|
||||
|
||||
fun readP2PLocation(tag: NBTTagCompound): P2PLocation? {
|
||||
return try {
|
||||
P2PLocation(
|
||||
x = tag.getInteger("x"),
|
||||
y = tag.getInteger("y"),
|
||||
z = tag.getInteger("z"),
|
||||
facing = ForgeDirection.values()[tag.getByte("f").toInt()],
|
||||
dim = tag.getInteger("d"))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun PartP2PTunnel<*>.toLoc() = P2PLocation(location.x, location.y, location.z, side, location.dimension)
|
||||
+13
-3
@@ -1,13 +1,23 @@
|
||||
package com.projecturanus.betterp2p.network
|
||||
package com.projecturanus.betterp2p.network.packet
|
||||
|
||||
import com.projecturanus.betterp2p.network.ModNetwork
|
||||
|
||||
import com.projecturanus.betterp2p.util.p2p.P2PCache
|
||||
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 io.netty.buffer.ByteBuf
|
||||
|
||||
class C2SCloseGui : IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
}
|
||||
}
|
||||
|
||||
class ServerCloseGuiHandler : IMessageHandler<C2SCloseGui, IMessage?> {
|
||||
override fun onMessage(message: C2SCloseGui, ctx: MessageContext): IMessage? {
|
||||
P2PCache.statusMap.remove(ctx.serverHandler.playerEntity.uniqueID)
|
||||
ModNetwork.playerState.remove(ctx.serverHandler.playerEntity.uniqueID)
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.projecturanus.betterp2p.network.packet
|
||||
|
||||
import com.projecturanus.betterp2p.network.ModNetwork
|
||||
import com.projecturanus.betterp2p.network.data.P2PLocation
|
||||
import com.projecturanus.betterp2p.network.data.readP2PLocation
|
||||
import com.projecturanus.betterp2p.network.data.writeP2PLocation
|
||||
|
||||
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 io.netty.buffer.ByteBuf
|
||||
|
||||
/**
|
||||
* Client->Server packet that links 2 P2Ps together.
|
||||
*/
|
||||
class C2SLinkP2P(var input: P2PLocation? = null, var output: P2PLocation? = null): IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
input = readP2PLocation(buf)
|
||||
output = readP2PLocation(buf)
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
writeP2PLocation(buf, input!!)
|
||||
writeP2PLocation(buf, output!!)
|
||||
}
|
||||
}
|
||||
|
||||
class ServerLinkP2PHandler : IMessageHandler<C2SLinkP2P, IMessage?> {
|
||||
override fun onMessage(message: C2SLinkP2P, ctx: MessageContext): IMessage? {
|
||||
// Validate message
|
||||
if (message.input == null || message.output == null) {
|
||||
return null
|
||||
}
|
||||
val state = ModNetwork.playerState[ctx.serverHandler.playerEntity.uniqueID] ?: return null
|
||||
val result = state.gridCache.linkP2P(message.input!!, message.output!!)
|
||||
|
||||
if (result != null) {
|
||||
ModNetwork.requestP2PUpdate(ctx.serverHandler.playerEntity)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.projecturanus.betterp2p.network.packet
|
||||
|
||||
import com.projecturanus.betterp2p.network.ModNetwork
|
||||
import com.projecturanus.betterp2p.network.data.TUNNEL_ANY
|
||||
|
||||
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 io.netty.buffer.ByteBuf
|
||||
|
||||
/**
|
||||
* Send a request to the server to refresh the p2p list with the given type. This must be validated
|
||||
* by the server side. This is a full refresh (not just an update).
|
||||
*/
|
||||
class C2SRefreshP2PList(var type: Int = TUNNEL_ANY): IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
type = buf.readByte().toInt()
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
buf.writeByte(type)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Server handler.
|
||||
* Handler on server side
|
||||
*/
|
||||
class ServerRefreshP2PListHandler : IMessageHandler<C2SRefreshP2PList, IMessage?> {
|
||||
override fun onMessage(message: C2SRefreshP2PList, ctx: MessageContext): IMessage? {
|
||||
ModNetwork.requestP2PList(ctx.serverHandler.playerEntity, message.type)
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.projecturanus.betterp2p.network.packet
|
||||
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.common.DimensionManager
|
||||
|
||||
import com.projecturanus.betterp2p.network.ModNetwork
|
||||
import com.projecturanus.betterp2p.network.data.P2PLocation
|
||||
import com.projecturanus.betterp2p.network.data.readP2PLocation
|
||||
import com.projecturanus.betterp2p.network.data.writeP2PLocation
|
||||
|
||||
import appeng.api.networking.IGridHost
|
||||
import appeng.api.parts.IPartHost
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
import com.projecturanus.betterp2p.network.data.toLoc
|
||||
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 io.netty.buffer.ByteBuf
|
||||
|
||||
/**
|
||||
* Client->Server packet for rename operation
|
||||
*/
|
||||
class C2SRenameP2P(var p2p: P2PLocation? = null, var name: String = ""): IMessage {
|
||||
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
p2p = readP2PLocation(buf)
|
||||
val length = buf.readInt()
|
||||
val nameB = StringBuilder()
|
||||
for (i in 0 until length) {
|
||||
nameB.append(buf.readChar())
|
||||
}
|
||||
name = nameB.toString()
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
writeP2PLocation(buf, p2p!!)
|
||||
buf.writeInt(name.length)
|
||||
for (c in name) {
|
||||
buf.writeChar(c.code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for renaming p2p tunnels.
|
||||
*/
|
||||
class ServerRenameP2PTunnel : IMessageHandler<C2SRenameP2P, IMessage?> {
|
||||
override fun onMessage(message: C2SRenameP2P, ctx: MessageContext): IMessage? {
|
||||
if (message.p2p == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val world: World = DimensionManager.getWorld(message.p2p!!.dim)
|
||||
val te: TileEntity = world.getTileEntity(message.p2p!!.x, message.p2p!!.y, message.p2p!!.z)
|
||||
val state = ModNetwork.playerState[ctx.serverHandler.playerEntity.uniqueID] ?: return null
|
||||
val facing = message.p2p!!.facing
|
||||
if (te is IGridHost && te.getGridNode(facing) != null) {
|
||||
val partTunnel = (te as IPartHost).getPart(facing)
|
||||
|
||||
if (partTunnel is PartP2PTunnel<*>) {
|
||||
partTunnel.customName = message.name
|
||||
val input: PartP2PTunnel<*> = if (partTunnel.isOutput) {
|
||||
partTunnel.input
|
||||
} else {
|
||||
partTunnel
|
||||
}
|
||||
// Mark all dirty.
|
||||
input.outputs.forEach {
|
||||
state.gridCache.markDirty(it.toLoc(), it)
|
||||
}
|
||||
state.gridCache.markDirty(input.toLoc(), input)
|
||||
|
||||
ModNetwork.requestP2PUpdate(ctx.serverHandler.playerEntity)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.projecturanus.betterp2p.network.packet
|
||||
|
||||
import com.projecturanus.betterp2p.BetterP2P
|
||||
import com.projecturanus.betterp2p.network.ModNetwork
|
||||
import com.projecturanus.betterp2p.network.data.P2PLocation
|
||||
import com.projecturanus.betterp2p.network.data.TUNNEL_ANY
|
||||
import com.projecturanus.betterp2p.network.data.readP2PLocation
|
||||
import com.projecturanus.betterp2p.network.data.writeP2PLocation
|
||||
|
||||
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 io.netty.buffer.ByteBuf
|
||||
|
||||
class C2STypeChange(var newType: Int = TUNNEL_ANY, var p2p: P2PLocation? = null): IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
newType = buf.readByte().toInt()
|
||||
p2p = readP2PLocation(buf)
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
buf.writeByte(newType)
|
||||
writeP2PLocation(buf, p2p!!)
|
||||
}
|
||||
}
|
||||
|
||||
class ServerTypeChangeHandler : IMessageHandler<C2STypeChange, IMessage?> {
|
||||
override fun onMessage(message: C2STypeChange, ctx: MessageContext): IMessage? {
|
||||
// Validate message
|
||||
if (message.p2p == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val state = ModNetwork.playerState[ctx.serverHandler.playerEntity.uniqueID] ?: return null
|
||||
val type = BetterP2P.proxy.getP2PFromIndex(message.newType) ?: return null
|
||||
|
||||
if (state.gridCache.changeAllP2Ps(message.p2p!!, type)) {
|
||||
ModNetwork.requestP2PUpdate(ctx.serverHandler.playerEntity)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.projecturanus.betterp2p.network.packet
|
||||
|
||||
import com.projecturanus.betterp2p.network.ModNetwork
|
||||
import com.projecturanus.betterp2p.network.data.P2PLocation
|
||||
import com.projecturanus.betterp2p.network.data.TUNNEL_ANY
|
||||
import com.projecturanus.betterp2p.network.data.readP2PLocation
|
||||
import com.projecturanus.betterp2p.network.data.writeP2PLocation
|
||||
|
||||
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 io.netty.buffer.ByteBuf
|
||||
|
||||
/**
|
||||
* Unlink input from outputs message (set freq to 0)
|
||||
*/
|
||||
class C2SUnlinkP2P(var p2p: P2PLocation? = null, var type: Int = TUNNEL_ANY): IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
p2p = readP2PLocation(buf)
|
||||
type = buf.readByte().toInt()
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
// Clientside can crash if they want to send faulty packets :P
|
||||
writeP2PLocation(buf, p2p!!)
|
||||
buf.writeByte(type)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Client -> Server
|
||||
* Handler on server side
|
||||
*/
|
||||
class ServerUnlinkP2PHandler : IMessageHandler<C2SUnlinkP2P, S2COpenGui?> {
|
||||
override fun onMessage(message: C2SUnlinkP2P, ctx: MessageContext): S2COpenGui? {
|
||||
// message validation
|
||||
if (message.p2p == null) {
|
||||
return null
|
||||
}
|
||||
val cache = ModNetwork.playerState[ctx.serverHandler.playerEntity.uniqueID] ?: return null
|
||||
|
||||
cache.gridCache.unlinkP2P(message.p2p!!)
|
||||
ModNetwork.requestP2PUpdate(ctx.serverHandler.playerEntity)
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.projecturanus.betterp2p.network.packet
|
||||
|
||||
import com.projecturanus.betterp2p.item.ItemAdvancedMemoryCard
|
||||
import com.projecturanus.betterp2p.network.data.MemoryInfo
|
||||
import com.projecturanus.betterp2p.network.data.readMemoryInfo
|
||||
import com.projecturanus.betterp2p.network.data.writeMemoryInfo
|
||||
|
||||
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 io.netty.buffer.ByteBuf
|
||||
|
||||
/**
|
||||
* Client->Server: Update the advanced memory card data
|
||||
*/
|
||||
class C2SUpdateMemoryInfo(var info: MemoryInfo = MemoryInfo()) : IMessage {
|
||||
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
info = readMemoryInfo(buf)
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
writeMemoryInfo(buf, info)
|
||||
}
|
||||
}
|
||||
|
||||
class ServerUpdateInfoHandler : IMessageHandler<C2SUpdateMemoryInfo, IMessage?> {
|
||||
|
||||
override fun onMessage(message: C2SUpdateMemoryInfo, ctx: MessageContext): IMessage? {
|
||||
val player = ctx.serverHandler.playerEntity
|
||||
val stack = player.heldItem
|
||||
|
||||
if (stack.item is ItemAdvancedMemoryCard) {
|
||||
ItemAdvancedMemoryCard.writeInfo(stack, message.info)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.projecturanus.betterp2p.network.packet
|
||||
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
import com.projecturanus.betterp2p.client.gui.GuiAdvancedMemoryCard
|
||||
import com.projecturanus.betterp2p.network.data.*
|
||||
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 cpw.mods.fml.relauncher.Side
|
||||
import cpw.mods.fml.relauncher.SideOnly
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
||||
/**
|
||||
* A Server->Client packet that sends a list of P2Ps over the net.
|
||||
*/
|
||||
class S2COpenGui(var infos: List<P2PInfo> = emptyList(),
|
||||
var memoryInfo: MemoryInfo = MemoryInfo()) : IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
val length = buf.readInt()
|
||||
val list = ArrayList<P2PInfo>(length)
|
||||
|
||||
for (i in 0 until length) {
|
||||
val info = readP2PInfo(buf)
|
||||
|
||||
if (info != null) {
|
||||
list.add(info)
|
||||
}
|
||||
}
|
||||
|
||||
infos = list
|
||||
memoryInfo = readMemoryInfo(buf)
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
buf.writeInt(infos.size)
|
||||
infos.forEach { writeP2PInfo(buf, it) }
|
||||
writeMemoryInfo(buf, memoryInfo)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler on client side for GUI open.
|
||||
*/
|
||||
class ClientOpenGuiHandler : IMessageHandler<S2COpenGui, IMessage?> {
|
||||
@SideOnly(Side.CLIENT)
|
||||
override fun onMessage(message: S2COpenGui, ctx: MessageContext): IMessage? {
|
||||
val gui = Minecraft.getMinecraft().currentScreen
|
||||
if (gui is GuiAdvancedMemoryCard) {
|
||||
gui.refreshInfo(message.infos)
|
||||
} else {
|
||||
Minecraft.getMinecraft().displayGuiScreen(GuiAdvancedMemoryCard(message))
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.projecturanus.betterp2p.network.packet
|
||||
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
import com.projecturanus.betterp2p.client.gui.GuiAdvancedMemoryCard
|
||||
import com.projecturanus.betterp2p.network.data.P2PInfo
|
||||
import com.projecturanus.betterp2p.network.data.readP2PInfo
|
||||
import com.projecturanus.betterp2p.network.data.writeP2PInfo
|
||||
|
||||
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 cpw.mods.fml.relauncher.Side
|
||||
import cpw.mods.fml.relauncher.SideOnly
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
||||
/**
|
||||
* Server -> Client packet for sending P2P updates. More lightweight than OpenGui.
|
||||
*/
|
||||
class S2CUpdateP2P(var infos: List<P2PInfo> = emptyList(), var clear: Boolean = false): IMessage {
|
||||
override fun fromBytes(buf: ByteBuf) {
|
||||
val length = buf.readInt()
|
||||
val list = ArrayList<P2PInfo>(length)
|
||||
|
||||
for (i in 0 until length) {
|
||||
val info = readP2PInfo(buf)
|
||||
|
||||
if (info != null) {
|
||||
list.add(info)
|
||||
}
|
||||
}
|
||||
|
||||
infos = list
|
||||
clear = buf.readBoolean()
|
||||
}
|
||||
|
||||
override fun toBytes(buf: ByteBuf) {
|
||||
buf.writeInt(infos.size)
|
||||
infos.forEach { writeP2PInfo(buf, it) }
|
||||
buf.writeBoolean(clear)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler on client side for updating P2Ps.
|
||||
*/
|
||||
class ClientUpdateP2PHandler : IMessageHandler<S2CUpdateP2P, IMessage?> {
|
||||
@SideOnly(Side.CLIENT)
|
||||
override fun onMessage(message: S2CUpdateP2P, ctx: MessageContext): IMessage? {
|
||||
val gui = Minecraft.getMinecraft().currentScreen
|
||||
|
||||
if (gui is GuiAdvancedMemoryCard) {
|
||||
if (message.clear) {
|
||||
gui.refreshInfo(message.infos)
|
||||
} else {
|
||||
gui.updateInfo(message.infos)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,16 @@
|
||||
package com.projecturanus.betterp2p.util
|
||||
|
||||
import appeng.api.config.SecurityPermissions
|
||||
import appeng.api.networking.IGrid
|
||||
import appeng.api.networking.security.ISecurityGrid
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.EnumFacing
|
||||
import net.minecraft.util.Vec3
|
||||
import net.minecraft.world.IBlockAccess
|
||||
|
||||
import appeng.api.parts.IPart
|
||||
import appeng.api.parts.IPartHost
|
||||
import appeng.api.parts.SelectedPart
|
||||
import appeng.parts.AEBasePart
|
||||
import appeng.parts.ICableBusContainer
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
import appeng.parts.p2p.PartP2PTunnelNormal
|
||||
import appeng.tile.networking.TileCableBus
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.EnumFacing
|
||||
import net.minecraft.util.Vec3
|
||||
import net.minecraft.world.IBlockAccess
|
||||
|
||||
/**
|
||||
* @see appeng.block.networking.BlockCableBus.cb
|
||||
@@ -37,33 +32,6 @@ fun getPart(w: IBlockAccess, posX: Int, posY: Int, posZ: Int, hitX: Float, hitY:
|
||||
return p?.part
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of p2p in the part's target grid
|
||||
* @param grid Grid
|
||||
* @param player Player to check permission
|
||||
* @param clazz P2P class type
|
||||
* @return a list of p2p tunnel in the target grid, or an empty list
|
||||
*/
|
||||
fun listTargetGridP2P(grid: IGrid?, player: EntityPlayer, clazz: Class<out PartP2PTunnel<*>>): List<PartP2PTunnel<*>> {
|
||||
if (grid is ISecurityGrid)
|
||||
if (!grid.hasPermission(player, SecurityPermissions.BUILD))
|
||||
return emptyList()
|
||||
|
||||
return grid?.getMachines(clazz)?.map { it.machine as PartP2PTunnel<*> }?.toList() ?: emptyList()
|
||||
}
|
||||
|
||||
fun listAllGridP2P(grid: IGrid?, player: EntityPlayer): List<PartP2PTunnel<*>> {
|
||||
if (grid is ISecurityGrid && !grid.hasPermission(player, SecurityPermissions.BUILD))
|
||||
return emptyList()
|
||||
val classes = grid?.machinesClasses?.filter {
|
||||
// Find all P2P tunnels...
|
||||
c -> c.superclass.superclass == PartP2PTunnel::class.java
|
||||
} ?: emptyList()
|
||||
val ret: MutableList<PartP2PTunnel<*>> = mutableListOf()
|
||||
classes.forEach{ c -> ret.addAll(grid?.getMachines(c)?.map { it.machine as PartP2PTunnel<*> } ?: emptyList()) }
|
||||
return ret
|
||||
}
|
||||
|
||||
val AEBasePart.facingPosX: Int?
|
||||
get() =
|
||||
host?.location?.x?.and(side?.offsetX ?: EnumFacing.UP.frontOffsetX)
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
package com.projecturanus.betterp2p.util.p2p
|
||||
|
||||
class LinkException(message: String? = null) : RuntimeException(message)
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.projecturanus.betterp2p.util.p2p
|
||||
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Cache P2P status for client to use
|
||||
*/
|
||||
object P2PCache {
|
||||
val statusMap: MutableMap<UUID, P2PStatus> = Collections.synchronizedMap(WeakHashMap())
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.projecturanus.betterp2p.util.p2p
|
||||
|
||||
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
|
||||
|
||||
/**
|
||||
* When the player uses the adv memory card, this is cached on the server side
|
||||
* to provide access to the Grid when the player performs actions in the GUI.
|
||||
*/
|
||||
class P2PStatus(val grid: IGrid, val player: EntityPlayer, type: Int) {
|
||||
/**
|
||||
* The P2P list. This is a list of all P2Ps, and only the requested
|
||||
* ones are sent.
|
||||
*/
|
||||
val listP2P: MutableMap<Long, PartP2PTunnel<*>> = mutableMapOf()
|
||||
|
||||
/**
|
||||
* Server copy of the p2p currently selected in client
|
||||
*/
|
||||
var lastP2PType: Int = type
|
||||
|
||||
/**
|
||||
* Refreshes the p2p list
|
||||
*/
|
||||
private fun rebuildList() {
|
||||
listP2P.clear()
|
||||
listAllGridP2P(grid, player).forEach { listP2P[hashP2P(it)] = it }
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes and gets the p2p list of the targeted type
|
||||
* @param type if TUNNEL_ANY or invalid, returns the full list; else
|
||||
* filters the list to the targeted type
|
||||
*/
|
||||
fun refresh(type: Int): List<P2PInfo> {
|
||||
rebuildList()
|
||||
return if (type == TUNNEL_ANY) {
|
||||
listP2P.values.map { it.toInfo() }
|
||||
} else {
|
||||
listP2P.values.mapNotNull {
|
||||
if ((BetterP2P.proxy.getP2PFromClass(it.javaClass)?.index ?: TUNNEL_ANY) == type) {
|
||||
it.toInfo()
|
||||
} else null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,258 +1,9 @@
|
||||
package com.projecturanus.betterp2p.util.p2p
|
||||
|
||||
import appeng.api.config.SecurityPermissions
|
||||
import appeng.api.networking.IGrid
|
||||
import appeng.api.networking.security.ISecurityGrid
|
||||
import appeng.api.parts.IPart
|
||||
import appeng.api.parts.PartItemStack
|
||||
import appeng.helpers.IInterfaceHost
|
||||
import appeng.me.GridAccessException
|
||||
import appeng.me.GridNode
|
||||
import appeng.me.cache.P2PCache
|
||||
import appeng.parts.automation.UpgradeInventory
|
||||
import appeng.parts.p2p.PartP2PInterface
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
import appeng.parts.p2p.PartP2PTunnelNormal
|
||||
import appeng.parts.p2p.PartP2PTunnelStatic
|
||||
import appeng.tile.inventory.AppEngInternalInventory
|
||||
import appeng.util.Platform
|
||||
import com.projecturanus.betterp2p.BetterP2P
|
||||
import com.projecturanus.betterp2p.capability.TUNNEL_ANY
|
||||
import com.projecturanus.betterp2p.network.P2PInfo
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.util.ChatComponentText
|
||||
import net.minecraft.util.ChatComponentTranslation
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
import com.projecturanus.betterp2p.network.data.TUNNEL_ANY
|
||||
|
||||
fun linkP2P(player: EntityPlayer, inputIndex: Long, outputIndex: Long, status: P2PStatus) : Pair<PartP2PTunnel<*>, PartP2PTunnel<*>>? {
|
||||
// If these calls mess up we have bigger problems...
|
||||
val input = status.listP2P[inputIndex] ?: return null
|
||||
var output = status.listP2P[outputIndex] ?: return null
|
||||
|
||||
val grid: IGrid? = input.gridNode?.grid
|
||||
if (grid is ISecurityGrid) {
|
||||
if (!grid.hasPermission(player, SecurityPermissions.BUILD) || !grid.hasPermission(player, SecurityPermissions.SECURITY)) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Change to exception
|
||||
if (input.javaClass != output.javaClass) {
|
||||
//change output to input
|
||||
output = changeP2P(output, BetterP2P.proxy.getP2PFromClass(input.javaClass)!!, player) ?: return null
|
||||
}
|
||||
if (input == output) {
|
||||
// Network loop
|
||||
return null
|
||||
}
|
||||
var frequency = input.frequency
|
||||
val cache = input.proxy.p2P
|
||||
// TODO reduce changes
|
||||
if (input.frequency == 0L || input.isOutput) {
|
||||
frequency = System.currentTimeMillis()
|
||||
}
|
||||
// If tunnel was already bound, unbind that one
|
||||
if (cache.getInput(frequency) != null) {
|
||||
val originalInput = cache.getInput(frequency)
|
||||
if (originalInput != input) {
|
||||
updateP2P(originalInput, frequency, true, player, input.customName)
|
||||
}
|
||||
}
|
||||
val inputResult: PartP2PTunnel<*> = updateP2P(input, frequency, false, player, input.customName)
|
||||
val outputResult: PartP2PTunnel<*> = updateP2P(output, frequency, true, player, input.customName)
|
||||
if (input is IInterfaceHost && output is IInterfaceHost) {
|
||||
// For input and output, retain upgrades, items, and settings.
|
||||
inputResult as IInterfaceHost
|
||||
outputResult as IInterfaceHost
|
||||
val upgradesIn = input.interfaceDuality.getInventoryByName("upgrades") as UpgradeInventory
|
||||
upgradesIn.forEachIndexed { index, stack ->
|
||||
(inputResult.interfaceDuality.getInventoryByName("upgrades") as UpgradeInventory).setInventorySlotContents(index, stack)
|
||||
}
|
||||
val upgradesOut = output.interfaceDuality.getInventoryByName("upgrades") as UpgradeInventory
|
||||
upgradesOut.forEachIndexed { index, stack ->
|
||||
(outputResult.interfaceDuality.getInventoryByName("upgrades") as UpgradeInventory).setInventorySlotContents(index, stack)
|
||||
}
|
||||
val itemsIn = input.interfaceDuality.storage as AppEngInternalInventory
|
||||
itemsIn.forEachIndexed { index, stack ->
|
||||
(inputResult.interfaceDuality.storage as AppEngInternalInventory).setInventorySlotContents(index, stack)
|
||||
}
|
||||
val itemsOut = output.interfaceDuality.storage as AppEngInternalInventory
|
||||
itemsOut.forEachIndexed { index, stack ->
|
||||
(outputResult.interfaceDuality.storage as AppEngInternalInventory).setInventorySlotContents(index, stack)
|
||||
}
|
||||
val settingsIn = input.interfaceDuality.configManager
|
||||
settingsIn.settings.forEach {
|
||||
inputResult.configManager.putSetting(it, settingsIn.getSetting(it))
|
||||
}
|
||||
val settingsOut = output.interfaceDuality.configManager
|
||||
settingsOut.settings.forEach {
|
||||
outputResult.configManager.putSetting(it, settingsOut.getSetting(it))
|
||||
}
|
||||
|
||||
// For input, just copy the patterns over
|
||||
val patternsIn = input.interfaceDuality.patterns as AppEngInternalInventory
|
||||
patternsIn.forEachIndexed { index, stack ->
|
||||
(inputResult.interfaceDuality.patterns as AppEngInternalInventory).setInventorySlotContents(index, stack)
|
||||
}
|
||||
// For output, drop items
|
||||
val dropItems = mutableListOf<ItemStack>()
|
||||
val patternsOut = output.interfaceDuality.patterns as AppEngInternalInventory
|
||||
dropItems.addAll(patternsOut)
|
||||
Platform.spawnDrops(player.worldObj, output.location.x, output.location.y, output.location.z, dropItems)
|
||||
}
|
||||
return inputResult to outputResult
|
||||
}
|
||||
|
||||
fun unlinkP2P(player: EntityPlayer, p2pIndex: Long, status: P2PStatus): PartP2PTunnel<*>? {
|
||||
if (status.grid is ISecurityGrid) {
|
||||
if (!status.grid.hasPermission(player, SecurityPermissions.BUILD) ||
|
||||
!status.grid.hasPermission(player, SecurityPermissions.SECURITY)) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
val tunnel = status.listP2P[p2pIndex] ?: return null
|
||||
val oldFreq = tunnel.frequency
|
||||
if (oldFreq == 0L) {
|
||||
return tunnel
|
||||
}
|
||||
|
||||
updateP2P(tunnel, 0L, false, player, tunnel.customName)
|
||||
return tunnel
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts one P2P into the type
|
||||
*/
|
||||
fun changeP2P(tunnel: PartP2PTunnel<*>, newType: TunnelInfo, player: EntityPlayer): PartP2PTunnel<*>? {
|
||||
val grid = tunnel.gridNode.grid
|
||||
if (grid is ISecurityGrid) {
|
||||
if (!grid.hasPermission(player, SecurityPermissions.BUILD) ||
|
||||
!grid.hasPermission(player, SecurityPermissions.SECURITY)) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
if (BetterP2P.proxy.getP2PFromClass(tunnel.javaClass) == newType) {
|
||||
player.addChatMessage(ChatComponentText("P2P already this type."))
|
||||
return null
|
||||
}
|
||||
if (newType.clazz.superclass == PartP2PTunnelStatic::class.java) {
|
||||
var canConvert = false
|
||||
for ((i, stack) in player.inventory.mainInventory.withIndex()) {
|
||||
if (stack?.isItemEqual(newType.stack) == true) {
|
||||
player.inventory.decrStackSize(i, 1)
|
||||
canConvert = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!canConvert) {
|
||||
player.addChatMessage(ChatComponentTranslation("gui.advanced_memory_card.error.missing_items", 1, newType.stack.displayName))
|
||||
return null
|
||||
}
|
||||
}
|
||||
if (tunnel is PartP2PTunnelStatic<*>) {
|
||||
val drop = ItemStack.copyItemStack(tunnel.itemStack)
|
||||
drop.stackSize = 1
|
||||
if (!player.inventory.addItemStackToInventory(drop)) {
|
||||
val drops = mutableListOf<ItemStack>(drop)
|
||||
tunnel.getDrops(drops, false)
|
||||
Platform.spawnDrops(player.worldObj, player.serverPosX, player.serverPosY, player.serverPosZ, drops)
|
||||
}
|
||||
}
|
||||
|
||||
val host = tunnel.host
|
||||
host.removePart(tunnel.side, false)
|
||||
val dir = host.addPart(newType.stack, tunnel.side, player)
|
||||
val newPart = host.getPart(dir)
|
||||
if (newPart is PartP2PTunnel<*>) {
|
||||
newPart.outputProperty = tunnel.isOutput
|
||||
try {
|
||||
val p2p: P2PCache = newPart.proxy.p2P
|
||||
p2p.updateFreq(newPart, tunnel.frequency)
|
||||
return newPart
|
||||
} catch (e: GridAccessException) {
|
||||
// :P
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts all connected P2Ps to a new type
|
||||
*/
|
||||
fun changeAllP2Ps(tunnel: PartP2PTunnel<*>, newType: TunnelInfo, player: EntityPlayer): Boolean {
|
||||
val grid = tunnel.gridNode.grid
|
||||
if (grid is ISecurityGrid) {
|
||||
if (!grid.hasPermission(player, SecurityPermissions.BUILD) ||
|
||||
!grid.hasPermission(player, SecurityPermissions.SECURITY)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (tunnel.isOutput && tunnel.input != null) {
|
||||
return changeAllP2Ps(tunnel.input, newType, player)
|
||||
} else {
|
||||
val outputs = tunnel.outputs.toMutableList()
|
||||
if (newType.clazz.superclass == PartP2PTunnelStatic::class.java) {
|
||||
val amt = outputs.size + 1
|
||||
var hasItems = false
|
||||
for (stack in player.inventory.mainInventory) {
|
||||
if (stack?.isItemEqual(newType.stack) == true && stack.stackSize >= amt) {
|
||||
hasItems = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!hasItems) {
|
||||
player.addChatMessage(ChatComponentTranslation("gui.advanced_memory_card.error.missing_items", amt, newType.stack.displayName))
|
||||
return false
|
||||
}
|
||||
}
|
||||
changeP2P(tunnel, newType, player)
|
||||
for (o in outputs) {
|
||||
changeP2P(o, newType, player)
|
||||
}
|
||||
return true
|
||||
}
|
||||
} catch (e: GridAccessException) {
|
||||
// :P
|
||||
}
|
||||
return false
|
||||
}
|
||||
/**
|
||||
* Due to Applied Energistics' limit
|
||||
*/
|
||||
fun updateP2P(tunnel: PartP2PTunnel<*>, frequency: Long, output: Boolean, player: EntityPlayer, name: String): PartP2PTunnel<*> {
|
||||
val side = tunnel.side
|
||||
val data = NBTTagCompound()
|
||||
|
||||
tunnel.host.removePart(side, true)
|
||||
|
||||
val p2pItem: ItemStack = tunnel.getItemStack(PartItemStack.Wrench)
|
||||
|
||||
tunnel.outputProperty = output
|
||||
tunnel.customName = name
|
||||
|
||||
p2pItem.writeToNBT(data)
|
||||
data.setLong("freq", frequency)
|
||||
|
||||
val newType = ItemStack.loadItemStackFromNBT(data)
|
||||
val dir: ForgeDirection = tunnel.host?.addPart(newType, side, player) ?: throw RuntimeException("Cannot bind")
|
||||
val newBus: IPart = tunnel.host.getPart(dir)
|
||||
if (newBus is PartP2PTunnel<*>) {
|
||||
newBus.outputProperty = output
|
||||
try {
|
||||
val p2p = newBus.proxy.p2P
|
||||
p2p.updateFreq(newBus, frequency)
|
||||
} catch (e: GridAccessException) {
|
||||
// :P
|
||||
}
|
||||
newBus.onTunnelNetworkChange()
|
||||
return newBus
|
||||
} else {
|
||||
throw RuntimeException("Cannot bind")
|
||||
}
|
||||
}
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
|
||||
var PartP2PTunnel<*>.outputProperty
|
||||
get() = isOutput
|
||||
@@ -265,11 +16,6 @@ var PartP2PTunnel<*>.outputProperty
|
||||
val PartP2PTunnel<*>.hasChannel
|
||||
get() = isPowered && isActive
|
||||
|
||||
fun PartP2PTunnel<*>.toInfo()
|
||||
= P2PInfo(frequency, location.x, location.y, location.z, location.dimension, side,
|
||||
customName, isOutput, hasChannel, (externalFacingNode as? GridNode)?.usedChannels() ?: -1,
|
||||
getTypeIndex())
|
||||
|
||||
/**
|
||||
* Get the type index or use TUNNEL_ANY
|
||||
*/
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package com.projecturanus.betterp2p.util.p2p
|
||||
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.IIcon
|
||||
|
||||
import appeng.parts.p2p.PartP2PTunnel
|
||||
|
||||
/**
|
||||
* Common tunnel info to be used on server
|
||||
*/
|
||||
|
||||
@@ -45,3 +45,4 @@ gui.advanced_memory_card.p2p_status.offline=Offline
|
||||
gui.advanced_memory_card.types.filtered=Showing: %s
|
||||
gui.advanced_memory_card.types.any=§aAll
|
||||
gui.advanced_memory_card.error.missing_items=Cannot change P2P type without %dx %s(s).
|
||||
gui.advanced_memory_card.error.same_type=P2P already this type.
|
||||
Reference in new issue
Block a user