Basic MCMP integration for cables.

This commit is contained in:
Florian Nücke 2016-03-27 18:18:36 +02:00
parent f36e9b918d
commit e90c9ade09
17 changed files with 567 additions and 2 deletions

View File

@ -80,9 +80,13 @@ repositories {
url = "http://mobiusstrip.eu/maven"
}
ivy {
name 'ComputerCraft'
name = "ComputerCraft"
artifactPattern "http://addons-origin.cursecdn.com/files/${config.cc.cf}/[module][revision].[ext]"
}
maven {
name = "MCMP"
url "http://maven.amadornes.com/"
}
/*
maven {
name = "BluePower"
@ -181,6 +185,7 @@ dependencies {
deobfCompile "mezz.jei:jei_1.8.9:${config.jei.version}"
deobfCompile "li.cil.tis3d:TIS-3D:${config.tis3d.version}"
deobfCompile "mcp.mobius.waila:Waila:${config.waila.version}"
deobfCompile "MCMultiPart:MCMultiPart:${config.mcmp.version}:universal"
/*
provided "codechicken:CodeChickenCore:${config.minecraft.version}-${config.ccc.version}:dev"
provided "codechicken:CodeChickenLib:${config.minecraft.version}-${config.ccl.version}:dev"

View File

@ -30,6 +30,7 @@ gt.version=5.04.06
ic2.version=2.2.654-experimental
igwmod.version=1.1.3-18
jei.version=2.28.7.174
mcmp.version=1.0.8
mekanism.build=5
mekanism.version=7.1.2
mfr.cf=2229/626

View File

@ -4,6 +4,8 @@ import li.cil.oc.client.Textures
import li.cil.oc.common.block
import li.cil.oc.common.block.Cable
import li.cil.oc.common.tileentity
import li.cil.oc.integration.Mods
import li.cil.oc.integration.mcmp.PartCableModel
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.Color
import li.cil.oc.util.ExtendedWorld._
@ -35,7 +37,9 @@ object CableModel extends SmartBlockModelBase with ISmartItemModel {
}
override def handleBlockState(state: IBlockState) = state match {
case extended: IExtendedBlockState => new BlockModel(extended)
case extended: IExtendedBlockState =>
if (Mods.MCMultiPart.isAvailable) new PartCableModel.BlockModel(extended)
else new BlockModel(extended)
case _ => missingModel
}

View File

@ -52,6 +52,7 @@ object Mods {
val IndustrialCraft2Classic = new SimpleMod(IDs.IndustrialCraft2Classic, providesPower = true)
val IngameWiki = new SimpleMod(IDs.IngameWiki, version = "@[1.1.3,)")
val JustEnoughItems = new SimpleMod(IDs.JustEnoughItems)
val MCMultiPart = new SimpleMod(IDs.MCMultiPart)
val Mekanism = new SimpleMod(IDs.Mekanism, providesPower = true)
val MekanismGas = new SimpleMod(IDs.MekanismGas)
val Minecraft = new SimpleMod(IDs.Minecraft)
@ -114,6 +115,7 @@ object Mods {
// integration.gc.ModGalacticraft,
// integration.gregtech.ModGregtech,
// integration.ic2.ModIndustrialCraft2,
integration.mcmp.ModMCMultiPart,
// integration.mekanism.ModMekanism,
// integration.mekanism.gas.ModMekanismGas,
// integration.mfr.ModMineFactoryReloaded,
@ -204,6 +206,7 @@ object Mods {
final val IndustrialCraft2Classic = "IC2-Classic"
final val IngameWiki = "IGWMod"
final val JustEnoughItems = "JEI"
final val MCMultiPart = "mcmultipart"
final val Mekanism = "Mekanism"
final val MekanismGas = "MekanismAPI|gas"
final val Minecraft = "Minecraft"

View File

@ -0,0 +1,71 @@
package li.cil.oc.integration.mcmp
import li.cil.oc.Constants
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.internal.Colored
import li.cil.oc.api.network.Environment
import li.cil.oc.api.network.SidedComponent
import li.cil.oc.api.network.SidedEnvironment
import mcmultipart.capabilities.CapabilityWrapperRegistry
import mcmultipart.capabilities.PartAttachCapabilitiesEvent
import mcmultipart.item.PartPlacementWrapper
import mcmultipart.multipart.IMultipart
import mcmultipart.multipart.MultipartRegistry
import net.minecraft.client.resources.model.IBakedModel
import net.minecraft.client.resources.model.ModelResourceLocation
import net.minecraft.util.RegistrySimple
import net.minecraftforge.client.event.ModelBakeEvent
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
object MCMultiPart {
final val CableMultipartLocation = Settings.resourceDomain + ":" + "multipart_" + Constants.BlockName.Cable
final val CableMultipartVariantLocation = new ModelResourceLocation(CableMultipartLocation, "multipart")
def init(): Unit = {
MultipartRegistry.registerPart(classOf[PartCable], PartProvider.PartTypeCable)
MultipartRegistry.registerPartFactory(PartProvider, PartProvider.PartTypeCable)
MultipartRegistry.registerPartConverter(PartConverter)
MultipartRegistry.registerReversePartConverter(PartConverter)
CapabilityWrapperRegistry.registerCapabilityWrapper(WrapperColored)
CapabilityWrapperRegistry.registerCapabilityWrapper(WrapperEnvironment)
CapabilityWrapperRegistry.registerCapabilityWrapper(WrapperSidedEnvironment)
val placementWrapper = new PartPlacementWrapper(api.Items.get(Constants.BlockName.Cable).createItemStack(1), PartProvider)
placementWrapper.register(PartProvider.PartTypeCable)
MinecraftForge.EVENT_BUS.register(this)
}
@SubscribeEvent
def onModelBake(e: ModelBakeEvent): Unit = {
val registry = e.modelRegistry.asInstanceOf[RegistrySimple[ModelResourceLocation, IBakedModel]]
registry.putObject(CableMultipartVariantLocation, PartCableModel)
}
@SubscribeEvent
def onAttachPartCapabilities(event: PartAttachCapabilitiesEvent): Unit = {
event.getPart match {
case part: IMultipart with Environment =>
event.addCapability(PartCapabilityEnvironment.PartProviderEnvironment, new PartCapabilityEnvironment.Provider(part))
case _ =>
}
event.getPart match {
case part: IMultipart with Environment with SidedComponent =>
event.addCapability(PartCapabilitySidedComponent.PartSidedComponent, new PartCapabilitySidedComponent.Provider(part))
case part: IMultipart with SidedEnvironment =>
event.addCapability(PartCapabilitySidedEnvironment.PartProviderSidedEnvironment, new PartCapabilitySidedEnvironment.Provider(part))
case _ =>
}
event.getPart match {
case part: IMultipart with Colored =>
event.addCapability(PartCapabilityColored.PartProviderColored, new PartCapabilityColored.Provider(part))
case _ =>
}
}
}

View File

@ -0,0 +1,12 @@
package li.cil.oc.integration.mcmp
import li.cil.oc.integration.ModProxy
import li.cil.oc.integration.Mods
object ModMCMultiPart extends ModProxy {
override def getMod = Mods.MCMultiPart
override def initialize(): Unit = {
MCMultiPart.init()
}
}

View File

@ -0,0 +1,180 @@
package li.cil.oc.integration.mcmp
import java.util
import li.cil.oc.Constants
import li.cil.oc.api
import li.cil.oc.api.internal.Colored
import li.cil.oc.api.network.Environment
import li.cil.oc.api.network.Message
import li.cil.oc.api.network.Node
import li.cil.oc.common.block.Cable
import li.cil.oc.common.block.property
import li.cil.oc.common.tileentity
import li.cil.oc.util.Color
import mcmultipart.multipart.ISlottedPart
import mcmultipart.multipart.Multipart
import mcmultipart.multipart.PartSlot
import mcmultipart.raytrace.PartMOP
import net.minecraft.block.material.Material
import net.minecraft.block.state.BlockState
import net.minecraft.block.state.IBlockState
import net.minecraft.entity.Entity
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.network.PacketBuffer
import net.minecraft.tileentity.TileEntity
import net.minecraft.util.AxisAlignedBB
import net.minecraftforge.common.property.IExtendedBlockState
import net.minecraftforge.common.property.ExtendedBlockState
class PartCable extends Multipart with ISlottedPart with Environment with Colored {
final val CableDefinition = api.Items.get(Constants.BlockName.Cable)
final val CableBlock = CableDefinition.block()
val wrapped = new tileentity.Cable()
// ----------------------------------------------------------------------- //
// Environment
override def node(): Node = wrapped.node
override def onMessage(message: Message): Unit = wrapped.onMessage(message)
override def onConnect(node: Node): Unit = wrapped.onConnect(node)
override def onDisconnect(node: Node): Unit = wrapped.onDisconnect(node)
// ----------------------------------------------------------------------- //
// Colored
override def getColor = wrapped.getColor
override def setColor(value: Int): Unit = {
if (value != getColor) {
wrapped.setColor(value)
if (getWorld != null && !getWorld.isRemote) {
sendUpdatePacket(true)
}
}
}
override def controlsConnectivity = wrapped.controlsConnectivity
// ----------------------------------------------------------------------- //
// ISlottedPart
override def getSlotMask: util.EnumSet[PartSlot] = util.EnumSet.of(PartSlot.CENTER)
// ----------------------------------------------------------------------- //
// IMultipart
override def addSelectionBoxes(list: util.List[AxisAlignedBB]): Unit = {
if (getWorld != null) {
list.add(Cable.bounds(getWorld, getPos))
}
}
override def addCollisionBoxes(mask: AxisAlignedBB, list: util.List[AxisAlignedBB], collidingEntity: Entity): Unit = {
if (getWorld != null) {
list.add(Cable.bounds(getWorld, getPos)) //.offset(getPos.getX, getPos.getY, getPos.getZ))
}
}
override def getPickBlock(player: EntityPlayer, hit: PartMOP): ItemStack = wrapped.createItemStack()
override def getDrops: util.List[ItemStack] = util.Arrays.asList(wrapped.createItemStack())
override def getHardness(hit: PartMOP): Float = CableBlock.getBlockHardness(getWorld, getPos)
override def getMaterial: Material = CableBlock.getMaterial
override def isToolEffective(toolType: String, level: Int): Boolean = CableBlock.isToolEffective(toolType, getWorld.getBlockState(getPos))
// ----------------------------------------------------------------------- //
override def getModelPath = MCMultiPart.CableMultipartLocation
override def createBlockState(): BlockState = new ExtendedBlockState(CableBlock, Array.empty, Array(property.PropertyTile.Tile))
override def getExtendedState(state: IBlockState): IBlockState =
state match {
case extendedState: IExtendedBlockState =>
wrapped.setWorldObj(getWorld)
wrapped.setPos(getPos)
extendedState.withProperty(property.PropertyTile.Tile, wrapped)
case _ => state
}
override def onAdded(): Unit = {
super.onAdded()
wrapped.validate()
wrapped.setWorldObj(getWorld)
wrapped.setPos(getPos)
}
override def onRemoved(): Unit = {
super.onRemoved()
wrapped.invalidate()
wrapped.setWorldObj(null)
wrapped.setPos(null)
}
override def onLoaded(): Unit = {
super.onLoaded()
wrapped.validate()
wrapped.setWorldObj(getWorld)
wrapped.setPos(getPos)
}
override def onUnloaded(): Unit = {
super.onUnloaded()
wrapped.invalidate()
wrapped.setWorldObj(null)
wrapped.setPos(null)
}
override def onConverted(tile: TileEntity): Unit = {
super.onConverted(tile)
val nbt = new NBTTagCompound()
tile.writeToNBT(nbt)
wrapped.readFromNBT(nbt)
}
// ----------------------------------------------------------------------- //
override def onActivated(player: EntityPlayer, heldItem: ItemStack, hit: PartMOP): Boolean = {
if (Color.isDye(heldItem)) {
setColor(Color.rgbValues(Color.dyeColor(player.getHeldItem)))
markDirty()
if (!player.capabilities.isCreativeMode && wrapped.consumesDye) {
player.getHeldItem.splitStack(1)
}
true
}
else super.onActivated(player, heldItem, hit)
}
// ----------------------------------------------------------------------- //
override def writeToNBT(tag: NBTTagCompound): Unit = {
super.writeToNBT(tag)
wrapped.writeToNBT(tag)
}
override def readFromNBT(tag: NBTTagCompound): Unit = {
super.readFromNBT(tag)
wrapped.readFromNBT(tag)
}
override def writeUpdatePacket(buf: PacketBuffer): Unit = {
super.writeUpdatePacket(buf)
buf.writeInt(getColor)
}
override def readUpdatePacket(buf: PacketBuffer): Unit = {
super.readUpdatePacket(buf)
setColor(buf.readInt())
}
}

View File

@ -0,0 +1,31 @@
package li.cil.oc.integration.mcmp
import li.cil.oc.client.renderer.block.CableModel
import li.cil.oc.client.renderer.block.SmartBlockModelBase
import li.cil.oc.util.BlockPosition
import mcmultipart.client.multipart.ISmartMultipartModel
import mcmultipart.multipart.MultipartHelper
import mcmultipart.multipart.PartSlot
import net.minecraft.block.state.IBlockState
import net.minecraft.client.resources.model.IBakedModel
import net.minecraftforge.common.property.IExtendedBlockState
object PartCableModel extends SmartBlockModelBase with ISmartMultipartModel {
override def handlePartState(state: IBlockState): IBakedModel = state match {
case extended: IExtendedBlockState => new BlockModel(extended)
case _ => missingModel
}
class BlockModel(state: IExtendedBlockState) extends CableModel.BlockModel(state) {
override protected def isCable(pos: BlockPosition): Boolean = super.isCable(pos) || (pos.world match {
case Some(world) =>
val container = MultipartHelper.getPartContainer(world, pos.toBlockPos)
(container != null) && (container.getPartInSlot(PartSlot.CENTER) match {
case cable: PartCable => true
case _ => false
})
case _ => false
})
}
}

View File

@ -0,0 +1,32 @@
package li.cil.oc.integration.mcmp
import li.cil.oc.api.internal.Colored
import li.cil.oc.common.capabilities.Capabilities
import li.cil.oc.integration.Mods
import mcmultipart.multipart.IMultipart
import net.minecraft.util.EnumFacing
import net.minecraft.util.ResourceLocation
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
object PartCapabilityColored {
final val PartProviderColored = new ResourceLocation(Mods.IDs.OpenComputers, "part_colored")
class Provider(val part: IMultipart with Colored) extends ICapabilityProvider with Colored {
override def hasCapability(capability: Capability[_], facing: EnumFacing): Boolean = {
capability == Capabilities.ColoredCapability
}
override def getCapability[T](capability: Capability[T], facing: EnumFacing): T = {
if (hasCapability(capability, facing)) this.asInstanceOf[T]
else null.asInstanceOf[T]
}
override def getColor = part.getColor
override def setColor(value: Int) = part.setColor(value)
override def controlsConnectivity = part.controlsConnectivity
}
}

View File

@ -0,0 +1,36 @@
package li.cil.oc.integration.mcmp
import li.cil.oc.api.network.Environment
import li.cil.oc.api.network.Message
import li.cil.oc.api.network.Node
import li.cil.oc.common.capabilities.Capabilities
import li.cil.oc.integration.Mods
import mcmultipart.multipart.IMultipart
import net.minecraft.util.EnumFacing
import net.minecraft.util.ResourceLocation
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
object PartCapabilityEnvironment {
final val PartProviderEnvironment = new ResourceLocation(Mods.IDs.OpenComputers, "part_environment")
class Provider(val part: IMultipart with Environment) extends ICapabilityProvider with Environment {
override def hasCapability(capability: Capability[_], facing: EnumFacing): Boolean = {
capability == Capabilities.EnvironmentCapability
}
override def getCapability[T](capability: Capability[T], facing: EnumFacing): T = {
if (hasCapability(capability, facing)) this.asInstanceOf[T]
else null.asInstanceOf[T]
}
override def node = part.node
override def onMessage(message: Message) = part.onMessage(message)
override def onConnect(node: Node) = part.onConnect(node)
override def onDisconnect(node: Node) = part.onDisconnect(node)
}
}

View File

@ -0,0 +1,32 @@
package li.cil.oc.integration.mcmp
import li.cil.oc.api.network.Environment
import li.cil.oc.api.network.SidedComponent
import li.cil.oc.api.network.SidedEnvironment
import li.cil.oc.common.capabilities.Capabilities
import li.cil.oc.integration.Mods
import mcmultipart.multipart.IMultipart
import net.minecraft.util.EnumFacing
import net.minecraft.util.ResourceLocation
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
object PartCapabilitySidedComponent {
final val PartSidedComponent = new ResourceLocation(Mods.IDs.OpenComputers, "part_sided_component")
class Provider(val part: IMultipart with Environment with SidedComponent) extends ICapabilityProvider with SidedEnvironment {
override def hasCapability(capability: Capability[_], facing: EnumFacing): Boolean = {
capability == Capabilities.SidedEnvironmentCapability
}
override def getCapability[T](capability: Capability[T], facing: EnumFacing): T = {
if (hasCapability(capability, facing)) this.asInstanceOf[T]
else null.asInstanceOf[T]
}
override def sidedNode(side: EnumFacing) = if (part.canConnectNode(side)) part.node else null
override def canConnect(side: EnumFacing) = part.canConnectNode(side)
}
}

View File

@ -0,0 +1,30 @@
package li.cil.oc.integration.mcmp
import li.cil.oc.api.network.SidedEnvironment
import li.cil.oc.common.capabilities.Capabilities
import li.cil.oc.integration.Mods
import mcmultipart.multipart.IMultipart
import net.minecraft.util.EnumFacing
import net.minecraft.util.ResourceLocation
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
object PartCapabilitySidedEnvironment {
final val PartProviderSidedEnvironment = new ResourceLocation(Mods.IDs.OpenComputers, "sided_environment")
class Provider(val part: IMultipart with SidedEnvironment) extends ICapabilityProvider with SidedEnvironment {
override def hasCapability(capability: Capability[_], facing: EnumFacing): Boolean = {
capability == Capabilities.SidedEnvironmentCapability
}
override def getCapability[T](capability: Capability[T], facing: EnumFacing): T = {
if (hasCapability(capability, facing)) this.asInstanceOf[T]
else null.asInstanceOf[T]
}
override def sidedNode(side: EnumFacing) = part.sidedNode(side)
override def canConnect(side: EnumFacing) = part.canConnect(side)
}
}

View File

@ -0,0 +1,55 @@
package li.cil.oc.integration.mcmp
import java.util
import java.util.Collections
import li.cil.oc.Constants
import li.cil.oc.api
import li.cil.oc.common.EventHandler
import li.cil.oc.common.tileentity.Cable
import li.cil.oc.server.PacketSender
import mcmultipart.multipart.IMultipart
import mcmultipart.multipart.IMultipartContainer
import mcmultipart.multipart.IPartConverter.IPartConverter2
import mcmultipart.multipart.IPartConverter.IReversePartConverter
import net.minecraft.block.Block
import net.minecraft.util.BlockPos
import net.minecraft.world.IBlockAccess
object PartConverter extends IPartConverter2 with IReversePartConverter {
final lazy val CableBlock = api.Items.get(Constants.BlockName.Cable).block()
override def getConvertableBlocks: util.Collection[Block] = Collections.singletonList(CableBlock)
override def convertBlock(world: IBlockAccess, pos: BlockPos, simulated: Boolean): util.Collection[_ <: IMultipart] = {
world.getTileEntity(pos) match {
case tileEntity: Cable =>
val part = new PartCable()
part.setColor(tileEntity.getColor)
Collections.singletonList(part)
case _ => Collections.emptyList()
}
}
override def convertToBlock(container: IMultipartContainer): Boolean = {
val parts = container.getParts
(parts.size() == 1) && (parts.iterator().next() match {
case part: PartCable =>
// TODO Create temporary node bridging hole left by removing multipart, remove after tile entity creation?
val color = part.getColor
val world = container.getWorldIn
val pos = container.getPosIn
world.setBlockToAir(pos)
world.setBlockState(pos, CableBlock.getDefaultState)
world.getTileEntity(pos) match {
case tileEntity: Cable =>
tileEntity.setColor(color)
EventHandler.scheduleServer(() => PacketSender.sendColorChange(tileEntity)) // HACKS!
case _ =>
}
true
case _ =>
false
})
}
}

View File

@ -0,0 +1,31 @@
package li.cil.oc.integration.mcmp
import li.cil.oc.Constants
import li.cil.oc.api
import li.cil.oc.integration.Mods
import mcmultipart.item.IItemMultipartFactory
import mcmultipart.multipart.IMultipart
import mcmultipart.multipart.IPartFactory
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.util.BlockPos
import net.minecraft.util.EnumFacing
import net.minecraft.util.Vec3
import net.minecraft.world.World
object PartProvider extends IPartFactory with IItemMultipartFactory {
final val PartTypeCable = Mods.IDs.OpenComputers + ":cable"
final lazy val CableDescriptor = api.Items.get(Constants.BlockName.Cable)
override def createPart(partType: String, client: Boolean): IMultipart = {
if (partType == PartTypeCable) new PartCable()
else null
}
override def createPart(world: World, pos: BlockPos, side: EnumFacing, hit: Vec3, stack: ItemStack, player: EntityPlayer): IMultipart = {
val descriptor = api.Items.get(stack)
if (descriptor == CableDescriptor) new PartCable()
else null
}
}

View File

@ -0,0 +1,14 @@
package li.cil.oc.integration.mcmp
import java.util
import li.cil.oc.api.internal.Colored
import li.cil.oc.common.capabilities.Capabilities
import mcmultipart.capabilities.ICapabilityWrapper
import net.minecraftforge.common.capabilities.Capability
object WrapperColored extends ICapabilityWrapper[Colored] {
override def getCapability: Capability[Colored] = Capabilities.ColoredCapability
override def wrapImplementations(implementations: util.Collection[Colored]): Colored = implementations.iterator().next()
}

View File

@ -0,0 +1,14 @@
package li.cil.oc.integration.mcmp
import java.util
import li.cil.oc.api.network.Environment
import li.cil.oc.common.capabilities.Capabilities
import mcmultipart.capabilities.ICapabilityWrapper
import net.minecraftforge.common.capabilities.Capability
object WrapperEnvironment extends ICapabilityWrapper[Environment] {
override def getCapability: Capability[Environment] = Capabilities.EnvironmentCapability
override def wrapImplementations(implementations: util.Collection[Environment]): Environment = implementations.iterator().next()
}

View File

@ -0,0 +1,14 @@
package li.cil.oc.integration.mcmp
import java.util
import li.cil.oc.api.network.SidedEnvironment
import li.cil.oc.common.capabilities.Capabilities
import mcmultipart.capabilities.ICapabilityWrapper
import net.minecraftforge.common.capabilities.Capability
object WrapperSidedEnvironment extends ICapabilityWrapper[SidedEnvironment] {
override def getCapability: Capability[SidedEnvironment] = Capabilities.SidedEnvironmentCapability
override def wrapImplementations(implementations: util.Collection[SidedEnvironment]): SidedEnvironment = implementations.iterator().next()
}