added new Keyboard implementation so that keyboard only works on proper sides again, still keeping the old one around for upgrading.

This commit is contained in:
Florian Nücke 2014-02-10 23:40:42 +01:00
parent 9c3e6fca80
commit 81e900bfef
11 changed files with 371 additions and 104 deletions

View File

@ -4,8 +4,8 @@ import cpw.mods.fml.common.registry.GameRegistry
import li.cil.oc.common.block._
import li.cil.oc.common.tileentity
import net.minecraft.item.ItemStack
import net.minecraftforge.oredict.OreDictionary
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.oredict.OreDictionary
object Blocks {
var blockSimple: SimpleDelegator = _
@ -20,6 +20,7 @@ object Blocks {
var case1, case2, case3: Case = _
var diskDrive: DiskDrive = _
var keyboard: Keyboard = _
var keyboardDeprecated: KeyboardDeprecated = _
var powerConverter: PowerConverter = _
var powerDistributor: PowerDistributor = _
var redstone: Redstone = _
@ -43,6 +44,42 @@ object Blocks {
})
}
// IMPORTANT: the multi block must come first, since the sub blocks will
// try to register with it. Also, the order the sub blocks are created in
// must not be changed since that order determines their actual IDs.
adapter = new Adapter(blockSimple)
cable = new Cable(blockSpecial)
capacitor = new Capacitor(blockSimple)
case1 = new Case.Tier1(blockSimpleWithRedstone)
case2 = new Case.Tier2(blockSimpleWithRedstone)
case3 = new Case.Tier3(blockSimpleWithRedstone)
charger = new Charger(blockSimpleWithRedstone)
diskDrive = new DiskDrive(blockSimple)
keyboardDeprecated = new KeyboardDeprecated(blockSpecial)
powerDistributor = new PowerDistributor(blockSimple)
powerConverter = new PowerConverter(blockSimple)
redstone = new Redstone(blockSimpleWithRedstone)
robotAfterimage = new RobotAfterimage(blockSpecial)
robotProxy = new RobotProxy(blockSpecialWithRedstone)
router = new Router(blockSimple)
screen1 = new Screen.Tier1(blockSimpleWithRedstone)
screen2 = new Screen.Tier2(blockSimpleWithRedstone)
screen3 = new Screen.Tier3(blockSimpleWithRedstone)
// For automatic conversion from old format (when screens did not take
// redstone inputs) to keep save format compatible.
blockSimple.subBlocks += screen1
blockSimple.subBlocks += screen2
blockSimple.subBlocks += screen3
// v1.2.0
serverRack = new Rack(blockSpecialWithRedstone)
// v2.0.0
keyboard = new Keyboard()
GameRegistry.registerBlock(keyboard, classOf[Item], Settings.namespace + "keyboard")
GameRegistry.registerBlock(blockSimple, classOf[Item], Settings.namespace + "simple")
GameRegistry.registerBlock(blockSimpleWithRedstone, classOf[Item], Settings.namespace + "simple_redstone")
GameRegistry.registerBlock(blockSpecial, classOf[Item], Settings.namespace + "special")
@ -63,44 +100,13 @@ object Blocks {
GameRegistry.registerTileEntity(classOf[tileentity.Screen], Settings.namespace + "screen")
GameRegistry.registerTileEntity(classOf[tileentity.Rack], Settings.namespace + "serverRack")
// IMPORTANT: the multi block must come first, since the sub blocks will
// try to register with it. Also, the order the sub blocks are created in
// must not be changed since that order determines their actual IDs.
adapter = new Adapter(blockSimple)
cable = new Cable(blockSpecial)
capacitor = new Capacitor(blockSimple)
case1 = new Case.Tier1(blockSimpleWithRedstone)
case2 = new Case.Tier2(blockSimpleWithRedstone)
case3 = new Case.Tier3(blockSimpleWithRedstone)
charger = new Charger(blockSimpleWithRedstone)
diskDrive = new DiskDrive(blockSimple)
keyboard = new Keyboard(blockSpecial)
powerDistributor = new PowerDistributor(blockSimple)
powerConverter = new PowerConverter(blockSimple)
redstone = new Redstone(blockSimpleWithRedstone)
robotAfterimage = new RobotAfterimage(blockSpecial)
robotProxy = new RobotProxy(blockSpecialWithRedstone)
router = new Router(blockSimple)
screen1 = new Screen.Tier1(blockSimpleWithRedstone)
screen2 = new Screen.Tier2(blockSimpleWithRedstone)
screen3 = new Screen.Tier3(blockSimpleWithRedstone)
// For automatic conversion from old format (when screens did not take
// redstone inputs) to keep save format compatible.
blockSimple.subBlocks += screen1
blockSimple.subBlocks += screen2
blockSimple.subBlocks += screen3
// v1.2.0
serverRack = new Rack(blockSpecialWithRedstone)
register("oc:craftingCable", cable.createItemStack())
register("oc:craftingCapacitor", capacitor.createItemStack())
register("oc:craftingCaseTier1", case1.createItemStack())
register("oc:craftingCaseTier2", case2.createItemStack())
register("oc:craftingCaseTier3", case3.createItemStack())
register("oc:craftingDiskDrive", diskDrive.createItemStack())
register("oc:craftingKeyboard", keyboard.createItemStack())
register("oc:craftingKeyboard", keyboardDeprecated.createItemStack())
register("oc:craftingPowerDistributor", powerDistributor.createItemStack())
register("oc:craftingRouter", router.createItemStack())
register("oc:craftingScreenTier1", screen1.createItemStack())

View File

@ -125,7 +125,7 @@ object Recipes {
addRecipe(Blocks.case2.createItemStack(), recipes, "case2")
addRecipe(Blocks.case3.createItemStack(), recipes, "case3")
addRecipe(Blocks.diskDrive.createItemStack(), recipes, "diskDrive")
addRecipe(Blocks.keyboard.createItemStack(), recipes, "keyboard")
addRecipe(new ItemStack(Blocks.keyboard), recipes, "keyboard")
addRecipe(Blocks.powerConverter.createItemStack(), recipes, "powerConverter")
addRecipe(Blocks.powerDistributor.createItemStack(), recipes, "powerDistributor")
addRecipe(Blocks.redstone.createItemStack(), recipes, "redstone")

View File

@ -3,11 +3,11 @@ package li.cil.oc.client
import li.cil.oc.common.inventory.ServerInventory
import li.cil.oc.common.{GuiHandler => CommonGuiHandler, item, tileentity, GuiType}
import li.cil.oc.{Settings, Items}
import net.minecraft.client.Minecraft
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.util.ChatComponentTranslation
import net.minecraft.world.World
import scala.collection.convert.WrapAsScala._
import net.minecraft.util.ChatComponentTranslation
import net.minecraft.client.Minecraft
object GuiHandler extends CommonGuiHandler {
override def getClientGuiElement(id: Int, player: EntityPlayer, world: World, x: Int, y: Int, z: Int): AnyRef =

View File

@ -2,10 +2,10 @@ package li.cil.oc.client
import cpw.mods.fml.common.eventhandler.SubscribeEvent
import cpw.mods.fml.common.network.FMLNetworkEvent.ClientCustomPacketEvent
import li.cil.oc.Settings
import li.cil.oc.common.PacketType
import li.cil.oc.common.tileentity._
import li.cil.oc.common.{PacketHandler => CommonPacketHandler}
import li.cil.oc.Settings
import li.cil.oc.util.PackedColor
import net.minecraft.client.gui.GuiScreen
import net.minecraft.client.Minecraft

View File

@ -2,18 +2,18 @@ package li.cil.oc.client
import cpw.mods.fml.client.registry.{RenderingRegistry, ClientRegistry}
import cpw.mods.fml.common.event.{FMLPreInitializationEvent, FMLPostInitializationEvent, FMLInitializationEvent}
import cpw.mods.fml.common.FMLCommonHandler
import cpw.mods.fml.common.network.NetworkRegistry
import li.cil.oc.client
import li.cil.oc.client.renderer.WirelessNetworkDebugRenderer
import li.cil.oc.client.renderer.block.BlockRenderer
import li.cil.oc.client.renderer.item.UpgradeRenderer
import li.cil.oc.client.renderer.tileentity._
import li.cil.oc.client.renderer.WirelessNetworkDebugRenderer
import li.cil.oc.common.tileentity
import li.cil.oc.common.{Proxy => CommonProxy}
import li.cil.oc.{Items, Settings, OpenComputers}
import net.minecraftforge.client.MinecraftForgeClient
import net.minecraftforge.common.MinecraftForge
import cpw.mods.fml.common.FMLCommonHandler
private[oc] class Proxy extends CommonProxy {
override def preInit(e: FMLPreInitializationEvent) {

View File

@ -2,7 +2,7 @@ package li.cil.oc.client.renderer.block
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler
import li.cil.oc.client.renderer.tileentity.{CableRenderer, RobotRenderer}
import li.cil.oc.common.block.{RobotAfterimage, RobotProxy, Cable, Delegator}
import li.cil.oc.common.block._
import li.cil.oc.common.tileentity
import net.minecraft.block.Block
import net.minecraft.client.renderer.{Tessellator, RenderBlocks}
@ -11,6 +11,7 @@ import net.minecraft.world.IBlockAccess
import net.minecraftforge.common.util.ForgeDirection
import org.lwjgl.opengl.GL11
import li.cil.oc.Blocks
import scala.Some
object BlockRenderer extends ISimpleBlockRenderingHandler {
var getRenderId = -1
@ -41,6 +42,9 @@ object BlockRenderer extends ISimpleBlockRenderingHandler {
case delegator: Delegator[_] =>
delegator.setBlockBoundsForItemRender(metadata)
delegator.preItemRender(metadata)
case simple: SimpleBlock =>
simple.setBlockBoundsForItemRender(metadata)
simple.preItemRender(metadata)
case _ => block.setBlockBoundsForItemRender()
}
renderer.setRenderBoundsFromBlock(block)

View File

@ -1,15 +1,15 @@
package li.cil.oc.common.asm
import cpw.mods.fml.common.Loader
import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper
import cpw.mods.fml.common.Loader
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions
import java.util.logging.{Level, Logger}
import li.cil.oc.util.mods.StargateTech2
import net.minecraft.launchwrapper.{LaunchClassLoader, IClassTransformer}
import net.minecraft.tileentity.TileEntity
import org.objectweb.asm.tree._
import org.objectweb.asm.{ClassWriter, ClassReader}
import scala.collection.convert.WrapAsScala._
import net.minecraft.tileentity.TileEntity
@TransformerExclusions(Array("li.cil.oc.common.asm"))
class ClassTransformer extends IClassTransformer {
@ -22,10 +22,10 @@ class ClassTransformer extends IClassTransformer {
return ensureStargateTechCompatibility(basicClass)
}
else if (basicClass != null
&& !name.startsWith( """net.minecraft.""")
&& !name.startsWith( """net.minecraftforge.""")
&& !name.startsWith( """li.cil.oc.common.asm.""")
&& !name.startsWith( """li.cil.oc.api.""")) {
&& !name.startsWith("""net.minecraft.""")
&& !name.startsWith("""net.minecraftforge.""")
&& !name.startsWith("""li.cil.oc.common.asm.""")
&& !name.startsWith("""li.cil.oc.api.""")) {
val classNode = newClassNode(basicClass)
if (classNode.interfaces.contains("li/cil/oc/api/network/SimpleComponent")) {
try {

View File

@ -18,13 +18,19 @@ class Item(value: Block) extends ItemBlock(value) {
super.addInformation(stack, player, tooltip, advanced)
block match {
case delegator: Delegator[_] => delegator.addInformation(getMetadata(stack.getItemDamage), stack, player, tooltip.asInstanceOf[util.List[String]], advanced)
case _ =>
case _ => block match {
case simple: SimpleBlock => simple.tooltipLines(getMetadata(stack.getItemDamage), stack, player, tooltip.asInstanceOf[util.List[String]], advanced)
case _ =>
}
}
}
override def getRarity(stack: ItemStack) = Delegator.subBlock(stack) match {
case Some(subBlock) => subBlock.rarity
case _ => EnumRarity.common
case _ => block match {
case simple: SimpleBlock => simple.rarity
case _ => EnumRarity.common
}
}
override def getMetadata(itemDamage: Int) = itemDamage

View File

@ -1,73 +1,68 @@
package li.cil.oc.common.block
import java.util
import li.cil.oc.Settings
import li.cil.oc.api
import java.util.Random
import li.cil.oc.common.tileentity
import li.cil.oc.util.Tooltip
import net.minecraft.client.renderer.texture.IIconRegister
import li.cil.oc.{CreativeTab, api, Settings}
import net.minecraft.block.Block
import net.minecraft.block.material.Material
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.util.{AxisAlignedBB, IIcon}
import net.minecraft.world.{IBlockAccess, World}
import net.minecraft.world.{World, IBlockAccess}
import net.minecraftforge.common.util.ForgeDirection
import org.lwjgl.opengl.GL11
import net.minecraft.block.Block
import net.minecraft.item.ItemStack
import java.util
import li.cil.oc.util.Tooltip
class Keyboard(val parent: SpecialDelegator) extends SpecialDelegate {
val unlocalizedName = "Keyboard"
class Keyboard extends SimpleBlock(Material.rock) {
setBlockName("Keyboard")
setBlockTextureName(Settings.resourceDomain + ":keyboard")
setLightOpacity(0)
setCreativeTab(CreativeTab)
var icon: IIcon = null
override def tooltipLines(stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) {
tooltip.addAll(Tooltip.get(unlocalizedName))
override def tooltipLines(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) {
tooltip.addAll(Tooltip.get("Keyboard"))
}
override def icon(side: ForgeDirection) = Some(icon)
override def renderAsNormalBlock = false
override def registerIcons(iconRegister: IIconRegister) = {
icon = iconRegister.registerIcon(Settings.resourceDomain + ":keyboard")
}
override def shouldSideBeRendered(world: IBlockAccess, x: Int, y: Int, z: Int, side: Int) = true
override def shouldSideBeRendered(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = true
override def isOpaqueCube = false
override def hasTileEntity = true
override def isNormalCube = false
override def createTileEntity(world: World) = Some(new tileentity.Keyboard(world.isRemote))
override def hasTileEntity(metadata: Int) = true
override def update(world: World, x: Int, y: Int, z: Int) =
override def createTileEntity(world: World, metadata: Int) = new tileentity.Keyboard(world.isRemote)
override def updateTick(world: World, x: Int, y: Int, z: Int, rng: Random) =
world.getTileEntity(x, y, z) match {
case keyboard: tileentity.Keyboard => api.Network.joinOrCreateNetwork(keyboard)
case _ =>
}
override def canPlaceBlockOnSide(world: World, x: Int, y: Int, z: Int, side: ForgeDirection) =
world.isSideSolid(x + side.offsetX, y + side.offsetY, z + side.offsetZ, side.getOpposite) &&
override def canPlaceBlockOnSide(world: World, x: Int, y: Int, z: Int, side: ForgeDirection) = {
world.isSideSolid(x + side.offsetX, y + side.offsetY, z + side.offsetZ, side) &&
(world.getTileEntity(x + side.offsetX, y + side.offsetY, z + side.offsetZ) match {
case screen: tileentity.Screen => screen.facing != side.getOpposite
case _ => true
})
override def isNormalCube(world: IBlockAccess, x: Int, y: Int, z: Int) = false
override def opacity(world: IBlockAccess, x: Int, y: Int, z: Int) = 0
override def updateBounds(world: IBlockAccess, x: Int, y: Int, z: Int) =
world.getTileEntity(x, y, z) match {
case keyboard: tileentity.Keyboard => parent.setBlockBounds(computeBounds(keyboard.pitch, keyboard.yaw))
case _ => super.updateBounds(world, x, y, z)
}
override def itemBounds() {
parent.setBlockBounds(computeBounds(ForgeDirection.NORTH, ForgeDirection.WEST))
}
override def preItemRender() {
override def doSetBlockBoundsBasedOnState(world: IBlockAccess, x: Int, y: Int, z: Int) =
world.getTileEntity(x, y, z) match {
case keyboard: tileentity.Keyboard => setBlockBounds(keyboard.pitch, keyboard.yaw)
case _ =>
}
override def setBlockBoundsForItemRender(metadata: Int) = setBlockBounds(ForgeDirection.NORTH, ForgeDirection.WEST)
override def preItemRender(metadata: Int) {
GL11.glTranslatef(-0.75f, 0, 0)
GL11.glScalef(1.5f, 1.5f, 1.5f)
}
private def computeBounds(pitch: ForgeDirection, yaw: ForgeDirection) = {
private def setBlockBounds(pitch: ForgeDirection, yaw: ForgeDirection) {
val (forward, up) = pitch match {
case side@(ForgeDirection.DOWN | ForgeDirection.UP) => (side, yaw)
case _ => (yaw, ForgeDirection.UP)
@ -80,32 +75,23 @@ class Keyboard(val parent: SpecialDelegator) extends SpecialDelegate {
val y1 = up.offsetY * sizes(1) + side.offsetY * sizes(2) - forward.offsetY * 0.5f
val z0 = -up.offsetZ * sizes(1) - side.offsetZ * sizes(2) - forward.offsetZ * sizes(0)
val z1 = up.offsetZ * sizes(1) + side.offsetZ * sizes(2) - forward.offsetZ * 0.5f
AxisAlignedBB.getBoundingBox(
setBlockBounds(
math.min(x0, x1) + 0.5f, math.min(y0, y1) + 0.5f, math.min(z0, z1) + 0.5f,
math.max(x0, x1) + 0.5f, math.max(y0, y1) + 0.5f, math.max(z0, z1) + 0.5f)
}
override def neighborBlockChanged(world: World, x: Int, y: Int, z: Int, block: Block) =
override def onNeighborBlockChange(world: World, x: Int, y: Int, z: Int, block: Block) =
world.getTileEntity(x, y, z) match {
case keyboard: tileentity.Keyboard if canPlaceBlockOnSide(world, x, y, z, keyboard.facing.getOpposite) => // Can stay.
case keyboard: tileentity.Keyboard if canPlaceBlockOnSide(world, x, y, z, keyboard.facing.getOpposite.ordinal) => // Can stay.
case _ =>
parent.dropBlockAsItem(world, x, y, z, world.getBlockMetadata(x, y, z), 0)
dropBlockAsItem(world, x, y, z, world.getBlockMetadata(x, y, z), 0)
world.setBlockToAir(x, y, z)
}
override def rightClick(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) =
override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) =
adjacencyInfo(world, x, y, z) match {
case Some((keyboard, screen, sx, sy, sz, facing)) => screen.rightClick(world, sx, sy, sz, player, facing, 0, 0, 0)
case _ => super.rightClick(world, x, y, z, player, side, hitX, hitY, hitZ)
}
def adjacentScreen(world: World, x: Int, y: Int, z: Int) =
adjacencyInfo(world, x, y, z) match {
case Some((_, _, sx, sy, sz, _)) => world.getTileEntity(sx, sy, sz) match {
case screen: tileentity.Screen => Some(screen)
case _ => None
}
case _ => None
case _ => false
}
def adjacencyInfo(world: World, x: Int, y: Int, z: Int) =
@ -145,5 +131,5 @@ class Keyboard(val parent: SpecialDelegator) extends SpecialDelegate {
case _ => None
}
override protected val validRotations_ = null
override def getValidRotations(world: World, x: Int, y: Int, z: Int) = null
}

View File

@ -0,0 +1,153 @@
package li.cil.oc.common.block
import java.util
import li.cil.oc.{Blocks, api, Settings}
import li.cil.oc.common.tileentity
import li.cil.oc.util.Tooltip
import net.minecraft.block.Block
import net.minecraft.client.renderer.texture.IIconRegister
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.util.{MovingObjectPosition, AxisAlignedBB, IIcon}
import net.minecraft.world.{IBlockAccess, World}
import net.minecraftforge.common.util.ForgeDirection
import org.lwjgl.opengl.GL11
class KeyboardDeprecated(val parent: SpecialDelegator) extends SpecialDelegate {
val unlocalizedName = "Keyboard"
var icon: IIcon = null
showInItemList = false
// Phase over to new, proper keyboard.
override def pick(target: MovingObjectPosition, world: World, x: Int, y: Int, z: Int) = new ItemStack(Blocks.keyboard)
override def tooltipLines(stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) {
tooltip.addAll(Tooltip.get(unlocalizedName))
}
override def icon(side: ForgeDirection) = Some(icon)
override def registerIcons(iconRegister: IIconRegister) = {
icon = iconRegister.registerIcon(Settings.resourceDomain + ":keyboard")
}
override def shouldSideBeRendered(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = true
override def hasTileEntity = true
override def createTileEntity(world: World) = Some(new tileentity.Keyboard(world.isRemote))
override def update(world: World, x: Int, y: Int, z: Int) =
world.getTileEntity(x, y, z) match {
case keyboard: tileentity.Keyboard => api.Network.joinOrCreateNetwork(keyboard)
case _ =>
}
override def canPlaceBlockOnSide(world: World, x: Int, y: Int, z: Int, side: ForgeDirection) =
world.isSideSolid(x + side.offsetX, y + side.offsetY, z + side.offsetZ, side.getOpposite) &&
(world.getTileEntity(x + side.offsetX, y + side.offsetY, z + side.offsetZ) match {
case screen: tileentity.Screen => screen.facing != side.getOpposite
case _ => true
})
override def isNormalCube(world: IBlockAccess, x: Int, y: Int, z: Int) = false
override def opacity(world: IBlockAccess, x: Int, y: Int, z: Int) = 0
override def updateBounds(world: IBlockAccess, x: Int, y: Int, z: Int) =
world.getTileEntity(x, y, z) match {
case keyboard: tileentity.Keyboard => parent.setBlockBounds(computeBounds(keyboard.pitch, keyboard.yaw))
case _ => super.updateBounds(world, x, y, z)
}
override def itemBounds() {
parent.setBlockBounds(computeBounds(ForgeDirection.NORTH, ForgeDirection.WEST))
}
override def preItemRender() {
GL11.glTranslatef(-0.75f, 0, 0)
GL11.glScalef(1.5f, 1.5f, 1.5f)
}
private def computeBounds(pitch: ForgeDirection, yaw: ForgeDirection) = {
val (forward, up) = pitch match {
case side@(ForgeDirection.DOWN | ForgeDirection.UP) => (side, yaw)
case _ => (yaw, ForgeDirection.UP)
}
val side = forward.getRotation(up)
val sizes = Array(7f / 16f, 4f / 16f, 7f / 16f)
val x0 = -up.offsetX * sizes(1) - side.offsetX * sizes(2) - forward.offsetX * sizes(0)
val x1 = up.offsetX * sizes(1) + side.offsetX * sizes(2) - forward.offsetX * 0.5f
val y0 = -up.offsetY * sizes(1) - side.offsetY * sizes(2) - forward.offsetY * sizes(0)
val y1 = up.offsetY * sizes(1) + side.offsetY * sizes(2) - forward.offsetY * 0.5f
val z0 = -up.offsetZ * sizes(1) - side.offsetZ * sizes(2) - forward.offsetZ * sizes(0)
val z1 = up.offsetZ * sizes(1) + side.offsetZ * sizes(2) - forward.offsetZ * 0.5f
AxisAlignedBB.getBoundingBox(
math.min(x0, x1) + 0.5f, math.min(y0, y1) + 0.5f, math.min(z0, z1) + 0.5f,
math.max(x0, x1) + 0.5f, math.max(y0, y1) + 0.5f, math.max(z0, z1) + 0.5f)
}
override def neighborBlockChanged(world: World, x: Int, y: Int, z: Int, block: Block) =
world.getTileEntity(x, y, z) match {
case keyboard: tileentity.Keyboard if canPlaceBlockOnSide(world, x, y, z, keyboard.facing.getOpposite) => // Can stay.
case _ =>
parent.dropBlockAsItem(world, x, y, z, world.getBlockMetadata(x, y, z), 0)
world.setBlockToAir(x, y, z)
}
override def rightClick(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) =
adjacencyInfo(world, x, y, z) match {
case Some((keyboard, screen, sx, sy, sz, facing)) => screen.rightClick(world, sx, sy, sz, player, facing, 0, 0, 0)
case _ => super.rightClick(world, x, y, z, player, side, hitX, hitY, hitZ)
}
def adjacentScreen(world: World, x: Int, y: Int, z: Int) =
adjacencyInfo(world, x, y, z) match {
case Some((_, _, sx, sy, sz, _)) => world.getTileEntity(sx, sy, sz) match {
case screen: tileentity.Screen => Some(screen)
case _ => None
}
case _ => None
}
def adjacencyInfo(world: World, x: Int, y: Int, z: Int) =
world.getTileEntity(x, y, z) match {
case keyboard: tileentity.Keyboard =>
val (sx, sy, sz) = (
x + keyboard.facing.getOpposite.offsetX,
y + keyboard.facing.getOpposite.offsetY,
z + keyboard.facing.getOpposite.offsetZ)
Delegator.subBlock(world, sx, sy, sz) match {
case Some(screen: Screen) => Some((keyboard, screen, sx, sy, sz, keyboard.facing.getOpposite))
case _ =>
// Special case #1: check for screen in front of the keyboard.
val forward = keyboard.facing match {
case ForgeDirection.UP | ForgeDirection.DOWN => keyboard.yaw
case _ => ForgeDirection.UP
}
val (sx, sy, sz) = (
x + forward.offsetX,
y + forward.offsetY,
z + forward.offsetZ)
Delegator.subBlock(world, sx, sy, sz) match {
case Some(screen: Screen) => Some((keyboard, screen, sx, sy, sz, forward))
case _ if keyboard.facing != ForgeDirection.UP && keyboard.facing != ForgeDirection.DOWN =>
// Special case #2: check for screen below keyboards on walls.
val (sx, sy, sz) = (
x - forward.offsetX,
y - forward.offsetY,
z - forward.offsetZ)
Delegator.subBlock(world, sx, sy, sz) match {
case Some(screen: Screen) => Some((keyboard, screen, sx, sy, sz, forward.getOpposite))
case _ => None
}
case _ => None
}
}
case _ => None
}
override protected val validRotations_ = null
}

View File

@ -0,0 +1,112 @@
package li.cil.oc.common.block
import cpw.mods.fml.relauncher.{Side, SideOnly}
import java.util
import li.cil.oc.client.renderer.block.BlockRenderer
import li.cil.oc.common.tileentity
import li.cil.oc.Settings
import li.cil.oc.util.ItemCosts
import net.minecraft.block.Block
import net.minecraft.block.material.Material
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.entity.{Entity, EnumCreatureType}
import net.minecraft.item.{EnumRarity, ItemStack}
import net.minecraft.util.Vec3
import net.minecraft.world.{World, IBlockAccess}
import net.minecraftforge.common.util.ForgeDirection
import org.lwjgl.input
class SimpleBlock(material: Material) extends Block(material) {
override def getUnlocalizedName = Settings.namespace + super.getUnlocalizedName
def rarity = EnumRarity.common
def setFacing(world: World, x: Int, y: Int, z: Int, value: ForgeDirection) =
world.getTileEntity(x, y, z) match {
case rotatable: tileentity.Rotatable => rotatable.setFromFacing(value); true
case _ => false
}
def setRotationFromEntityPitchAndYaw(world: World, x: Int, y: Int, z: Int, value: Entity) =
world.getTileEntity(x, y, z) match {
case rotatable: tileentity.Rotatable => rotatable.setFromEntityPitchAndYaw(value); true
case _ => false
}
override def rotateBlock(world: World, x: Int, y: Int, z: Int, axis: ForgeDirection) =
world.getTileEntity(x, y, z) match {
case rotatable: tileentity.Rotatable if rotatable.rotate(axis) => world.markBlockForUpdate(x, y, z); true
case _ => false
}
@SideOnly(Side.CLIENT)
def tooltipLines(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: java.util.List[String], advanced: Boolean) {
if (input.Keyboard.isKeyDown(input.Keyboard.KEY_LMENU)) {
ItemCosts.addTooltip(stack, tooltip.asInstanceOf[util.List[String]])
}
}
@SideOnly(Side.CLIENT)
def preItemRender(metadata: Int) {}
final override def setBlockBoundsForItemRender() = setBlockBoundsForItemRender(0)
def setBlockBoundsForItemRender(metadata: Int) = super.setBlockBoundsForItemRender()
override def getRenderType = BlockRenderer.getRenderId
override def canBeReplacedByLeaves(world: IBlockAccess, x: Int, y: Int, z: Int) = false
override def canCreatureSpawn(creature: EnumCreatureType, world: IBlockAccess, x: Int, y: Int, z: Int) = false
final override def canPlaceBlockOnSide(world: World, x: Int, y: Int, z: Int, side: Int) =
canPlaceBlockOnSide(world, x, y, z, ForgeDirection.getOrientation(side).getOpposite)
def canPlaceBlockOnSide(world: World, x: Int, y: Int, z: Int, side: ForgeDirection) =
super.canPlaceBlockOnSide(world, x, y, z, side.getOpposite.ordinal)
final override def canConnectRedstone(world: IBlockAccess, x: Int, y: Int, z: Int, side: Int) =
canConnectRedstone(world, x, y, z, side match {
case -1 => ForgeDirection.UP
case 0 => ForgeDirection.NORTH
case 1 => ForgeDirection.EAST
case 2 => ForgeDirection.SOUTH
case 3 => ForgeDirection.WEST
})
def canConnectRedstone(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = false
final override def isProvidingStrongPower(world: IBlockAccess, x: Int, y: Int, z: Int, side: Int) =
isProvidingStrongPower(world, x, y, z, ForgeDirection.getOrientation(side).getOpposite)
def isProvidingStrongPower(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) =
isProvidingWeakPower(world, x, y, z, side)
final override def isProvidingWeakPower(world: IBlockAccess, x: Int, y: Int, z: Int, side: Int) =
isProvidingWeakPower(world, x, y, z, ForgeDirection.getOrientation(side).getOpposite)
def isProvidingWeakPower(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = 0
// This function can mess things up badly in single player if not
// synchronized because it sets fields in an instance stored in the
// static block list... which is used by both server and client thread.
// The other place where this is locked is in collisionRayTrace below,
// which seems to be the only built-in function that *logically* depends
// on the state bounds (rest is rendering which is unimportant).
final override def setBlockBoundsBasedOnState(world: IBlockAccess, x: Int, y: Int, z: Int) =
this.synchronized(doSetBlockBoundsBasedOnState(world, x, y, z))
protected def doSetBlockBoundsBasedOnState(world: IBlockAccess, x: Int, y: Int, z: Int) =
super.setBlockBoundsBasedOnState(world, x, y, z)
final override def collisionRayTrace(world: World, x: Int, y: Int, z: Int, origin: Vec3, direction: Vec3) =
this.synchronized(intersect(world, x, y, z, origin, direction))
protected def intersect(world: World, x: Int, y: Int, z: Int, origin: Vec3, direction: Vec3) =
super.collisionRayTrace(world, x, y, z, origin, direction)
final override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float): Boolean =
onBlockActivated(world, x, y, z, player, ForgeDirection.getOrientation(side), hitX, hitY, hitZ)
def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float) = false
}