mirror of
https://github.com/GTNewHorizons/ForgeMultipart.git
synced 2026-11-13 17:04:25 +00:00
Fixed improper AABB culling of multipart tiles Fixed some bounding box highlight issues Added ability for parts to override harvesting
178 lines
6.0 KiB
Scala
178 lines
6.0 KiB
Scala
package codechicken.multipart.handler
|
|
|
|
import codechicken.lib.packet.PacketCustom.IClientPacketHandler
|
|
import codechicken.lib.packet.PacketCustom.IServerPacketHandler
|
|
import codechicken.lib.packet.PacketCustom
|
|
import net.minecraft.client.multiplayer.NetClientHandler
|
|
import net.minecraft.client.Minecraft
|
|
import codechicken.multipart.MultiPartRegistry
|
|
import net.minecraft.network.NetServerHandler
|
|
import net.minecraft.entity.player.EntityPlayerMP
|
|
import codechicken.multipart.TileMultipart
|
|
import codechicken.multipart.ControlKeyModifer
|
|
import codechicken.multipart.TileMultipart
|
|
import net.minecraft.network.packet.Packet255KickDisconnect
|
|
import net.minecraft.server.MinecraftServer
|
|
import net.minecraft.world.World
|
|
import net.minecraft.world.chunk.Chunk
|
|
import java.util.Map
|
|
import java.util.Iterator
|
|
import net.minecraft.tileentity.TileEntity
|
|
import codechicken.multipart.TileMultipart
|
|
import net.minecraft.entity.player.EntityPlayer
|
|
import scala.collection.mutable.{Map => MMap}
|
|
import codechicken.lib.vec.BlockCoord
|
|
import codechicken.lib.data.MCOutputStreamWrapper
|
|
import java.io.DataOutputStream
|
|
import java.io.ByteArrayOutputStream
|
|
import net.minecraft.world.WorldServer
|
|
import net.minecraft.world.ChunkCoordIntPair
|
|
import MultipartProxy._
|
|
import codechicken.multipart.PacketScheduler
|
|
|
|
class MultipartPH
|
|
{
|
|
val channel = MultipartMod
|
|
val registryChannel = "ForgeMultipart"//Must use the 250 system for ID registry as the NetworkMod idMap hasn't been properly initialized from the server yet.
|
|
}
|
|
|
|
object MultipartCPH extends MultipartPH with IClientPacketHandler
|
|
{
|
|
def handlePacket(packet:PacketCustom, netHandler:NetClientHandler, mc:Minecraft)
|
|
{
|
|
packet.getType match
|
|
{
|
|
case 1 => handlePartRegistration(packet, netHandler)
|
|
case 2 => handleCompressedTileDesc(packet, mc.theWorld)
|
|
case 3 => handleCompressedTileData(packet, mc.theWorld)
|
|
}
|
|
}
|
|
|
|
def handlePartRegistration(packet:PacketCustom, netHandler:NetClientHandler)
|
|
{
|
|
val missing = MultiPartRegistry.readIDMap(packet)
|
|
if(!missing.isEmpty)
|
|
netHandler.handleKickDisconnect(new Packet255KickDisconnect("The following multiparts are not installed on this client: "+missing.mkString(", ")))
|
|
}
|
|
|
|
def handleCompressedTileDesc(packet:PacketCustom, world:World)
|
|
{
|
|
val cc = new ChunkCoordIntPair(packet.readInt, packet.readInt)
|
|
val num = packet.readUShort
|
|
for(i <- 0 until num)
|
|
TileMultipart.handleDescPacket(world, indexInChunk(cc, packet.readShort), packet)
|
|
}
|
|
|
|
def handleCompressedTileData(packet:PacketCustom, world:World)
|
|
{
|
|
var x = packet.readInt
|
|
while(x != Int.MaxValue)
|
|
{
|
|
val pos = new BlockCoord(x, packet.readInt, packet.readInt)
|
|
var i = packet.readUByte
|
|
while(i < 255)
|
|
{
|
|
TileMultipart.handlePacket(pos, world, i, packet)
|
|
i = packet.readUByte
|
|
}
|
|
x = packet.readInt
|
|
}
|
|
TileMultipart.flushClientCache()
|
|
}
|
|
}
|
|
|
|
object MultipartSPH extends MultipartPH with IServerPacketHandler
|
|
{
|
|
class MCByteStream(bout:ByteArrayOutputStream) extends MCOutputStreamWrapper(new DataOutputStream(bout))
|
|
{
|
|
def getBytes = bout.toByteArray
|
|
}
|
|
|
|
private val updateMap = MMap[World, MMap[BlockCoord, MCByteStream]]()
|
|
|
|
def handlePacket(packet:PacketCustom, netHandler:NetServerHandler, sender:EntityPlayerMP)
|
|
{
|
|
packet.getType() match
|
|
{
|
|
case 1 => ControlKeyModifer.map.put(sender, packet.readBoolean)
|
|
}
|
|
}
|
|
|
|
def onWorldUnload(world:World)
|
|
{
|
|
if(!world.isRemote)
|
|
updateMap.remove(world)
|
|
}
|
|
|
|
def getTileStream(world:World, pos:BlockCoord) =
|
|
updateMap.getOrElseUpdate(world, {
|
|
if(world.isRemote)
|
|
throw new IllegalArgumentException("Cannot use MultipartSPH on a client world")
|
|
MMap()
|
|
}).getOrElseUpdate(pos, {
|
|
val s = new MCByteStream(new ByteArrayOutputStream)
|
|
s.writeCoord(pos)
|
|
s
|
|
})
|
|
|
|
def onTickEnd(players:Seq[EntityPlayerMP])
|
|
{
|
|
PacketScheduler.sendScheduled()
|
|
|
|
players.foreach{p =>
|
|
val m = updateMap.getOrElse(p.worldObj, null)
|
|
if(m != null && !m.isEmpty)
|
|
{
|
|
val manager = p.worldObj.asInstanceOf[WorldServer].getPlayerManager
|
|
val packet = new PacketCustom(channel, 3).setChunkDataPacket().compressed()
|
|
var send = false
|
|
m.foreach(e =>
|
|
if(manager.isPlayerWatchingChunk(p, e._1.x>>4, e._1.z>>4))
|
|
{
|
|
send = true
|
|
packet.writeByteArray(e._2.getBytes)
|
|
packet.writeByte(255)//terminator
|
|
})
|
|
if(send)
|
|
{
|
|
packet.writeInt(Int.MaxValue)//terminator
|
|
packet.sendToPlayer(p)
|
|
}
|
|
}
|
|
}
|
|
updateMap.foreach(_._2.clear())
|
|
}
|
|
|
|
def onChunkWatch(player:EntityPlayer, chunk:Chunk)
|
|
{
|
|
val pkt = getDescPacket(chunk, chunk.chunkTileEntityMap.asInstanceOf[Map[_, TileEntity]].values.iterator)
|
|
if(pkt != null)
|
|
pkt.sendToPlayer(player)
|
|
}
|
|
|
|
def getDescPacket(chunk:Chunk, it:Iterator[TileEntity]):PacketCustom =
|
|
{
|
|
val s = new MCByteStream(new ByteArrayOutputStream)
|
|
|
|
var num = 0
|
|
while(it.hasNext)
|
|
{
|
|
val tile = it.next
|
|
if(tile.isInstanceOf[TileMultipart])
|
|
{
|
|
s.writeShort(indexInChunk(new BlockCoord(tile)))
|
|
tile.asInstanceOf[TileMultipart].writeDesc(s)
|
|
num+=1
|
|
}
|
|
}
|
|
if(num != 0)
|
|
{
|
|
return new PacketCustom(channel, 2).setChunkDataPacket().compressed()
|
|
.writeInt(chunk.xPosition).writeInt(chunk.zPosition)
|
|
.writeShort(num)
|
|
.writeByteArray(s.getBytes)
|
|
}
|
|
return null;
|
|
}
|
|
}
|