From 4417ef0729baecbe6170b7448b270e77d98a5ea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sun, 28 Dec 2014 13:25:43 +0100 Subject: [PATCH] Let this commit stand testament to the many failed attempts at getting ISmartBlockModel to do what I want. And it still ain't workin' yet. --- .../opencomputers/blockstates/case1.json | 12 +- .../opencomputers/blockstates/case2.json | 12 +- .../opencomputers/blockstates/case3.json | 12 +- .../blockstates/caseCreative.json | 12 +- .../opencomputers/blockstates/keyboard.json | 25 +- .../opencomputers/blockstates/screen1.json | 24 +- .../opencomputers/blockstates/screen2.json | 24 +- .../opencomputers/blockstates/screen3.json | 24 +- .../models/block/case_running.json | 7 + .../{CaseBackOn.png => case_back_running.png} | Bin .../{CaseSideOn.png => case_side_running.png} | Bin src/main/scala/li/cil/oc/client/Proxy.scala | 95 +++++-- .../renderer/block/ExtendedBlockModel.scala | 247 ++++++++++++++++++ src/main/scala/li/cil/oc/common/Proxy.scala | 6 +- .../scala/li/cil/oc/common/block/Case.scala | 62 ++--- .../li/cil/oc/common/block/Charger.scala | 2 +- .../li/cil/oc/common/block/DiskDrive.scala | 2 +- .../li/cil/oc/common/block/Keyboard.scala | 13 +- .../scala/li/cil/oc/common/block/Raid.scala | 2 +- .../scala/li/cil/oc/common/block/Screen.scala | 3 +- .../li/cil/oc/common/block/SimpleBlock.scala | 6 - .../cil/oc/common/block/traits/Extended.scala | 103 ++++++++ .../common/block/traits/OmniRotatable.scala | 51 ++-- .../oc/common/block/traits/Rotatable.scala | 44 ++-- .../scala/li/cil/oc/common/init/Items.scala | 18 +- .../common/tileentity/traits/Rotatable.scala | 3 +- .../common/tileentity/traits/TileEntity.scala | 4 +- 27 files changed, 627 insertions(+), 186 deletions(-) create mode 100644 src/main/resources/assets/opencomputers/models/block/case_running.json rename src/main/resources/assets/opencomputers/textures/blocks/{CaseBackOn.png => case_back_running.png} (100%) rename src/main/resources/assets/opencomputers/textures/blocks/{CaseSideOn.png => case_side_running.png} (100%) create mode 100644 src/main/scala/li/cil/oc/client/renderer/block/ExtendedBlockModel.scala create mode 100644 src/main/scala/li/cil/oc/common/block/traits/Extended.scala diff --git a/src/main/resources/assets/opencomputers/blockstates/case1.json b/src/main/resources/assets/opencomputers/blockstates/case1.json index fd8f30415..2ed08635b 100644 --- a/src/main/resources/assets/opencomputers/blockstates/case1.json +++ b/src/main/resources/assets/opencomputers/blockstates/case1.json @@ -1,8 +1,12 @@ { "variants": { - "facing=north": { "model": "opencomputers:case" }, - "facing=south": { "model": "opencomputers:case", "y": 180 }, - "facing=west": { "model": "opencomputers:case", "y": 270 }, - "facing=east": { "model": "opencomputers:case", "y": 90 } + "facing=north,running=false": { "model": "opencomputers:case" }, + "facing=south,running=false": { "model": "opencomputers:case", "y": 180 }, + "facing=west,running=false": { "model": "opencomputers:case", "y": 270 }, + "facing=east,running=false": { "model": "opencomputers:case", "y": 90 }, + "facing=north,running=true": { "model": "opencomputers:case_running" }, + "facing=south,running=true": { "model": "opencomputers:case_running", "y": 180 }, + "facing=west,running=true": { "model": "opencomputers:case_running", "y": 270 }, + "facing=east,running=true": { "model": "opencomputers:case_running", "y": 90 } } } diff --git a/src/main/resources/assets/opencomputers/blockstates/case2.json b/src/main/resources/assets/opencomputers/blockstates/case2.json index fd8f30415..2ed08635b 100644 --- a/src/main/resources/assets/opencomputers/blockstates/case2.json +++ b/src/main/resources/assets/opencomputers/blockstates/case2.json @@ -1,8 +1,12 @@ { "variants": { - "facing=north": { "model": "opencomputers:case" }, - "facing=south": { "model": "opencomputers:case", "y": 180 }, - "facing=west": { "model": "opencomputers:case", "y": 270 }, - "facing=east": { "model": "opencomputers:case", "y": 90 } + "facing=north,running=false": { "model": "opencomputers:case" }, + "facing=south,running=false": { "model": "opencomputers:case", "y": 180 }, + "facing=west,running=false": { "model": "opencomputers:case", "y": 270 }, + "facing=east,running=false": { "model": "opencomputers:case", "y": 90 }, + "facing=north,running=true": { "model": "opencomputers:case_running" }, + "facing=south,running=true": { "model": "opencomputers:case_running", "y": 180 }, + "facing=west,running=true": { "model": "opencomputers:case_running", "y": 270 }, + "facing=east,running=true": { "model": "opencomputers:case_running", "y": 90 } } } diff --git a/src/main/resources/assets/opencomputers/blockstates/case3.json b/src/main/resources/assets/opencomputers/blockstates/case3.json index fd8f30415..2ed08635b 100644 --- a/src/main/resources/assets/opencomputers/blockstates/case3.json +++ b/src/main/resources/assets/opencomputers/blockstates/case3.json @@ -1,8 +1,12 @@ { "variants": { - "facing=north": { "model": "opencomputers:case" }, - "facing=south": { "model": "opencomputers:case", "y": 180 }, - "facing=west": { "model": "opencomputers:case", "y": 270 }, - "facing=east": { "model": "opencomputers:case", "y": 90 } + "facing=north,running=false": { "model": "opencomputers:case" }, + "facing=south,running=false": { "model": "opencomputers:case", "y": 180 }, + "facing=west,running=false": { "model": "opencomputers:case", "y": 270 }, + "facing=east,running=false": { "model": "opencomputers:case", "y": 90 }, + "facing=north,running=true": { "model": "opencomputers:case_running" }, + "facing=south,running=true": { "model": "opencomputers:case_running", "y": 180 }, + "facing=west,running=true": { "model": "opencomputers:case_running", "y": 270 }, + "facing=east,running=true": { "model": "opencomputers:case_running", "y": 90 } } } diff --git a/src/main/resources/assets/opencomputers/blockstates/caseCreative.json b/src/main/resources/assets/opencomputers/blockstates/caseCreative.json index fd8f30415..2ed08635b 100644 --- a/src/main/resources/assets/opencomputers/blockstates/caseCreative.json +++ b/src/main/resources/assets/opencomputers/blockstates/caseCreative.json @@ -1,8 +1,12 @@ { "variants": { - "facing=north": { "model": "opencomputers:case" }, - "facing=south": { "model": "opencomputers:case", "y": 180 }, - "facing=west": { "model": "opencomputers:case", "y": 270 }, - "facing=east": { "model": "opencomputers:case", "y": 90 } + "facing=north,running=false": { "model": "opencomputers:case" }, + "facing=south,running=false": { "model": "opencomputers:case", "y": 180 }, + "facing=west,running=false": { "model": "opencomputers:case", "y": 270 }, + "facing=east,running=false": { "model": "opencomputers:case", "y": 90 }, + "facing=north,running=true": { "model": "opencomputers:case_running" }, + "facing=south,running=true": { "model": "opencomputers:case_running", "y": 180 }, + "facing=west,running=true": { "model": "opencomputers:case_running", "y": 270 }, + "facing=east,running=true": { "model": "opencomputers:case_running", "y": 90 } } } diff --git a/src/main/resources/assets/opencomputers/blockstates/keyboard.json b/src/main/resources/assets/opencomputers/blockstates/keyboard.json index 3db2890cf..579000792 100644 --- a/src/main/resources/assets/opencomputers/blockstates/keyboard.json +++ b/src/main/resources/assets/opencomputers/blockstates/keyboard.json @@ -1,16 +1,17 @@ { "variants": { - "facing=north,up=up": { "model": "opencomputers:keyboard" }, - "facing=south,up=up": { "model": "opencomputers:keyboard", "y": 180 }, - "facing=west,up=up": { "model": "opencomputers:keyboard", "y": 270 }, - "facing=east,up=up": { "model": "opencomputers:keyboard", "y": 90 }, - "facing=up,up=north": { "model": "opencomputers:keyboard", "x": 90 }, - "facing=up,up=south": { "model": "opencomputers:keyboard", "x": 90, "y": 180 }, - "facing=up,up=east": { "model": "opencomputers:keyboard", "x": 90, "y": 270 }, - "facing=up,up=west": { "model": "opencomputers:keyboard", "x": 90, "y": 90 }, - "facing=down,up=north": { "model": "opencomputers:keyboard", "x": -90 }, - "facing=down,up=south": { "model": "opencomputers:keyboard", "x": -90, "y": 180 }, - "facing=down,up=east": { "model": "opencomputers:keyboard", "x": -90, "y": 270 }, - "facing=down,up=west": { "model": "opencomputers:keyboard", "x": -90, "y": 90 } + "normal": { "model": "opencomputers:keyboard" }/*, + "pitch=north,yaw=north": { "model": "opencomputers:keyboard" }, + "pitch=north,yaw=south": { "model": "opencomputers:keyboard", "y": 180 }, + "pitch=north,yaw=east": { "model": "opencomputers:keyboard", "y": 270 }, + "pitch=north,yaw=west": { "model": "opencomputers:keyboard", "y": 90 }, + "pitch=up,yaw=north": { "model": "opencomputers:keyboard", "x": 90 }, + "pitch=up,yaw=south": { "model": "opencomputers:keyboard", "x": 90, "y": 180 }, + "pitch=up,yaw=east": { "model": "opencomputers:keyboard", "x": 90, "y": 270 }, + "pitch=up,yaw=west": { "model": "opencomputers:keyboard", "x": 90, "y": 90 }, + "pitch=down,yaw=north": { "model": "opencomputers:keyboard", "x": -90 }, + "pitch=down,yaw=south": { "model": "opencomputers:keyboard", "x": -90, "y": 180 }, + "pitch=down,yaw=east": { "model": "opencomputers:keyboard", "x": -90, "y": 270 }, + "pitch=down,yaw=west": { "model": "opencomputers:keyboard", "x": -90, "y": 90 } } } diff --git a/src/main/resources/assets/opencomputers/blockstates/screen1.json b/src/main/resources/assets/opencomputers/blockstates/screen1.json index 63ba96081..b54966d25 100644 --- a/src/main/resources/assets/opencomputers/blockstates/screen1.json +++ b/src/main/resources/assets/opencomputers/blockstates/screen1.json @@ -1,16 +1,16 @@ { "variants": { - "facing=north,up=up": { "model": "opencomputers:screen" }, - "facing=south,up=up": { "model": "opencomputers:screen", "y": 180 }, - "facing=west,up=up": { "model": "opencomputers:screen", "y": 270 }, - "facing=east,up=up": { "model": "opencomputers:screen", "y": 90 }, - "facing=up,up=north": { "model": "opencomputers:screen", "x": 90 }, - "facing=up,up=south": { "model": "opencomputers:screen", "x": 90, "y": 180 }, - "facing=up,up=east": { "model": "opencomputers:screen", "x": 90, "y": 270 }, - "facing=up,up=west": { "model": "opencomputers:screen", "x": 90, "y": 90 }, - "facing=down,up=north": { "model": "opencomputers:screen", "x": -90 }, - "facing=down,up=south": { "model": "opencomputers:screen", "x": -90, "y": 180 }, - "facing=down,up=east": { "model": "opencomputers:screen", "x": -90, "y": 270 }, - "facing=down,up=west": { "model": "opencomputers:screen", "x": -90, "y": 90 } + "pitch=north,yaw=north": { "model": "opencomputers:screen" }, + "pitch=north,yaw=south": { "model": "opencomputers:screen", "y": 180 }, + "pitch=north,yaw=east": { "model": "opencomputers:screen", "y": 270 }, + "pitch=north,yaw=west": { "model": "opencomputers:screen", "y": 90 }, + "pitch=up,yaw=north": { "model": "opencomputers:screen", "x": 90 }, + "pitch=up,yaw=south": { "model": "opencomputers:screen", "x": 90, "y": 180 }, + "pitch=up,yaw=east": { "model": "opencomputers:screen", "x": 90, "y": 270 }, + "pitch=up,yaw=west": { "model": "opencomputers:screen", "x": 90, "y": 90 }, + "pitch=down,yaw=north": { "model": "opencomputers:screen", "x": -90 }, + "pitch=down,yaw=south": { "model": "opencomputers:screen", "x": -90, "y": 180 }, + "pitch=down,yaw=east": { "model": "opencomputers:screen", "x": -90, "y": 270 }, + "pitch=down,yaw=west": { "model": "opencomputers:screen", "x": -90, "y": 90 } } } diff --git a/src/main/resources/assets/opencomputers/blockstates/screen2.json b/src/main/resources/assets/opencomputers/blockstates/screen2.json index 63ba96081..b54966d25 100644 --- a/src/main/resources/assets/opencomputers/blockstates/screen2.json +++ b/src/main/resources/assets/opencomputers/blockstates/screen2.json @@ -1,16 +1,16 @@ { "variants": { - "facing=north,up=up": { "model": "opencomputers:screen" }, - "facing=south,up=up": { "model": "opencomputers:screen", "y": 180 }, - "facing=west,up=up": { "model": "opencomputers:screen", "y": 270 }, - "facing=east,up=up": { "model": "opencomputers:screen", "y": 90 }, - "facing=up,up=north": { "model": "opencomputers:screen", "x": 90 }, - "facing=up,up=south": { "model": "opencomputers:screen", "x": 90, "y": 180 }, - "facing=up,up=east": { "model": "opencomputers:screen", "x": 90, "y": 270 }, - "facing=up,up=west": { "model": "opencomputers:screen", "x": 90, "y": 90 }, - "facing=down,up=north": { "model": "opencomputers:screen", "x": -90 }, - "facing=down,up=south": { "model": "opencomputers:screen", "x": -90, "y": 180 }, - "facing=down,up=east": { "model": "opencomputers:screen", "x": -90, "y": 270 }, - "facing=down,up=west": { "model": "opencomputers:screen", "x": -90, "y": 90 } + "pitch=north,yaw=north": { "model": "opencomputers:screen" }, + "pitch=north,yaw=south": { "model": "opencomputers:screen", "y": 180 }, + "pitch=north,yaw=east": { "model": "opencomputers:screen", "y": 270 }, + "pitch=north,yaw=west": { "model": "opencomputers:screen", "y": 90 }, + "pitch=up,yaw=north": { "model": "opencomputers:screen", "x": 90 }, + "pitch=up,yaw=south": { "model": "opencomputers:screen", "x": 90, "y": 180 }, + "pitch=up,yaw=east": { "model": "opencomputers:screen", "x": 90, "y": 270 }, + "pitch=up,yaw=west": { "model": "opencomputers:screen", "x": 90, "y": 90 }, + "pitch=down,yaw=north": { "model": "opencomputers:screen", "x": -90 }, + "pitch=down,yaw=south": { "model": "opencomputers:screen", "x": -90, "y": 180 }, + "pitch=down,yaw=east": { "model": "opencomputers:screen", "x": -90, "y": 270 }, + "pitch=down,yaw=west": { "model": "opencomputers:screen", "x": -90, "y": 90 } } } diff --git a/src/main/resources/assets/opencomputers/blockstates/screen3.json b/src/main/resources/assets/opencomputers/blockstates/screen3.json index 63ba96081..b54966d25 100644 --- a/src/main/resources/assets/opencomputers/blockstates/screen3.json +++ b/src/main/resources/assets/opencomputers/blockstates/screen3.json @@ -1,16 +1,16 @@ { "variants": { - "facing=north,up=up": { "model": "opencomputers:screen" }, - "facing=south,up=up": { "model": "opencomputers:screen", "y": 180 }, - "facing=west,up=up": { "model": "opencomputers:screen", "y": 270 }, - "facing=east,up=up": { "model": "opencomputers:screen", "y": 90 }, - "facing=up,up=north": { "model": "opencomputers:screen", "x": 90 }, - "facing=up,up=south": { "model": "opencomputers:screen", "x": 90, "y": 180 }, - "facing=up,up=east": { "model": "opencomputers:screen", "x": 90, "y": 270 }, - "facing=up,up=west": { "model": "opencomputers:screen", "x": 90, "y": 90 }, - "facing=down,up=north": { "model": "opencomputers:screen", "x": -90 }, - "facing=down,up=south": { "model": "opencomputers:screen", "x": -90, "y": 180 }, - "facing=down,up=east": { "model": "opencomputers:screen", "x": -90, "y": 270 }, - "facing=down,up=west": { "model": "opencomputers:screen", "x": -90, "y": 90 } + "pitch=north,yaw=north": { "model": "opencomputers:screen" }, + "pitch=north,yaw=south": { "model": "opencomputers:screen", "y": 180 }, + "pitch=north,yaw=east": { "model": "opencomputers:screen", "y": 270 }, + "pitch=north,yaw=west": { "model": "opencomputers:screen", "y": 90 }, + "pitch=up,yaw=north": { "model": "opencomputers:screen", "x": 90 }, + "pitch=up,yaw=south": { "model": "opencomputers:screen", "x": 90, "y": 180 }, + "pitch=up,yaw=east": { "model": "opencomputers:screen", "x": 90, "y": 270 }, + "pitch=up,yaw=west": { "model": "opencomputers:screen", "x": 90, "y": 90 }, + "pitch=down,yaw=north": { "model": "opencomputers:screen", "x": -90 }, + "pitch=down,yaw=south": { "model": "opencomputers:screen", "x": -90, "y": 180 }, + "pitch=down,yaw=east": { "model": "opencomputers:screen", "x": -90, "y": 270 }, + "pitch=down,yaw=west": { "model": "opencomputers:screen", "x": -90, "y": 90 } } } diff --git a/src/main/resources/assets/opencomputers/models/block/case_running.json b/src/main/resources/assets/opencomputers/models/block/case_running.json new file mode 100644 index 000000000..f16c7e156 --- /dev/null +++ b/src/main/resources/assets/opencomputers/models/block/case_running.json @@ -0,0 +1,7 @@ +{ + "parent": "opencomputers:block/case", + "textures": { + "side": "opencomputers:blocks/case_side_running", + "south": "opencomputers:blocks/case_back_running" + } +} diff --git a/src/main/resources/assets/opencomputers/textures/blocks/CaseBackOn.png b/src/main/resources/assets/opencomputers/textures/blocks/case_back_running.png similarity index 100% rename from src/main/resources/assets/opencomputers/textures/blocks/CaseBackOn.png rename to src/main/resources/assets/opencomputers/textures/blocks/case_back_running.png diff --git a/src/main/resources/assets/opencomputers/textures/blocks/CaseSideOn.png b/src/main/resources/assets/opencomputers/textures/blocks/case_side_running.png similarity index 100% rename from src/main/resources/assets/opencomputers/textures/blocks/CaseSideOn.png rename to src/main/resources/assets/opencomputers/textures/blocks/case_side_running.png diff --git a/src/main/scala/li/cil/oc/client/Proxy.scala b/src/main/scala/li/cil/oc/client/Proxy.scala index 90eda0084..7ad786264 100644 --- a/src/main/scala/li/cil/oc/client/Proxy.scala +++ b/src/main/scala/li/cil/oc/client/Proxy.scala @@ -2,28 +2,40 @@ package li.cil.oc.client import li.cil.oc.OpenComputers import li.cil.oc.Settings +import li.cil.oc.api import li.cil.oc.client import li.cil.oc.client.renderer.PetRenderer import li.cil.oc.client.renderer.TextBufferRenderCache import li.cil.oc.client.renderer.WirelessNetworkDebugRenderer +import li.cil.oc.client.renderer.block.ExtendedBlockModel import li.cil.oc.client.renderer.entity.DroneRenderer import li.cil.oc.client.renderer.item.ItemRenderer import li.cil.oc.client.renderer.tileentity._ +import li.cil.oc.common.block.traits.Extended import li.cil.oc.common.component.TextBuffer import li.cil.oc.common.entity.Drone import li.cil.oc.common.init.Items -import li.cil.oc.common.item.Delegate +import li.cil.oc.common.block import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity.ServerRack import li.cil.oc.common.{Proxy => CommonProxy} import li.cil.oc.util.Audio import net.minecraft.block.Block +import net.minecraft.block.properties.IProperty +import net.minecraft.block.state.IBlockState import net.minecraft.client.Minecraft -import net.minecraft.client.renderer.ItemModelMesher +import net.minecraft.client.renderer.ItemMeshDefinition +import net.minecraft.client.renderer.block.statemap.IStateMapper +import net.minecraft.client.resources.model.ModelBakery import net.minecraft.client.resources.model.ModelResourceLocation import net.minecraft.item.Item +import net.minecraft.item.ItemStack import net.minecraftforge.client.MinecraftForgeClient import net.minecraftforge.common.MinecraftForge +import net.minecraftforge.common.property.ExtendedBlockState +import net.minecraftforge.common.property.IExtendedBlockState +import net.minecraftforge.common.property.IUnlistedProperty +import net.minecraftforge.common.property.Properties import net.minecraftforge.fml.client.registry.ClientRegistry import net.minecraftforge.fml.client.registry.RenderingRegistry import net.minecraftforge.fml.common.FMLCommonHandler @@ -34,9 +46,12 @@ import net.minecraftforge.fml.common.network.NetworkRegistry import org.lwjgl.opengl.GLContext import scala.collection.mutable +import scala.collection.convert.WrapAsScala._ +import scala.collection.convert.WrapAsJava._ private[oc] class Proxy extends CommonProxy { - private val pendingRegistrations = mutable.ArrayBuffer.empty[ItemModelMesher => Unit] + private val extendedBlocks = mutable.ArrayBuffer.empty[(Extended, String)] + private val meshableItems = mutable.ArrayBuffer.empty[Item] override def preInit(e: FMLPreInitializationEvent) { if (Loader.isModLoaded("OpenComponents")) { @@ -45,35 +60,81 @@ private[oc] class Proxy extends CommonProxy { super.preInit(e) +// MinecraftForge.EVENT_BUS.register(ExtendedBlockModel) MinecraftForge.EVENT_BUS.register(Sound) MinecraftForge.EVENT_BUS.register(Textures) } - override def registerModel(instance: Item, location: String): Unit ={ - pendingRegistrations += ((mesher: ItemModelMesher) => { - mesher.register(instance, 0, new ModelResourceLocation(Settings.resourceDomain + ":" + location, "inventory")) - }) + override def registerModel(instance: Item): Unit = { + meshableItems += instance } - override def registerModel(instance: Delegate, name: String): Unit = { + override def registerModel(instance: Block, id: String): Unit = { + val item = Item.getItemFromBlock(instance) + registerModel(item) +// ExtendedBlockModel.registerBlock(instance) + instance match { + case extended: block.traits.Extended => + extendedBlocks += extended -> (Settings.resourceDomain + ":" + id) +// val blockLocation = Settings.resourceDomain + ":" + id +// Minecraft.getMinecraft.getRenderItem.getItemModelMesher.getModelManager.getBlockModelShapes.getBlockStateMapper.registerBlockStateMapper(extended, new IStateMapper { +// override def putStateModelLocations(block: Block) = { +// val state = extended.getDefaultState +// val unlisted = extended.collectRawProperties() +// val values = unlisted.map(property => property.getAllowedValues.collect { +// case value: java.lang.Comparable[AnyRef]@unchecked => ((property, value), property.getName + "=" + property.getName(value)) +// }) +// values.foldLeft(Iterable((state, "")))((acc, value) => cross(acc, value)).map(variant => (variant._1, new ModelResourceLocation(blockLocation, variant._2.stripPrefix(",")))).toMap[AnyRef, AnyRef] +// } +// }) +// +// + // val unlisted = extended.collectRawProperties() +// val values = unlisted.map(property => property.getAllowedValues.collect { +// case value: java.lang.Comparable[AnyRef]@unchecked => property.getName + "=" + property.getName(value) +// }) +// val variants = values.foldLeft(Iterable(""))((acc, value) => cross(acc, value)).map(variant => id + "#" + variant.stripPrefix(",")).toSeq +// ModelBakery.addVariantName(item, variants: _*) + case _ => + } } - override def registerModel(instance: Block, location: String): Unit = { - registerModel(Item.getItemFromBlock(instance), location) - } + private def cross(xs: Iterable[(IExtendedBlockState, String)], ys: Iterable[((IUnlistedProperty[_], Comparable[AnyRef]), String)]) = + for { (state, stateString) <- xs; ((property, value), valueString) <- ys } yield (state.withProperty(property.asInstanceOf[IUnlistedProperty[Any]], value), stateString + "," + valueString) override def init(e: FMLInitializationEvent) { super.init(e) OpenComputers.channel.register(client.PacketHandler) - // TODO block rendering -// Settings.blockRenderId = RenderingRegistry.getNextAvailableRenderId -// RenderingRegistry.registerBlockHandler(BlockRenderer) - val mesher =Minecraft.getMinecraft.getRenderItem.getItemModelMesher - pendingRegistrations.foreach(_(mesher)) - pendingRegistrations.clear() + val mesher = Minecraft.getMinecraft.getRenderItem.getItemModelMesher + val meshDefinition = new ItemMeshDefinition { + override def getModelLocation(stack: ItemStack) = { + Option(api.Items.get(stack)) match { + case Some(descriptor) => new ModelResourceLocation(Settings.resourceDomain + ":" + descriptor.name(), "inventory") + case _ => null + } + } + } + meshableItems.foreach(item => mesher.register(item, meshDefinition)) + meshableItems.clear() + for((extended, blockLocation) <- extendedBlocks) { + Minecraft.getMinecraft.getRenderItem.getItemModelMesher.getModelManager.getBlockModelShapes.getBlockStateMapper.registerBlockStateMapper(extended, new IStateMapper { + override def putStateModelLocations(block: Block) = { + val state = extended.getDefaultState.asInstanceOf[IExtendedBlockState] + val unlisted = extended.collectRawProperties().toArray.sortBy(_._2.getName) + val values = unlisted.map { + case (property, propertyRaw) => propertyRaw.getAllowedValues.collect { + case value: java.lang.Comparable[AnyRef]@unchecked => ((property, value), propertyRaw.getName + "=" + propertyRaw.getName(value)) + } + } + values.foldLeft(Iterable((state, "")))((acc, value) => cross(acc, value)).map(variant => (variant._1, new ModelResourceLocation(blockLocation, variant._2.stripPrefix(",")))).toMap[AnyRef, AnyRef] + } + }) + } + extendedBlocks.clear() +// ExtendedBlockModel.init() RenderingRegistry.registerEntityRenderingHandler(classOf[Drone], DroneRenderer) diff --git a/src/main/scala/li/cil/oc/client/renderer/block/ExtendedBlockModel.scala b/src/main/scala/li/cil/oc/client/renderer/block/ExtendedBlockModel.scala new file mode 100644 index 000000000..1546e5b32 --- /dev/null +++ b/src/main/scala/li/cil/oc/client/renderer/block/ExtendedBlockModel.scala @@ -0,0 +1,247 @@ +package li.cil.oc.client.renderer.block + +import java.io.InputStreamReader +import java.util.Collections + +import com.google.common.base.Charsets +import com.google.common.base.Optional +import li.cil.oc.OpenComputers +import li.cil.oc.Settings +import li.cil.oc.common.block +import net.minecraft.block.Block +import net.minecraft.block.state.IBlockState +import net.minecraft.client.Minecraft +import net.minecraft.client.renderer.block.model.BlockPart +import net.minecraft.client.renderer.block.model.BlockPartFace +import net.minecraft.client.renderer.block.model.ItemCameraTransforms +import net.minecraft.client.renderer.block.model.ModelBlock +import net.minecraft.client.renderer.block.statemap.IStateMapper +import net.minecraft.client.renderer.block.statemap.StateMap +import net.minecraft.client.renderer.texture.TextureAtlasSprite +import net.minecraft.client.resources.model.IBakedModel +import net.minecraft.client.resources.model.ModelBakery +import net.minecraft.client.resources.model.ModelResourceLocation +import net.minecraft.client.resources.model.SimpleBakedModel +import net.minecraft.item.Item +import net.minecraft.util.EnumFacing +import net.minecraft.util.ResourceLocation +import net.minecraftforge.client.event.ModelBakeEvent +import net.minecraftforge.client.model.ISmartBlockModel +import net.minecraftforge.common.property.IExtendedBlockState +import net.minecraftforge.common.property.IUnlistedProperty +import net.minecraftforge.fml.client.FMLClientHandler +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.registry.FMLControlledNamespacedRegistry + +import scala.collection.convert.WrapAsScala._ +import scala.collection.mutable + +object ExtendedBlockModel { + private val extendedBlocks = mutable.ArrayBuffer.empty[block.traits.Extended] + + def registerBlock(instance: Block): Unit = { + instance match { + case extended: block.traits.Extended => extendedBlocks += extended + case _ => + } + } + +// def init(): Unit = { +// val mesher = Minecraft.getMinecraft.getRenderItem.getItemModelMesher +// for (extended <- extendedBlocks) { +// val blockName = extended.getUnlocalizedName.stripPrefix("tile.oc.") +// val blockLocation = Settings.resourceDomain + ":" + blockName +// val unlisted = extended.collectRawProperties() +// val values = unlisted.map(property => property.getAllowedValues.collect { +// case value: java.lang.Comparable[AnyRef]@unchecked => property.getName + "=" + property.getName(value) +// }) +// val variants = values.foldLeft(Iterable(""))((acc, value) => cross(acc, value)).map(_.stripPrefix(",")) +// for ((variant, pseudoMeta) <- variants.zipWithIndex) { +// val variantLocation = new ModelResourceLocation(blockLocation, variant) +// mesher.register(Item.getItemFromBlock(extended), pseudoMeta + 1, variantLocation) +// } +// } +// } + + @SubscribeEvent + def onModelBake(e: ModelBakeEvent): Unit = { + val registry = e.modelRegistry + for (extended <- extendedBlocks) { + val blockName = extended.getUnlocalizedName.stripPrefix("tile.oc.") + val blockLocation = Settings.resourceDomain + ":" + blockName + val modelLocation = new ModelResourceLocation(blockLocation) +// val model = e.modelRegistry.getObject(modelLocation) + registry.putObject(modelLocation, new ExtendedBlockModel(blockName)) + +// registry.putObject(modelLocation, new WrappedBlockModel(model)) + +// extended match { +// case rotatable: block.traits.Rotatable => +// registry.putObject(modelLocation, new RotatableBlockModel(model)) +// case rotatable: block.traits.OmniRotatable => +// registry.putObject(modelLocation, new OmniRotatableBlockModel( model)) +// case _ => +// } + +// loadModel(modelLocation) match { +// case Some(model) => +// val builder = new SimpleBakedModel.Builder(model) +// model.getElements.collect { +// case blockPart: BlockPart => +// blockPart.mapFaces.collect { +// case (facing: EnumFacing, facePart: BlockPartFace) => +// val texture = new ResourceLocation(model.resolveTextureName(facePart.texture)) +// if (facePart.cullFace == null) { +// builder.addGeneralQuad() +// } +// } +// } +// registry.putObject(modelLocation, new ExtendedBlockModel(blockName, model)) +// case _ => +// } + + +// val unlisted = extended.collectRawProperties() +// val values = unlisted.map(property => property.getAllowedValues.collect { +// case value: java.lang.Comparable[AnyRef]@unchecked => property.getName + "=" + property.getName(value) +// }) +// val variants = values.foldLeft(Iterable(""))((acc, value) => cross(acc, value)).map(_.stripPrefix(",")) +// val mesher = Minecraft.getMinecraft.getRenderItem.getItemModelMesher +// for ((variant, pseudoMeta) <- variants.zipWithIndex) { +// val variantLocation = new ModelResourceLocation(blockLocation, variant) +// mesher.register(Item.getItemFromBlock(extended), pseudoMeta + 1, variantLocation) +// } + +// for (variant <- variants) { +// val variantLocation = new ModelResourceLocation(blockLocation, variant) +// registry.putObject(variantLocation, e.modelManager.getModel(variantLocation, variant)) +// } + +// val builder = new StateMap.Builder() +// val properties = extended.collectRawProperties() +// for (property <- properties) { +// builder.setProperty(property) +// } +// e.modelManager.getBlockModelShapes.getBlockStateMapper.registerBlockStateMapper(extended, builder.build()) + + +// e.modelManager.getBlockModelShapes.getBlockStateMapper.registerBlockStateMapper(extended, new IStateMapper { +// override def putStateModelLocations(block: Block) = { +// val unlisted = extended.collectRawProperties() +// val values = unlisted.map(property => property.getAllowedValues.collect { +// case value: java.lang.Comparable[AnyRef]@unchecked => property.getName + "=" + property.getName(value) +// }) +// val variants = values.foldLeft(Iterable(""))((acc, value) => cross(acc, value)).map(_.stripPrefix(",")) +// } + +// override def getModelResourceLocation(state: IBlockState) = { +// state match { +// case extended: IExtendedBlockState => +// val variant = extended.getUnlistedProperties.collect { +// case (property, value) if value.isPresent => property.getName + "=" + property.valueToString(value.get) +// }.mkString(",") +// new ModelResourceLocation(blockLocation, variant) +// case _ => super.getModelResourceLocation(state) +// } +// } +// }) + } + +// abstract class WrappedBlockModel(val wrappedModel: IBakedModel) extends ISmartBlockModel { +// override def getFaceQuads(side: EnumFacing) = wrappedModel.getFaceQuads(side) +// +// override def getGeneralQuads = wrappedModel.getGeneralQuads +// +// override def isAmbientOcclusion = wrappedModel.isAmbientOcclusion +// +// override def isGui3d = wrappedModel.isGui3d +// +// override def isBuiltInRenderer = wrappedModel.isBuiltInRenderer +// +// override def getTexture = wrappedModel.getTexture +// +// override def getItemCameraTransforms = wrappedModel.getItemCameraTransforms +// } + +// class RotatableBlockModel(wrappedModel: IBakedModel) extends WrappedBlockModel(wrappedModel) { +// override def handleBlockState(state: IBlockState) = { +// } +// } + + } + +// private def loadModel(location: ModelResourceLocation) = { +// val resource = Minecraft.getMinecraft.getResourceManager.getResource(location) +// val stream = new InputStreamReader(resource.getInputStream, Charsets.UTF_8) +// try { +// val model = ModelBlock.deserialize(stream) +// model.name = resource.toString +// Some(model) +// } +// catch { +// case t: Throwable => +// OpenComputers.log.warn(s"Failed loading block model for $location.", t) +// None +// } +// finally { +// stream.close() +// } +// } + +// private def cross(xs: Iterable[String], ys: Iterable[String]) = for { x <- xs; y <- ys } yield x + "," + y +} + +class ExtendedBlockModel(val blockName: String) extends ISmartBlockModel { +// var statefulModel: Option[IBakedModel] = None + + override def handleBlockState(state: IBlockState) = { + state match { + case extended: IExtendedBlockState => + val variant = extended.getUnlistedProperties.collect { + case (key: IUnlistedProperty[AnyRef]@unchecked, value: Optional[AnyRef]@unchecked) if value.isPresent => key.getName + "=" + key.valueToString(value.get) + }.mkString(",") + val location = new ModelResourceLocation(Settings.resourceDomain + ":" + blockName, variant) +// statefulModel = Option(getSimpleModel(location)) + getSimpleModel(location) + case _ => + } + this + } + + private def getSimpleModel(location: ModelResourceLocation) = Minecraft.getMinecraft.getRenderItem.getItemModelMesher.getModelManager.getModel(location) + + override def getFaceQuads(side: EnumFacing) = Collections.emptyList() // statefulModel.map(_.getFaceQuads(side)).getOrElse(Collections.emptyList) + + override def getGeneralQuads = Collections.emptyList() // statefulModel.map(_.getGeneralQuads).getOrElse(Collections.emptyList) + + override def isAmbientOcclusion = true // statefulModel.fold(true)(_.isAmbientOcclusion) + + override def isGui3d = true // statefulModel.fold(true)(_.isGui3d) + + override def isBuiltInRenderer = false + + override def getTexture = null // statefulModel.fold(null: TextureAtlasSprite)(_.getTexture) + + override def getItemCameraTransforms = ItemCameraTransforms.DEFAULT // statefulModel.fold(null: ItemCameraTransforms)(_.getItemCameraTransforms) +} + +//class WrappedBlockModel(val wrappedModel: IBakedModel) extends ISmartBlockModel { +// override def handleBlockState(state: IBlockState) = wrappedModel +//// val model = Minecraft.getMinecraft.getRenderItem.getItemModelMesher.getModelManager.getModel() +//// wrappedModel +//// } +// +// override def getFaceQuads(side: EnumFacing) = wrappedModel.getFaceQuads(side) +// +// override def getGeneralQuads = wrappedModel.getGeneralQuads +// +// override def isAmbientOcclusion = wrappedModel.isAmbientOcclusion +// +// override def isGui3d = wrappedModel.isGui3d +// +// override def isBuiltInRenderer = wrappedModel.isBuiltInRenderer +// +// override def getTexture = wrappedModel.getTexture +// +// override def getItemCameraTransforms = wrappedModel.getItemCameraTransforms +//} \ No newline at end of file diff --git a/src/main/scala/li/cil/oc/common/Proxy.scala b/src/main/scala/li/cil/oc/common/Proxy.scala index 3e50ce704..f17302c01 100644 --- a/src/main/scala/li/cil/oc/common/Proxy.scala +++ b/src/main/scala/li/cil/oc/common/Proxy.scala @@ -66,11 +66,9 @@ class Proxy { api.Machine.add(classOf[LuaJLuaArchitecture]) } - def registerModel(instance: Item, location: String): Unit = {} + def registerModel(instance: Item): Unit = {} - def registerModel(instance: Delegate, location: String): Unit = {} - - def registerModel(instance: Block, location: String): Unit = {} + def registerModel(instance: Block, id: String): Unit = {} def init(e: FMLInitializationEvent) { OpenComputers.channel = NetworkRegistry.INSTANCE.newEventDrivenChannel("OpenComputers") diff --git a/src/main/scala/li/cil/oc/common/block/Case.scala b/src/main/scala/li/cil/oc/common/block/Case.scala index fc5e138c7..27b434e15 100644 --- a/src/main/scala/li/cil/oc/common/block/Case.scala +++ b/src/main/scala/li/cil/oc/common/block/Case.scala @@ -9,48 +9,48 @@ import li.cil.oc.common.tileentity import li.cil.oc.integration.util.Wrench import li.cil.oc.util.Color import li.cil.oc.util.Tooltip +import net.minecraft.block.properties.IProperty +import net.minecraft.block.properties.PropertyBool import net.minecraft.block.state.IBlockState import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.EnumRarity import net.minecraft.item.ItemStack import net.minecraft.util.BlockPos import net.minecraft.util.EnumFacing +import net.minecraft.world.IBlockAccess import net.minecraft.world.World +import net.minecraftforge.common.property.IExtendedBlockState +import net.minecraftforge.common.property.IUnlistedProperty +import net.minecraftforge.common.property.Properties import net.minecraftforge.fml.relauncher.Side import net.minecraftforge.fml.relauncher.SideOnly -class Case(val tier: Int) extends RedstoneAware with traits.PowerAcceptor with traits.Rotatable { - setDefaultState(buildDefaultState()) +import scala.collection.mutable - // TODO remove -// private val iconsOn = new Array[IIcon](6) -// -// // ----------------------------------------------------------------------- // -// -// override protected def customTextures = Array( -// Some("CaseTop"), -// Some("CaseTop"), -// Some("CaseBack"), -// Some("CaseFront"), -// Some("CaseSide"), -// Some("CaseSide") -// ) -// -// override def registerBlockIcons(iconRegister: IIconRegister) = { -// super.registerBlockIcons(iconRegister) -// System.arraycopy(icons, 0, iconsOn, 0, icons.length) -// iconsOn(EnumFacing.NORTH.ordinal) = iconRegister.getAtlasSprite(Settings.resourceDomain + ":CaseBackOn") -// iconsOn(EnumFacing.WEST.ordinal) = iconRegister.getAtlasSprite(Settings.resourceDomain + ":CaseSideOn") -// iconsOn(EnumFacing.EAST.ordinal) = iconsOn(EnumFacing.WEST.ordinal) -// } -// -// override def getIcon(world: IBlockAccess, x: Int, y: Int, z: Int, worldSide: EnumFacing, localSide: EnumFacing) = { -// if (world.getTileEntity(x, y, z) match { -// case computer: tileentity.Case => computer.isRunning -// case _ => false -// }) iconsOn(localSide.ordinal) -// else getIcon(localSide.ordinal(), 0) -// } +class Case(val tier: Int) extends RedstoneAware with traits.PowerAcceptor with traits.Rotatable { + final lazy val RunningRaw = PropertyBool.create("running") + final lazy val Running: IUnlistedProperty[Boolean] = Properties.toUnlisted(RunningRaw) + + override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state) + + override protected def addExtendedState(state: IExtendedBlockState, world: IBlockAccess, pos: BlockPos) = + world.getTileEntity(pos) match { + case computer: tileentity.traits.Computer => + super.addExtendedState(state.withProperty(Running, computer.isRunning), world, pos) + case _ => None + } + + override protected def addExtendedProperties(listed: mutable.ArrayBuffer[IProperty], unlisted: mutable.ArrayBuffer[IUnlistedProperty[_]]): Unit = { + super.addExtendedProperties(listed, unlisted) + unlisted += Running + } + + override protected def addExtendedRawProperties(unlisted: mutable.Map[IUnlistedProperty[_], IProperty]): Unit = { + super.addExtendedRawProperties(unlisted) + unlisted += Running -> RunningRaw + } + + // ----------------------------------------------------------------------- // @SideOnly(Side.CLIENT) override def getRenderColor(state: IBlockState) = Color.rgbValues(Color.byTier(tier)) diff --git a/src/main/scala/li/cil/oc/common/block/Charger.scala b/src/main/scala/li/cil/oc/common/block/Charger.scala index 6b2022de1..d9be6c52f 100644 --- a/src/main/scala/li/cil/oc/common/block/Charger.scala +++ b/src/main/scala/li/cil/oc/common/block/Charger.scala @@ -16,7 +16,7 @@ import net.minecraft.world.IBlockAccess import net.minecraft.world.World class Charger extends RedstoneAware with traits.PowerAcceptor with traits.Rotatable { - setDefaultState(buildDefaultState()) + override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state) override def energyThroughput = Settings.get.chargerRate diff --git a/src/main/scala/li/cil/oc/common/block/DiskDrive.scala b/src/main/scala/li/cil/oc/common/block/DiskDrive.scala index 32817803c..e43823ba8 100644 --- a/src/main/scala/li/cil/oc/common/block/DiskDrive.scala +++ b/src/main/scala/li/cil/oc/common/block/DiskDrive.scala @@ -13,7 +13,7 @@ import net.minecraft.util.EnumFacing import net.minecraft.world.World class DiskDrive extends SimpleBlock with traits.Rotatable { - setDefaultState(buildDefaultState()) + override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state) override protected def tooltipTail(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: java.util.List[String], advanced: Boolean) { super.tooltipTail(metadata, stack, player, tooltip, advanced) diff --git a/src/main/scala/li/cil/oc/common/block/Keyboard.scala b/src/main/scala/li/cil/oc/common/block/Keyboard.scala index f52d03bae..d3f645845 100644 --- a/src/main/scala/li/cil/oc/common/block/Keyboard.scala +++ b/src/main/scala/li/cil/oc/common/block/Keyboard.scala @@ -15,11 +15,12 @@ import org.lwjgl.opengl.GL11 class Keyboard extends SimpleBlock with traits.SpecialBlock with traits.OmniRotatable { setLightOpacity(0) - setDefaultState(buildDefaultState()) // For Immibis Microblock support. val ImmibisMicroblocks_TransformableBlockMarker = null + override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state) + override def shouldSideBeRendered(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = true override def setBlockBoundsForItemRender(metadata: Int) = setBlockBounds(EnumFacing.NORTH, EnumFacing.WEST) @@ -43,10 +44,10 @@ class Keyboard extends SimpleBlock with traits.SpecialBlock with traits.OmniRota case _ => } - override def localCanPlaceBlockOnSide(world: World, pos: BlockPos, side: EnumFacing) = { - world.isSideSolid(pos.offset(side), side.getOpposite) && - (world.getTileEntity(pos.offset(side)) match { - case screen: tileentity.Screen => screen.facing != side.getOpposite + override def canPlaceBlockOnSide(world: World, pos: BlockPos, side: EnumFacing) = { + world.isSideSolid(pos.offset(side.getOpposite), side) && + (world.getTileEntity(pos.offset(side.getOpposite)) match { + case screen: tileentity.Screen => screen.facing != side case _ => true }) } @@ -77,7 +78,7 @@ class Keyboard extends SimpleBlock with traits.SpecialBlock with traits.OmniRota override def onNeighborBlockChange(world: World, pos: BlockPos, state: IBlockState, neighborBlock: Block) = world.getTileEntity(pos) match { - case keyboard: tileentity.Keyboard if localCanPlaceBlockOnSide(world, pos, keyboard.facing.getOpposite) => // Can stay. + case keyboard: tileentity.Keyboard if canPlaceBlockOnSide(world, pos, keyboard.facing) => // Can stay. case _ => dropBlockAsItem(world, pos, world.getBlockState(pos), 0) world.setBlockToAir(pos) diff --git a/src/main/scala/li/cil/oc/common/block/Raid.scala b/src/main/scala/li/cil/oc/common/block/Raid.scala index 2c719ac98..8741040a3 100644 --- a/src/main/scala/li/cil/oc/common/block/Raid.scala +++ b/src/main/scala/li/cil/oc/common/block/Raid.scala @@ -10,7 +10,7 @@ import net.minecraft.util.EnumFacing import net.minecraft.world.World class Raid extends SimpleBlock with traits.Rotatable { - setDefaultState(buildDefaultState()) + override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state) override def hasTileEntity(state: IBlockState) = true diff --git a/src/main/scala/li/cil/oc/common/block/Screen.scala b/src/main/scala/li/cil/oc/common/block/Screen.scala index d95f0777d..51ab1755e 100644 --- a/src/main/scala/li/cil/oc/common/block/Screen.scala +++ b/src/main/scala/li/cil/oc/common/block/Screen.scala @@ -25,7 +25,8 @@ import net.minecraftforge.fml.relauncher.SideOnly class Screen(val tier: Int) extends RedstoneAware with traits.OmniRotatable { setLightLevel(0.34f) - setDefaultState(buildDefaultState()) + + override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state) @SideOnly(Side.CLIENT) override def getRenderColor(state: IBlockState) = Color.rgbValues(Color.byTier(tier)) diff --git a/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala b/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala index 4282e4fdb..126d020df 100644 --- a/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala +++ b/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala @@ -178,12 +178,6 @@ class SimpleBlock(material: Material = Material.iron) extends Block(material) { protected def intersect(world: World, pos: BlockPos, origin: Vec3, end: Vec3) = super.collisionRayTrace(world, pos, origin, end) - final override def canPlaceBlockOnSide(world: World, pos: BlockPos, side: EnumFacing) = - localCanPlaceBlockOnSide(world, pos, toLocal(world, pos, side.getOpposite)) - - def localCanPlaceBlockOnSide(world: World, pos: BlockPos, side: EnumFacing) = - super.canPlaceBlockOnSide(world, BlockPosition(pos).toBlockPos, side.getOpposite) - // ----------------------------------------------------------------------- // override def canConnectRedstone(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false diff --git a/src/main/scala/li/cil/oc/common/block/traits/Extended.scala b/src/main/scala/li/cil/oc/common/block/traits/Extended.scala new file mode 100644 index 000000000..c1a8e8fad --- /dev/null +++ b/src/main/scala/li/cil/oc/common/block/traits/Extended.scala @@ -0,0 +1,103 @@ +package li.cil.oc.common.block.traits + +import com.google.common.base.Optional +import com.google.common.collect.ImmutableList +import com.google.common.collect.ImmutableMap +import net.minecraft.block.Block +import net.minecraft.block.properties.IProperty +import net.minecraft.block.state.BlockState +import net.minecraft.block.state.BlockState.StateImplementation +import net.minecraft.block.state.IBlockState +import net.minecraft.util.BlockPos +import net.minecraft.world.IBlockAccess +import net.minecraftforge.common.property.ExtendedBlockState +import net.minecraftforge.common.property.IExtendedBlockState +import net.minecraftforge.common.property.IUnlistedProperty + +import scala.collection.mutable +import scala.collection.convert.WrapAsJava._ +import scala.collection.convert.WrapAsScala._ + +object Extended { + // Patch in custom hash codes for extended block states. + def wrap(state: IBlockState): StateImplementation = state match { + case wrapped: ExtendedBlockStateWithHashCode => wrapped + case extended: StateImplementation with IExtendedBlockState => new ExtendedBlockStateWithHashCode(extended) + case simple: StateImplementation => simple + } + + class ExtendedBlockStateWithHashCode(val inner: StateImplementation with IExtendedBlockState) extends StateImplementation(inner.getBlock, inner.getProperties) with IExtendedBlockState { + override def getPropertyNames = inner.getPropertyNames + + override def getValue(property: IProperty) = inner.getValue(property) + + override def withProperty(property: IProperty, value: Comparable[_]): IBlockState = wrap(inner.withProperty(property, value)) + + override def cycleProperty(property: IProperty) = wrap(inner.cycleProperty(property)) + + override def getProperties = inner.getProperties + + override def getBlock = inner.getBlock + + override def getUnlistedNames = inner.getUnlistedNames + + override def getValue[V](property: IUnlistedProperty[V]) = inner.getValue(property) + + override def withProperty[V](property: IUnlistedProperty[V], value: V) = wrap(inner.withProperty(property, value)).asInstanceOf[IExtendedBlockState] + + override def getUnlistedProperties = inner.getUnlistedProperties + + override def equals(obj: scala.Any) = inner.equals(obj) + + override def hashCode() = (inner.hashCode() * 31) ^ inner.getUnlistedProperties.collect { + case (property: IUnlistedProperty[AnyRef]@unchecked, value: Optional[AnyRef]@unchecked) if value.isPresent => property.getName + "=" + property.valueToString(value.get) + }.toArray.sorted.mkString(",").hashCode + } + +} + +trait Extended extends Block { + setDefaultExtendedState(Extended.wrap(getBlockState.getBaseState)) + + // Gnaah, implementation limitations :-/ + protected def setDefaultExtendedState(state: IBlockState): Unit + + override def getBlockState = super.getBlockState + + override def getActualState(state: IBlockState, worldIn: IBlockAccess, pos: BlockPos) = getExtendedState(state, worldIn, pos) + + override def getExtendedState(state: IBlockState, world: IBlockAccess, pos: BlockPos) = + addExtendedState(getDefaultState.asInstanceOf[IExtendedBlockState], world, pos). + getOrElse(super.getExtendedState(state, world, pos)) + + override def createBlockState() = { + val (listed, unlisted) = collectProperties() + new ExtendedBlockState(this, listed.toArray, unlisted.toArray) { + private lazy val validStates = ImmutableList.copyOf(super.getValidStates.map { + case state: IBlockState => Extended.wrap(state) + }.toArray) + override def createState(block: Block, properties: ImmutableMap[_, _], unlistedProperties: ImmutableMap[_, _]) = Extended.wrap(super.createState(block, properties, unlistedProperties)) + + override def getValidStates = validStates + } + } + + final def collectProperties() = { + val listed = mutable.ArrayBuffer.empty[IProperty] + val unlisted = mutable.ArrayBuffer.empty[IUnlistedProperty[_]] + addExtendedProperties(listed, unlisted) + (listed, unlisted) + } + + final def collectRawProperties() = { + val unlistedRaw = mutable.Map.empty[IUnlistedProperty[_], IProperty] + addExtendedRawProperties(unlistedRaw) + unlistedRaw + } + + protected def addExtendedState(state: IExtendedBlockState, world: IBlockAccess, pos: BlockPos): Option[IExtendedBlockState] = Some(state) + + protected def addExtendedProperties(listed: mutable.ArrayBuffer[IProperty], unlisted: mutable.ArrayBuffer[IUnlistedProperty[_]]): Unit = {} + + protected def addExtendedRawProperties(unlisted: mutable.Map[IUnlistedProperty[_], IProperty]): Unit = {} +} diff --git a/src/main/scala/li/cil/oc/common/block/traits/OmniRotatable.scala b/src/main/scala/li/cil/oc/common/block/traits/OmniRotatable.scala index 5d79dc3af..63ffe9337 100644 --- a/src/main/scala/li/cil/oc/common/block/traits/OmniRotatable.scala +++ b/src/main/scala/li/cil/oc/common/block/traits/OmniRotatable.scala @@ -2,37 +2,42 @@ package li.cil.oc.common.block.traits import com.google.common.base.Predicate import com.google.common.base.Predicates +import li.cil.oc.common.tileentity import net.minecraft.block.Block +import net.minecraft.block.properties.IProperty import net.minecraft.block.properties.PropertyDirection -import net.minecraft.block.state.BlockState -import net.minecraft.block.state.IBlockState +import net.minecraft.util.BlockPos import net.minecraft.util.EnumFacing -import net.minecraftforge.fml.relauncher.Side -import net.minecraftforge.fml.relauncher.SideOnly +import net.minecraft.world.IBlockAccess +import net.minecraftforge.common.property.IExtendedBlockState +import net.minecraftforge.common.property.IUnlistedProperty +import net.minecraftforge.common.property.Properties -trait OmniRotatable extends Block { - final lazy val Facing = PropertyDirection.create("facing", Predicates.instanceOf(classOf[EnumFacing])) - final lazy val Up = PropertyDirection.create("up", EnumFacing.Plane.HORIZONTAL.asInstanceOf[Predicate[EnumFacing]]) +import scala.collection.mutable - protected def buildDefaultState() = getBlockState.getBaseState.withProperty(Facing, EnumFacing.NORTH).withProperty(Up, EnumFacing.NORTH) +trait OmniRotatable extends Block with Extended { + final lazy val PitchRaw = PropertyDirection.create("pitch", Predicates.instanceOf(classOf[EnumFacing])) + final lazy val Pitch: IUnlistedProperty[EnumFacing] = Properties.toUnlisted(PitchRaw) + final lazy val YawRaw = PropertyDirection.create("yaw", EnumFacing.Plane.HORIZONTAL.asInstanceOf[Predicate[EnumFacing]]) + final lazy val Yaw: IUnlistedProperty[EnumFacing] = Properties.toUnlisted(YawRaw) - @SideOnly(Side.CLIENT) - override def getStateForEntityRender(state: IBlockState) = getDefaultState.withProperty(Facing, EnumFacing.SOUTH) + override protected def addExtendedState(state: IExtendedBlockState, world: IBlockAccess, pos: BlockPos) = + (world.getTileEntity(pos), state) match { + case rotatable: tileentity.traits.Rotatable => + super.addExtendedState(state.withProperty(Pitch, rotatable.pitch).withProperty(Yaw, rotatable.yaw), world, pos) + case _ => + None + } - override def getStateFromMeta(meta: Int) = { - val facing = EnumFacing.getFront(meta >>> 3) - val up = EnumFacing.getHorizontal(meta & 7) - if (up.getAxis == EnumFacing.Axis.Y) - getDefaultState.withProperty(Facing, facing).withProperty(Up, EnumFacing.NORTH) - else - getDefaultState.withProperty(Facing, facing).withProperty(Up, up) + override protected def addExtendedProperties(listed: mutable.ArrayBuffer[IProperty], unlisted: mutable.ArrayBuffer[IUnlistedProperty[_]]): Unit = { + super.addExtendedProperties(listed, unlisted) + unlisted += Pitch + unlisted += Yaw } - override def getMetaFromState(state: IBlockState) = { - val facing = state.getValue(Facing).asInstanceOf[EnumFacing] - val up = state.getValue(Up).asInstanceOf[EnumFacing] - facing.getIndex << 3 | up.getHorizontalIndex + override protected def addExtendedRawProperties(unlisted: mutable.Map[IUnlistedProperty[_], IProperty]): Unit = { + super.addExtendedRawProperties(unlisted) + unlisted += Pitch -> PitchRaw + unlisted += Yaw -> YawRaw } - - override def createBlockState() = new BlockState(this, Facing, Up) } diff --git a/src/main/scala/li/cil/oc/common/block/traits/Rotatable.scala b/src/main/scala/li/cil/oc/common/block/traits/Rotatable.scala index a2f845295..e8d7692bd 100644 --- a/src/main/scala/li/cil/oc/common/block/traits/Rotatable.scala +++ b/src/main/scala/li/cil/oc/common/block/traits/Rotatable.scala @@ -1,31 +1,39 @@ package li.cil.oc.common.block.traits import com.google.common.base.Predicate +import li.cil.oc.common.tileentity import net.minecraft.block.Block +import net.minecraft.block.properties.IProperty import net.minecraft.block.properties.PropertyDirection -import net.minecraft.block.state.BlockState -import net.minecraft.block.state.IBlockState +import net.minecraft.util.BlockPos import net.minecraft.util.EnumFacing -import net.minecraftforge.fml.relauncher.Side -import net.minecraftforge.fml.relauncher.SideOnly +import net.minecraft.world.IBlockAccess +import net.minecraftforge.common.property.IExtendedBlockState +import net.minecraftforge.common.property.IUnlistedProperty +import net.minecraftforge.common.property.Properties -trait Rotatable extends Block { - final lazy val Facing = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL.asInstanceOf[Predicate[EnumFacing]]) +import scala.collection.mutable - protected def buildDefaultState() = getBlockState.getBaseState.withProperty(Facing, EnumFacing.NORTH) +trait Rotatable extends Block with Extended { + final lazy val FacingRaw = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL.asInstanceOf[Predicate[EnumFacing]]) + final lazy val Facing: IUnlistedProperty[EnumFacing] = Properties.toUnlisted(FacingRaw) - @SideOnly(Side.CLIENT) - override def getStateForEntityRender(state: IBlockState) = getDefaultState.withProperty(Facing, EnumFacing.SOUTH) - - override def getStateFromMeta(meta: Int) = { - val facing = EnumFacing.getFront(meta) - if (facing.getAxis == EnumFacing.Axis.Y) - getDefaultState.withProperty(Facing, EnumFacing.NORTH) - else - getDefaultState.withProperty(Facing, facing) + override protected def addExtendedState(state: IExtendedBlockState, world: IBlockAccess, pos: BlockPos) = { + world.getTileEntity(pos) match { + case rotatable: tileentity.traits.Rotatable => + super.addExtendedState(state.withProperty(Facing, rotatable.facing), world, pos) + case _ => + None + } } - override def getMetaFromState(state: IBlockState) = state.getValue(Facing).asInstanceOf[EnumFacing].getIndex + override protected def addExtendedProperties(listed: mutable.ArrayBuffer[IProperty], unlisted: mutable.ArrayBuffer[IUnlistedProperty[_]]): Unit = { + super.addExtendedProperties(listed, unlisted) + unlisted += Facing + } - override def createBlockState() = new BlockState(this, Facing) + override protected def addExtendedRawProperties(unlisted: mutable.Map[IUnlistedProperty[_], IProperty]): Unit = { + super.addExtendedRawProperties(unlisted) + unlisted += Facing -> FacingRaw + } } diff --git a/src/main/scala/li/cil/oc/common/init/Items.scala b/src/main/scala/li/cil/oc/common/init/Items.scala index 603509128..b80bf484f 100644 --- a/src/main/scala/li/cil/oc/common/init/Items.scala +++ b/src/main/scala/li/cil/oc/common/init/Items.scala @@ -45,12 +45,15 @@ object Items extends ItemAPI { case simple: SimpleBlock => instance.setUnlocalizedName("oc." + id) GameRegistry.registerBlock(simple, classOf[common.block.Item], id) + OpenComputers.proxy.registerModel(instance, id) - instance.getBlockState.getValidStates.collect { - case state: IBlockState => - val id = Block.blockRegistry.getIDForObject(instance) << 4 | instance.getMetaFromState(state) - Block.BLOCK_STATE_IDS.put(state, id) - } +// Block.BLOCK_STATE_IDS.iterator().remove() +// Block.BLOCK_STATE_IDS.put(instance.getDefaultState, Block.blockRegistry.getIDForObject(instance) << 4) +// instance.getBlockState.getValidStates.collect { +// case state: IBlockState => +// val id = Block.blockRegistry.getIDForObject(instance) << 4 | instance.getMetaFromState(state) +// Block.BLOCK_STATE_IDS.put(state, id) +// } case _ => } @@ -67,7 +70,6 @@ object Items extends ItemAPI { } } names += instance -> id - OpenComputers.proxy.registerModel(instance, id) instance } @@ -82,7 +84,6 @@ object Items extends ItemAPI { override def createItemStack(size: Int) = delegate.createItemStack(size) } names += delegate -> id - OpenComputers.proxy.registerModel(delegate, id) delegate } @@ -91,6 +92,7 @@ object Items extends ItemAPI { case simple: SimpleItem => simple.setUnlocalizedName("oc." + id) GameRegistry.registerItem(simple, id) + OpenComputers.proxy.registerModel(instance) case _ => } descriptors += id -> new ItemInfo { @@ -106,7 +108,6 @@ object Items extends ItemAPI { } } names += instance -> id - OpenComputers.proxy.registerModel(instance, id) instance } @@ -172,6 +173,7 @@ object Items extends ItemAPI { } GameRegistry.registerItem(multi, "item") + OpenComputers.proxy.registerModel(multi) Recipes.addMultiItem(new item.Analyzer(multi), "analyzer", "oc:analyzer") diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Rotatable.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Rotatable.scala index 9f48418fd..23f3e7e22 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/Rotatable.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Rotatable.scala @@ -3,7 +3,6 @@ package li.cil.oc.common.tileentity.traits import li.cil.oc.Settings import li.cil.oc.api.internal import li.cil.oc.server.{PacketSender => ServerPacketSender} -import li.cil.oc.util.BlockPosition import li.cil.oc.util.ExtendedWorld._ import net.minecraft.entity.Entity import net.minecraft.nbt.NBTTagCompound @@ -169,7 +168,7 @@ trait Rotatable extends RotationAware with internal.Rotatable { else { world.markBlockForUpdate(getPos) } - world.notifyBlocksOfNeighborChange(BlockPosition(x, y, z), block) + world.notifyNeighborsOfStateChange(getPos, getBlockType) } // ----------------------------------------------------------------------- // diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/TileEntity.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/TileEntity.scala index 73d32fa04..dc9398709 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/TileEntity.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/TileEntity.scala @@ -24,8 +24,6 @@ trait TileEntity extends net.minecraft.tileentity.TileEntity with IUpdatePlayerL def position = BlockPosition(x, y, z) - def block = getBlockType - def isClient = !isServer def isServer = if (world != null) !world.isRemote else SideTracker.isServer @@ -35,7 +33,7 @@ trait TileEntity extends net.minecraft.tileentity.TileEntity with IUpdatePlayerL def canUpdate = true override def update() { - if (Settings.get.periodicallyForceLightUpdate && world.getTotalWorldTime % 40 == 0 && block.getLightValue(world, getPos) > 0) { + if (Settings.get.periodicallyForceLightUpdate && world.getTotalWorldTime % 40 == 0 && getBlockType.getLightValue(world, getPos) > 0) { world.markBlockForUpdate(getPos) } }