mirror of
https://github.com/GTNewHorizons/bdlib.git
synced 2026-10-26 22:33:53 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6b38472ce | ||
|
|
e6c0ef2c68 | ||
|
|
56110d8ec5 | ||
|
|
f000d11c54 | ||
|
|
913d4f48a6 | ||
|
|
a25553edaf | ||
|
|
82328d10ec | ||
|
|
12f19fc410 | ||
|
|
7c275f434a | ||
|
|
f960050f9c | ||
|
|
87dd7c34c5 | ||
|
|
9fdc6bd880 | ||
|
|
490433a7f4 | ||
|
|
71bef762a6 |
No files matched your search
+1
-1
@@ -21,7 +21,7 @@ buildscript {
|
||||
apply plugin: 'scala'
|
||||
apply plugin: 'forge'
|
||||
|
||||
version = "1.4.1"
|
||||
version = "1.4.3"
|
||||
|
||||
if (project.hasProperty('buildnum')) {
|
||||
project.version = project.version + '.' + project.buildnum
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
bdlib.multiblock.face.north=North
|
||||
bdlib.multiblock.face.south=South
|
||||
bdlib.multiblock.face.east=East
|
||||
bdlib.multiblock.face.west=West
|
||||
bdlib.multiblock.face.up=Top
|
||||
bdlib.multiblock.face.down=Bottom
|
||||
|
||||
bdlib.multiblock.disabled=Disabled
|
||||
bdlib.multiblock.incomplete=This machine is incomplete, it requires at least:
|
||||
bdlib.multiblock.notconnected=Not connected to a valid machine
|
||||
bdlib.multiblock.toomanyoutputs=Too many outputs connected, unable to attach new connection
|
||||
|
||||
bdlib.rsmode.always=Always ON
|
||||
bdlib.rsmode.never=Disabled
|
||||
bdlib.rsmode.rs_on=Enable on redstone
|
||||
bdlib.rsmode.rs_off=Disable on redstone
|
||||
|
||||
bdlib.label.empty=Empty
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
bdlib.multiblock.face.north=Север
|
||||
bdlib.multiblock.face.south=Юг
|
||||
bdlib.multiblock.face.east=Восток
|
||||
bdlib.multiblock.face.west=Запад
|
||||
bdlib.multiblock.face.up=Верх
|
||||
bdlib.multiblock.face.down=Низ
|
||||
|
||||
bdlib.multiblock.disabled=Отключено
|
||||
bdlib.multiblock.incomplete=Этот механизм не завершён, ему требуется как минимум:
|
||||
bdlib.multiblock.notconnected=Не подключено к верному механизму
|
||||
bdlib.multiblock.toomanyoutputs=Слишком много выходов подсоединено, нельзя установить новое соединение
|
||||
|
||||
bdlib.rsmode.always=Всегда ВКЛ.
|
||||
bdlib.rsmode.never=Отключен
|
||||
bdlib.rsmode.rs_on=Включение по сигналу красного камня
|
||||
bdlib.rsmode.rs_off=Отключение по сигналу красного камня
|
||||
|
||||
bdlib.label.empty=Пусто
|
||||
@@ -12,6 +12,7 @@ package net.bdew.lib
|
||||
import cpw.mods.fml.common.Mod
|
||||
import cpw.mods.fml.common.Mod.EventHandler
|
||||
import cpw.mods.fml.common.event.{FMLPreInitializationEvent, FMLServerStartingEvent}
|
||||
import net.bdew.lib.multiblock.network.NetHandler
|
||||
import net.minecraft.command.CommandHandler
|
||||
import org.apache.logging.log4j.Logger
|
||||
|
||||
@@ -29,6 +30,7 @@ object BdLib {
|
||||
def preInit(ev: FMLPreInitializationEvent) {
|
||||
log = ev.getModLog
|
||||
log.info("bdlib BDLIB_VER loaded")
|
||||
NetHandler.init()
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib
|
||||
|
||||
import net.minecraft.creativetab.CreativeTabs
|
||||
import net.minecraft.item.Item
|
||||
|
||||
class CreativeTabContainer {
|
||||
|
||||
class Tab(name: String, item: => Item) extends CreativeTabs(name) {
|
||||
override def getTabIconItem = item
|
||||
}
|
||||
|
||||
BdLib.logInfo("Loaded creative tabs for %s", Misc.getActiveModId)
|
||||
|
||||
def init() {}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ object Misc {
|
||||
|
||||
def filterType[T](from: Iterable[_], cls: Class[T]) = from.filter(cls.isInstance).asInstanceOf[Iterable[T]]
|
||||
|
||||
def getBiomeByName(name: String) = BiomeGenBase.getBiomeGenArray.find(x => x != null && x.biomeName == name).getOrElse(null)
|
||||
def getBiomeByName(name: String) = BiomeGenBase.getBiomeGenArray.find(x => x != null && x.biomeName == name).orNull
|
||||
|
||||
def haveModVersion(spec: String): Boolean = {
|
||||
val req = VersionParser.parseVersionReference(spec)
|
||||
@@ -89,5 +89,10 @@ object Misc {
|
||||
def getNeighbourTile[T](origin: TileEntity, dir: ForgeDirection, cls: Class[T]) =
|
||||
Option(origin.getWorldObj.getTileEntity(origin.xCoord + dir.offsetX,
|
||||
origin.yCoord + dir.offsetY, origin.zCoord + dir.offsetZ)) flatMap (asInstanceOpt(_, cls))
|
||||
|
||||
def applyMutator[T](f: (T) => Unit, init: T): T = {
|
||||
f(init)
|
||||
init
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.block
|
||||
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
case class BlockFace(x: Int, y: Int, z: Int, face: ForgeDirection) {
|
||||
def origin = BlockRef(x, y, z)
|
||||
def target = origin.neighbour(face)
|
||||
def opposite = face.getOpposite
|
||||
}
|
||||
|
||||
object BlockFace {
|
||||
def apply(bp: BlockRef, face: ForgeDirection) = new BlockFace(bp.x, bp.y, bp.z, face)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.block
|
||||
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.world.IBlockAccess
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
import scala.reflect.ClassTag
|
||||
|
||||
case class BlockRef(x: Int, y: Int, z: Int) {
|
||||
def block(w: IBlockAccess) = Option(w.getBlock(x, y, z))
|
||||
def tile(w: IBlockAccess) = Option(w.getTileEntity(x, y, z))
|
||||
def meta(w: IBlockAccess) = w.getBlockMetadata(x, y, z)
|
||||
|
||||
def blockIs(w: IBlockAccess, other: Block) = block(w).contains(other)
|
||||
|
||||
def neighbour(side: ForgeDirection) = BlockRef(x + side.offsetX, y + side.offsetY, z + side.offsetZ)
|
||||
def neighbours = ForgeDirection.VALID_DIRECTIONS.map(x => x -> neighbour(x)).toMap
|
||||
|
||||
override def toString = "(x=%d y=%d z=%d)".format(x, y, z)
|
||||
|
||||
def getTile[T: ClassTag](w: IBlockAccess) = tile(w) flatMap { tile =>
|
||||
val cls = implicitly[ClassTag[T]].runtimeClass
|
||||
if (cls.isInstance(tile))
|
||||
Some(tile.asInstanceOf[T])
|
||||
else None
|
||||
}
|
||||
|
||||
def ==(tx: Int, ty: Int, tz: Int) = x == tx && y == ty && z == tz
|
||||
|
||||
def getBlock[T: ClassTag](w: IBlockAccess) = block(w) flatMap { block =>
|
||||
val cls = implicitly[ClassTag[T]].runtimeClass
|
||||
if (cls.isInstance(block))
|
||||
Some(block.asInstanceOf[T])
|
||||
else None
|
||||
}
|
||||
|
||||
def writeToNBT(tag: NBTTagCompound) {
|
||||
tag.setInteger("x", x)
|
||||
tag.setInteger("y", y)
|
||||
tag.setInteger("z", z)
|
||||
}
|
||||
}
|
||||
|
||||
object BlockRef {
|
||||
def fromTile(te: TileEntity) = BlockRef(te.xCoord, te.yCoord, te.zCoord)
|
||||
def fromNBT(tag: NBTTagCompound) =
|
||||
BlockRef(tag.getInteger("x"), tag.getInteger("y"), tag.getInteger("z"))
|
||||
}
|
||||
@@ -18,6 +18,9 @@ trait HasTE[T] extends Block with ITileEntityProvider {
|
||||
val TEClass: Class[_ <: TileEntity]
|
||||
|
||||
def createNewTileEntity(world: World, meta: Int): TileEntity = TEClass.newInstance()
|
||||
|
||||
def getTE(w: IBlockAccess, ref: BlockRef): T = getTE(w, ref.x, ref.y, ref.z)
|
||||
|
||||
def getTE(w: IBlockAccess, x: Int, y: Int, z: Int): T = {
|
||||
var t = w.getTileEntity(x, y, z)
|
||||
if ((t == null) || !TEClass.isInstance(t)) {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.block
|
||||
|
||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||
import net.bdew.lib.Misc
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.client.renderer.texture.IIconRegister
|
||||
|
||||
trait NamedBlock extends Block {
|
||||
def name: String
|
||||
}
|
||||
|
||||
class SimpleBlock(val name: String, material: Material) extends Block(material) with NamedBlock {
|
||||
val modId = Misc.getActiveModId
|
||||
setBlockName(modId + "." + name)
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def registerBlockIcons(reg: IIconRegister) {
|
||||
blockIcon = reg.registerIcon(modId + ":" + name.toLowerCase)
|
||||
}
|
||||
}
|
||||
@@ -11,20 +11,19 @@ package net.bdew.lib.config
|
||||
|
||||
import cpw.mods.fml.common.registry.GameRegistry
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.block.HasTE
|
||||
import net.bdew.lib.block.{HasTE, NamedBlock}
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.creativetab.CreativeTabs
|
||||
import net.minecraft.item.ItemStack
|
||||
|
||||
class BlockManager() {
|
||||
|
||||
def regBlockCls[T <: Block](blockCls: Class[T], name: String, addStack: Boolean = false): T = {
|
||||
val block = blockCls.newInstance()
|
||||
regBlock[T](block, name, addStack)
|
||||
}
|
||||
class BlockManager(creativeTab: CreativeTabs) {
|
||||
def regBlock[T <: NamedBlock](block: T): T = regBlock(block, block.name)
|
||||
|
||||
def regBlock[T <: Block](block: T, name: String, addStack: Boolean = false): T = {
|
||||
GameRegistry.registerBlock(block, name)
|
||||
|
||||
block.setCreativeTab(creativeTab)
|
||||
|
||||
if (addStack)
|
||||
GameRegistry.registerCustomItemStack(name, new ItemStack(block))
|
||||
|
||||
|
||||
@@ -11,23 +11,21 @@ package net.bdew.lib.config
|
||||
|
||||
import cpw.mods.fml.common.registry.GameRegistry
|
||||
import net.bdew.lib.items.{NamedItem, SimpleItem}
|
||||
import net.minecraft.creativetab.CreativeTabs
|
||||
import net.minecraft.item.{Item, ItemStack}
|
||||
|
||||
class ItemManager() {
|
||||
class ItemManager(creativeTab: CreativeTabs) {
|
||||
def regSimpleItem(name: String): SimpleItem = regItem(new SimpleItem(name), name)
|
||||
|
||||
def regItem[T <: NamedItem](item: T): T = regItem[T](item, item.name)
|
||||
|
||||
def regItemCls[T <: Item](itemCls: Class[T], name: String, addStack: Boolean = false): T = {
|
||||
val item = itemCls.newInstance()
|
||||
regItem[T](item, name, addStack)
|
||||
}
|
||||
|
||||
def regItem[T <: Item](item: T, name: String, addStack: Boolean = false): T = {
|
||||
GameRegistry.registerItem(item, name)
|
||||
item.setCreativeTab(creativeTab)
|
||||
if (addStack)
|
||||
GameRegistry.registerCustomItemStack(name, new ItemStack(item))
|
||||
return item
|
||||
}
|
||||
|
||||
def load() {}
|
||||
}
|
||||
@@ -12,13 +12,14 @@ package net.bdew.lib.config
|
||||
import net.bdew.lib.gui.{GuiHandler, GuiProvider}
|
||||
import net.bdew.lib.machine.Machine
|
||||
import net.bdew.lib.recipes.gencfg.ConfigSection
|
||||
import net.minecraft.creativetab.CreativeTabs
|
||||
|
||||
class MachineManager(val tuning: ConfigSection, guiHandler: GuiHandler) {
|
||||
class MachineManager(val tuning: ConfigSection, guiHandler: GuiHandler, creativeTab: CreativeTabs) {
|
||||
def registerMachine[R <: Machine[_]](machine: R): R = {
|
||||
machine.tuning = tuning.getSection(machine.name)
|
||||
if (machine.tuning.getBoolean("Enabled")) {
|
||||
machine.enabled = true
|
||||
machine.regBlock()
|
||||
machine.regBlock(creativeTab)
|
||||
if (machine.isInstanceOf[GuiProvider])
|
||||
guiHandler.register(machine.asInstanceOf[GuiProvider])
|
||||
}
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data
|
||||
|
||||
import java.util.UUID
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.data
|
||||
|
||||
import net.bdew.lib.data.base.DataSlotVal
|
||||
|
||||
abstract class DataSlotOption[T] extends DataSlotVal[Option[T]] {
|
||||
override var cval: Option[T] = None
|
||||
|
||||
def set(v: T) {
|
||||
if (v == null) sys.error("Null should never be used with DataSlotOption")
|
||||
cval = Some(v)
|
||||
}
|
||||
|
||||
def unset() {
|
||||
cval = None
|
||||
}
|
||||
|
||||
override def isSame(v: Option[T]) = {
|
||||
if (v == null) sys.error("Null should never be used with DataSlotOption")
|
||||
super.isSame(v)
|
||||
}
|
||||
override def :=(that: Option[T]) = {
|
||||
if (that == null) sys.error("Null should never be used with DataSlotOption")
|
||||
super.:=(that)
|
||||
}
|
||||
override def :!=(that: Option[T]) = {
|
||||
if (that == null) sys.error("Null should never be used with DataSlotOption")
|
||||
super.:!=(that)
|
||||
}
|
||||
override def :==(that: Option[T]) = {
|
||||
if (that == null) sys.error("Null should never be used with DataSlotOption")
|
||||
super.:==(that)
|
||||
}
|
||||
override def update(v: Option[T]) = {
|
||||
if (v == null) sys.error("Null should never be used with DataSlotOption")
|
||||
super.update(v)
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,19 @@ abstract class DataSlotTankBase(sz: Int) extends FluidTank(sz) with IFluidTank w
|
||||
if (k == UpdateKind.GUI)
|
||||
setCapacity(tag.getInteger("size"))
|
||||
}
|
||||
override def setFluid(fluid: FluidStack) = execWithChangeNotify(super.setFluid(fluid))
|
||||
override def setCapacity(capacity: Int) = execWithChangeNotify(super.setCapacity(capacity))
|
||||
override def drain(maxDrain: Int, doDrain: Boolean) =
|
||||
if (doDrain)
|
||||
execWithChangeNotify(super.drain(maxDrain, true))
|
||||
else
|
||||
super.drain(maxDrain, false)
|
||||
|
||||
override def fill(resource: FluidStack, doFill: Boolean) =
|
||||
if (doFill)
|
||||
execWithChangeNotify(super.fill(resource, true))
|
||||
else
|
||||
super.fill(resource, false)
|
||||
}
|
||||
|
||||
case class DataSlotTank(name: String, parent: TileDataSlots, size: Int) extends DataSlotTankBase(size)
|
||||
|
||||
@@ -35,6 +35,12 @@ trait DataSlot {
|
||||
def save(t: NBTTagCompound, kind: UpdateKind.Value)
|
||||
def load(t: NBTTagCompound, kind: UpdateKind.Value)
|
||||
|
||||
def execWithChangeNotify[T](f: => T): T = {
|
||||
val v = f
|
||||
parent.dataSlotChanged(this)
|
||||
v
|
||||
}
|
||||
|
||||
def setUpdate(vals: UpdateKind.Value*): this.type = {
|
||||
updateKind = vals.toSet
|
||||
return this
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.gui.widgets
|
||||
|
||||
import net.bdew.lib.gui.{Point, Rect, Texture}
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.audio.PositionedSoundRecord
|
||||
import net.minecraft.util.ResourceLocation
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
class WidgetButtonIcon(p: Point, clicked: WidgetButtonIcon => Unit, baseTex: Texture, hoverTex: Texture) extends Widget {
|
||||
val rect = new Rect(p, 16, 16)
|
||||
val iconRect = new Rect(p +(1, 1), 14, 14)
|
||||
|
||||
var icon: Texture = null
|
||||
var hover: String = null
|
||||
|
||||
override def draw(mouse: Point) {
|
||||
if (rect.contains(mouse))
|
||||
parent.drawTexture(rect, hoverTex)
|
||||
else
|
||||
parent.drawTexture(rect, baseTex)
|
||||
|
||||
if (icon != null)
|
||||
parent.drawTexture(iconRect, icon)
|
||||
}
|
||||
|
||||
override def handleTooltip(p: Point, tip: mutable.MutableList[String]) {
|
||||
if (hover != null && hover > "")
|
||||
tip += hover
|
||||
}
|
||||
|
||||
override def mouseClicked(p: Point, button: Int) {
|
||||
Minecraft.getMinecraft.getSoundHandler.playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F))
|
||||
clicked(this)
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
package net.bdew.lib.gui.widgets
|
||||
|
||||
import net.bdew.lib.gui.{Rect, _}
|
||||
import net.bdew.lib.gui._
|
||||
|
||||
class WidgetSubcontainer(val rect: Rect) extends BaseWidget with WidgetContainer with SimpleDrawTarget {
|
||||
def getZLevel = parent.getZLevel
|
||||
|
||||
@@ -14,6 +14,7 @@ import net.bdew.lib.Misc
|
||||
import net.bdew.lib.block.HasTE
|
||||
import net.bdew.lib.recipes.gencfg.ConfigSection
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.creativetab.CreativeTabs
|
||||
|
||||
abstract class Machine[T <: Block](val name: String, blockConstruct: => T) {
|
||||
var block: T = null.asInstanceOf[T]
|
||||
@@ -21,9 +22,10 @@ abstract class Machine[T <: Block](val name: String, blockConstruct: => T) {
|
||||
var enabled = false
|
||||
val modId = Misc.getActiveModId
|
||||
|
||||
def regBlock() {
|
||||
def regBlock(creativeTab: CreativeTabs) {
|
||||
block = blockConstruct
|
||||
GameRegistry.registerBlock(block, name)
|
||||
block.setCreativeTab(creativeTab)
|
||||
if (block.isInstanceOf[HasTE[_]]) {
|
||||
GameRegistry.registerTileEntity(block.asInstanceOf[HasTE[_]].TEClass, "%s.%s".format(modId, name))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock
|
||||
|
||||
import net.bdew.lib.recipes.gencfg.{ConfigSection, EntryDouble}
|
||||
|
||||
trait MachineCore {
|
||||
var tuning: ConfigSection
|
||||
|
||||
def cfgSectionToMap(name: String) = tuning.getSection(name).map({
|
||||
case (n, EntryDouble(v)) => n -> v.toInt
|
||||
case (n, x) => sys.error("Invalid config value in section %s%s.%s = %s".format(tuning.pfx, name, n, x))
|
||||
}).toMap
|
||||
|
||||
lazy val modules = cfgSectionToMap("Modules")
|
||||
lazy val required = cfgSectionToMap("Required")
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock
|
||||
|
||||
import net.bdew.lib.gui.{Color, Texture}
|
||||
import net.minecraft.util.IIcon
|
||||
|
||||
trait ResourceProvider {
|
||||
// Icons for rendering, *must* be on block spritesheet
|
||||
def edge: IIcon
|
||||
def disabled: IIcon
|
||||
def output: IIcon
|
||||
def arrowTop: IIcon
|
||||
def arrowRight: IIcon
|
||||
def arrowBottom: IIcon
|
||||
def arrowLeft: IIcon
|
||||
|
||||
// Textures for GUI stuff
|
||||
def btBase: Texture
|
||||
def btHover: Texture
|
||||
def btRsOn: Texture
|
||||
def btRsOff: Texture
|
||||
def btEnabled: Texture
|
||||
def btDisabled: Texture
|
||||
|
||||
val outputColors: Map[Int, Color]
|
||||
val unlocalizedOutputName: Map[Int, String]
|
||||
def getModuleName(s: String): String
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock
|
||||
|
||||
import net.bdew.lib.block.BlockRef
|
||||
import net.bdew.lib.multiblock.tile.{TileController, TileModule}
|
||||
import net.minecraft.world.World
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
object Tools {
|
||||
def canConnect(world: World, core: BlockRef, kind: String): Boolean = {
|
||||
val t = core.getTile[TileController](world).getOrElse(return false)
|
||||
t.getNumOfMoudules(kind) < t.cfg.modules.getOrElse(kind, return false)
|
||||
}
|
||||
|
||||
def findConnections(world: World, start: BlockRef, kind: String) =
|
||||
(start.neighbours.values flatMap { case pos =>
|
||||
(pos.tile(world) flatMap {
|
||||
case t: TileModule => t.connected.cval
|
||||
case t: TileController => Some(pos)
|
||||
case _ => None
|
||||
}) filter (x => canConnect(world, x, kind))
|
||||
}).toList.distinct
|
||||
|
||||
def getAdjancedConnected(w: World, core: BlockRef, pos: BlockRef, seen: mutable.Set[BlockRef]) =
|
||||
pos.neighbours.values
|
||||
.filterNot(seen.contains)
|
||||
.flatMap(_.getTile[TileModule](w))
|
||||
.filter(x => x.connected.contains(core))
|
||||
.map(_.mypos)
|
||||
|
||||
def findReachableModules(world: World, core: BlockRef): Set[BlockRef] = {
|
||||
val seen = mutable.Set.empty[BlockRef]
|
||||
val queue = mutable.Queue.empty[BlockRef]
|
||||
queue ++= getAdjancedConnected(world, core, core, seen)
|
||||
while (queue.size > 0) {
|
||||
val current = queue.dequeue()
|
||||
seen.add(current)
|
||||
queue ++= getAdjancedConnected(world, core, current, seen)
|
||||
}
|
||||
return seen.toSet
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.block
|
||||
|
||||
import net.bdew.lib.block.{BlockRef, HasTE}
|
||||
import net.bdew.lib.multiblock.ResourceProvider
|
||||
import net.bdew.lib.multiblock.tile.TileController
|
||||
import net.bdew.lib.render.connected.ConnectedTextureBlock
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.world.{IBlockAccess, World}
|
||||
|
||||
abstract class BlockController[T <: TileController](val name: String, material: Material, val TEClass: Class[T])
|
||||
extends Block(material) with HasTE[T] with ConnectedTextureBlock {
|
||||
|
||||
def resources: ResourceProvider
|
||||
|
||||
override def edgeIcon = resources.edge
|
||||
|
||||
override def breakBlock(world: World, x: Int, y: Int, z: Int, block: Block, meta: Int) {
|
||||
getTE(world, x, y, z).onBreak()
|
||||
super.breakBlock(world, x, y, z, block, meta)
|
||||
}
|
||||
|
||||
override def canConnect(world: IBlockAccess, origin: BlockRef, target: BlockRef) =
|
||||
getTE(world, origin).modules.contains(target)
|
||||
|
||||
override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, meta: Int, xoffs: Float, yoffs: Float, zoffs: Float): Boolean = {
|
||||
if (player.isSneaking) return false
|
||||
if (world.isRemote) return true
|
||||
getTE(world, x, y, z).onClick(player)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.block
|
||||
|
||||
import net.bdew.lib.block.{BlockRef, HasTE}
|
||||
import net.bdew.lib.multiblock.tile.TileModule
|
||||
import net.bdew.lib.multiblock.{ResourceProvider, Tools}
|
||||
import net.bdew.lib.render.connected.ConnectedTextureBlock
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.entity.EntityLivingBase
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.ChatComponentTranslation
|
||||
import net.minecraft.world.{IBlockAccess, World}
|
||||
|
||||
abstract class BlockModule[T <: TileModule](val name: String, val kind: String, material: Material, val TEClass: Class[T])
|
||||
extends Block(material) with HasTE[T] with ConnectedTextureBlock {
|
||||
|
||||
def resources: ResourceProvider
|
||||
|
||||
override def edgeIcon = resources.edge
|
||||
|
||||
override def canPlaceBlockAt(world: World, x: Int, y: Int, z: Int): Boolean =
|
||||
Tools.findConnections(world, BlockRef(x, y, z), kind).size <= 1
|
||||
|
||||
override def onBlockPlacedBy(world: World, x: Int, y: Int, z: Int, player: EntityLivingBase, stack: ItemStack) {
|
||||
getTE(world, x, y, z).tryConnect()
|
||||
}
|
||||
|
||||
override def onNeighborBlockChange(world: World, x: Int, y: Int, z: Int, block: Block) {
|
||||
getTE(world, x, y, z).tryConnect()
|
||||
}
|
||||
|
||||
override def breakBlock(world: World, x: Int, y: Int, z: Int, block: Block, meta: Int) {
|
||||
getTE(world, x, y, z).onBreak()
|
||||
super.breakBlock(world, x, y, z, block, meta)
|
||||
}
|
||||
|
||||
override def canConnect(world: IBlockAccess, origin: BlockRef, target: BlockRef) = {
|
||||
val me = getTE(world, origin)
|
||||
me.connected.contains(target) ||
|
||||
(target.getTile[TileModule](world) exists { other =>
|
||||
me.getCore.isDefined && other.getCore == me.getCore
|
||||
})
|
||||
}
|
||||
|
||||
override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, meta: Int, xoffs: Float, yoffs: Float, zoffs: Float): Boolean = {
|
||||
if (player.isSneaking) return false
|
||||
if (world.isRemote) return true
|
||||
val te = getTE(world, x, y, z)
|
||||
(for {
|
||||
p <- te.connected.cval
|
||||
bl <- p.block(world)
|
||||
} yield {
|
||||
bl.onBlockActivated(world, p.x, p.y, p.z, player, meta, 0, 0, 0)
|
||||
}) getOrElse {
|
||||
player.addChatMessage(new ChatComponentTranslation("bdlib.multiblock.notconnected"))
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.block
|
||||
|
||||
import net.bdew.lib.block.{BlockFace, BlockRef}
|
||||
import net.bdew.lib.multiblock.tile.TileOutput
|
||||
import net.bdew.lib.render.connected.{BlockAdditionalRender, ConnectedHelper, FaceOverlay}
|
||||
import net.minecraft.world.IBlockAccess
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
trait BlockOutput[T <: TileOutput] extends BlockModule[T] with BlockAdditionalRender {
|
||||
def getAdjancedFaces(face: ForgeDirection, bp: BlockRef) = {
|
||||
val sides = ConnectedHelper.faceAdjanced(face)
|
||||
Seq(
|
||||
(BlockFace(bp, sides.top), resources.arrowTop),
|
||||
(BlockFace(bp, sides.right), resources.arrowRight),
|
||||
(BlockFace(bp, sides.bottom), resources.arrowBottom),
|
||||
(BlockFace(bp, sides.left), resources.arrowLeft)
|
||||
)
|
||||
}
|
||||
|
||||
def getFaceOverlays(world: IBlockAccess, x: Int, y: Int, z: Int, face: ForgeDirection): List[FaceOverlay] = {
|
||||
var result = List.empty[FaceOverlay]
|
||||
Option(getTE(world, x, y, z)) flatMap (_.getCore) map { core =>
|
||||
val bf = BlockFace(x, y, z, face)
|
||||
if (core.outputFaces.contains(bf))
|
||||
result :+= FaceOverlay(resources.output, resources.outputColors(core.outputFaces(bf)))
|
||||
for ((bf, icon) <- getAdjancedFaces(face, bf.origin)) {
|
||||
if (core.outputFaces.contains(bf))
|
||||
result :+= FaceOverlay(icon, resources.outputColors(core.outputFaces(bf)))
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.data
|
||||
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.block.BlockFace
|
||||
import net.bdew.lib.data.base.{DataSlot, TileDataSlots, UpdateKind}
|
||||
import net.minecraft.nbt.{NBTTagCompound, NBTTagIntArray, NBTTagList}
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
case class DataSlotBlockFaceMap(name: String, parent: TileDataSlots) extends DataSlot {
|
||||
val map = collection.mutable.Map.empty[BlockFace, Int]
|
||||
|
||||
setUpdate(UpdateKind.SAVE, UpdateKind.WORLD)
|
||||
|
||||
def inverted = map.map(_.swap)
|
||||
|
||||
def ent2arr(x: (BlockFace, Int)) = Array(x._2, x._1.x, x._1.y, x._1.z, x._1.face.ordinal())
|
||||
def arr2ent(x: Array[Int]) = BlockFace(x(1), x(2), x(3), ForgeDirection.values()(x(4))) -> x(0)
|
||||
|
||||
def save(t: NBTTagCompound, kind: UpdateKind.Value) {
|
||||
val lst = new NBTTagList()
|
||||
for (x <- map) lst.appendTag(new NBTTagIntArray(ent2arr(x)))
|
||||
t.setTag(name, lst)
|
||||
}
|
||||
|
||||
def load(t: NBTTagCompound, kind: UpdateKind.Value) {
|
||||
map.clear()
|
||||
map ++= Misc.iterNbtIntArray(t, name) map arr2ent
|
||||
}
|
||||
|
||||
def updated() = parent.dataSlotChanged(this)
|
||||
}
|
||||
|
||||
object DataSlotBlockFaceMap {
|
||||
|
||||
import scala.language.implicitConversions
|
||||
|
||||
implicit def dsbfm2map(v: DataSlotBlockFaceMap) = v.map
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.data
|
||||
|
||||
import net.bdew.lib.data.base.{DataSlot, TileDataSlots, UpdateKind}
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
case class DataSlotOutputConfig(name: String, parent: TileDataSlots, slots: Int) extends DataSlot {
|
||||
val map = collection.mutable.Map.empty[Int, OutputConfig]
|
||||
|
||||
setUpdate(UpdateKind.SAVE, UpdateKind.GUI)
|
||||
|
||||
def inverted = map.map(_.swap)
|
||||
|
||||
def save(t: NBTTagCompound, kind: UpdateKind.Value) {
|
||||
for ((n, x) <- map) {
|
||||
val tmp = new NBTTagCompound()
|
||||
x.write(tmp)
|
||||
val kind = x match {
|
||||
case _: OutputConfigPower => "power"
|
||||
case _ => sys.error("Unknown output config kind: " + x)
|
||||
}
|
||||
tmp.setString("kind", kind)
|
||||
t.setTag(name + "_" + n, tmp)
|
||||
}
|
||||
}
|
||||
|
||||
def load(t: NBTTagCompound, kind: UpdateKind.Value) {
|
||||
map.clear()
|
||||
for (i <- 0 until slots) {
|
||||
if (t.hasKey(name + "_" + i)) {
|
||||
val cfg = t.getCompoundTag(name + "_" + i)
|
||||
val cfgObj = cfg.getString("kind") match {
|
||||
case "power" => new OutputConfigPower
|
||||
case x => new OutputConfigInvalid
|
||||
}
|
||||
cfgObj.read(cfg)
|
||||
map += i -> cfgObj
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def updated() = parent.dataSlotChanged(this)
|
||||
}
|
||||
|
||||
object DataSlotOutputConfig {
|
||||
|
||||
import scala.language.implicitConversions
|
||||
|
||||
implicit def dsbfm2map(v: DataSlotOutputConfig) = v.map
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.data
|
||||
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.block.BlockRef
|
||||
import net.bdew.lib.data.DataSlotOption
|
||||
import net.bdew.lib.data.base.{TileDataSlots, UpdateKind}
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
case class DataSlotPos(name: String, parent: TileDataSlots) extends DataSlotOption[BlockRef] {
|
||||
setUpdate(UpdateKind.SAVE, UpdateKind.WORLD)
|
||||
|
||||
def save(t: NBTTagCompound, kind: UpdateKind.Value) {
|
||||
cval map (x => t.setTag(name, Misc.applyMutator(x.writeToNBT, new NBTTagCompound)))
|
||||
}
|
||||
|
||||
def load(t: NBTTagCompound, kind: UpdateKind.Value) {
|
||||
cval = if (t.hasKey(name))
|
||||
Some(BlockRef.fromNBT(t.getCompoundTag(name)))
|
||||
else
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.data
|
||||
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.block.BlockRef
|
||||
import net.bdew.lib.data.base.{DataSlot, TileDataSlots, UpdateKind}
|
||||
import net.minecraft.nbt.{NBTTagCompound, NBTTagList}
|
||||
|
||||
case class DataSlotPosSet(name: String, parent: TileDataSlots) extends DataSlot {
|
||||
val set = collection.mutable.Set.empty[BlockRef]
|
||||
|
||||
setUpdate(UpdateKind.SAVE, UpdateKind.WORLD)
|
||||
|
||||
def save(t: NBTTagCompound, kind: UpdateKind.Value) {
|
||||
val lst = new NBTTagList()
|
||||
for (x <- set) lst.appendTag(Misc.applyMutator(x.writeToNBT, new NBTTagCompound))
|
||||
t.setTag(name, lst)
|
||||
}
|
||||
|
||||
def load(t: NBTTagCompound, kind: UpdateKind.Value) {
|
||||
set.clear()
|
||||
set ++= Misc.iterNbtCompoundList(t, name) map BlockRef.fromNBT
|
||||
}
|
||||
|
||||
def updated() = parent.dataSlotChanged(this)
|
||||
|
||||
}
|
||||
|
||||
object DataSlotPosSet {
|
||||
|
||||
import scala.language.implicitConversions
|
||||
|
||||
implicit def dsps2set(v: DataSlotPosSet) = v.set
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.data
|
||||
|
||||
import net.bdew.lib.multiblock.network.MsgOutputCfg
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import sun.reflect.generics.reflectiveObjects.NotImplementedException
|
||||
|
||||
abstract class OutputConfig {
|
||||
def read(t: NBTTagCompound)
|
||||
def write(t: NBTTagCompound)
|
||||
def handleConfigPacket(m: MsgOutputCfg)
|
||||
}
|
||||
|
||||
class OutputConfigInvalid extends OutputConfig {
|
||||
def read(t: NBTTagCompound) {}
|
||||
def write(t: NBTTagCompound) = throw new NotImplementedException
|
||||
def handleConfigPacket(m: MsgOutputCfg) = throw new NotImplementedException
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.data
|
||||
|
||||
import net.bdew.lib.multiblock.network.MsgOutputCfg
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
case class MsgOutputCfgPower(output: Int, rsMode: RSMode.Value) extends MsgOutputCfg
|
||||
|
||||
class OutputConfigPower extends OutputConfig {
|
||||
var avg = 0.0
|
||||
var rsMode = RSMode.ALWAYS
|
||||
var unit = "MJ"
|
||||
|
||||
final val decay = 0.5
|
||||
|
||||
def updateAvg(v: Double) {
|
||||
avg = avg * decay + (1 - decay) * v
|
||||
}
|
||||
|
||||
def read(t: NBTTagCompound) {
|
||||
avg = t.getDouble("avg")
|
||||
rsMode = RSMode(t.getInteger("rsMode"))
|
||||
unit = t.getString("unit")
|
||||
}
|
||||
|
||||
def write(t: NBTTagCompound) {
|
||||
t.setDouble("avg", avg)
|
||||
t.setInteger("rsMode", rsMode.id)
|
||||
t.setString("unit", unit)
|
||||
}
|
||||
|
||||
def handleConfigPacket(m: MsgOutputCfg) = m match {
|
||||
case MsgOutputCfgPower(_, r) => rsMode = r
|
||||
case _ => sys.error("Invalid output config packet %s to config %s".format(m, this))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.data
|
||||
|
||||
object RSMode extends Enumeration {
|
||||
val ALWAYS = Value(0, "ALWAYS")
|
||||
val RS_ON = Value(1, "RS_ON")
|
||||
val RS_OFF = Value(2, "RS_OFF")
|
||||
val NEVER = Value(3, "NEVER")
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.gui
|
||||
|
||||
import net.bdew.lib.gui.widgets.Widget
|
||||
import net.bdew.lib.gui.{Color, Point, Rect, Texture}
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
class WidgetInfo(val rect: Rect, icon: Texture, text: => String, tooltip: => String) extends Widget {
|
||||
final val iconRect = Rect(1, 1, 8, 8)
|
||||
|
||||
override def handleTooltip(p: Point, tip: mutable.MutableList[String]) {
|
||||
if (iconRect.contains(p) && tooltip != null) tip += tooltip
|
||||
}
|
||||
|
||||
override def draw(mouse: Point) {
|
||||
parent.drawTexture(iconRect + rect.origin, icon)
|
||||
parent.drawText(text, rect.origin +(12, 1), Color.darkgray, false)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.gui
|
||||
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.gui.widgets.Widget
|
||||
import net.bdew.lib.gui.{Point, Rect, Texture}
|
||||
import net.bdew.lib.multiblock.interact.CIOutputFaces
|
||||
import net.bdew.lib.render.connected.BlockAdditionalRender
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
class WidgetOutputIcon(p: Point, te: CIOutputFaces, output: Int) extends Widget {
|
||||
val rect = new Rect(p, 16, 16)
|
||||
|
||||
override def draw(mouse: Point) {
|
||||
val faces = te.outputFaces.inverted
|
||||
if (faces.isDefinedAt(output)) {
|
||||
val bf = faces(output)
|
||||
bf.origin.block(te.getWorldObj) map { block =>
|
||||
parent.drawTexture(rect, Texture(Texture.BLOCKS, block.getIcon(te.getWorldObj, bf.origin.x, bf.origin.y, bf.origin.z, bf.face.ordinal())))
|
||||
if (block.isInstanceOf[BlockAdditionalRender]) {
|
||||
for (over <- block.asInstanceOf[BlockAdditionalRender].getFaceOverlays(te.getWorldObj, bf.origin.x, bf.origin.y, bf.origin.z, bf.face))
|
||||
parent.drawTexture(rect, Texture(Texture.BLOCKS, over.icon), over.color)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parent.drawTexture(rect, Texture(Texture.BLOCKS, te.resources.disabled), te.resources.outputColors(output))
|
||||
}
|
||||
}
|
||||
|
||||
override def handleTooltip(p: Point, tip: mutable.MutableList[String]) {
|
||||
val faces = te.outputFaces.inverted
|
||||
tip += Misc.toLocal(te.resources.unlocalizedOutputName(output))
|
||||
if (faces.isDefinedAt(output)) {
|
||||
val bf = faces(output)
|
||||
bf.origin.block(te.getWorldObj) map { block =>
|
||||
tip += block.getLocalizedName
|
||||
tip += "%d, %d, %d - %s".format(bf.x, bf.y, bf.z, Misc.toLocal("bdlib.multiblock.face." + bf.face.toString.toLowerCase))
|
||||
}
|
||||
} else {
|
||||
tip += Misc.toLocal("bdlib.multiblock.disabled")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.gui
|
||||
|
||||
import net.bdew.lib.gui.widgets.{WidgetMultipane, WidgetSubcontainer}
|
||||
import net.bdew.lib.gui.{Rect, _}
|
||||
import net.bdew.lib.multiblock.data.OutputConfigPower
|
||||
import net.bdew.lib.multiblock.interact.CIOutputFaces
|
||||
|
||||
class WidgetOutputs(p: Point, te: CIOutputFaces, rows: Int) extends WidgetSubcontainer(new Rect(p, 92, 19 * rows)) {
|
||||
for (i <- 0 until rows)
|
||||
add(new WidgetOutputRow(Point(0, 19 * i), te, i))
|
||||
}
|
||||
|
||||
class WidgetOutputDisplay extends WidgetSubcontainer(Rect(20, 0, 72, 18))
|
||||
|
||||
class WidgetOutputRow(p: Point, te: CIOutputFaces, output: Int) extends WidgetMultipane(new Rect(p, 92, 18)) {
|
||||
add(new WidgetOutputIcon(Point(1, 1), te, output))
|
||||
val emptyPane = addPane(new WidgetSubcontainer(rect))
|
||||
val powerPane = addPane(new WidgetPowerOutput(te, output))
|
||||
|
||||
def getActivePane =
|
||||
te.outputConfig.get(output) match {
|
||||
case Some(x: OutputConfigPower) => powerPane
|
||||
case _ => emptyPane
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.gui
|
||||
|
||||
import java.text.DecimalFormat
|
||||
|
||||
import net.bdew.lib.Misc
|
||||
import net.bdew.lib.gui.widgets.{WidgetButtonIcon, WidgetDynLabel}
|
||||
import net.bdew.lib.gui.{Color, Point}
|
||||
import net.bdew.lib.multiblock.data.{MsgOutputCfgPower, OutputConfigPower, RSMode}
|
||||
import net.bdew.lib.multiblock.interact.CIOutputFaces
|
||||
import net.bdew.lib.multiblock.network.NetHandler
|
||||
|
||||
class WidgetPowerOutput(te: CIOutputFaces, output: Int) extends WidgetOutputDisplay {
|
||||
def cfg = te.outputConfig(output).asInstanceOf[OutputConfigPower]
|
||||
val dec = new DecimalFormat("#,##0")
|
||||
val bt = add(new WidgetButtonIcon(Point(56, 1), clicked, te.resources.btBase, te.resources.btHover))
|
||||
add(new WidgetDynLabel("%s %s/t".format(dec.format(cfg.avg), cfg.unit), 1, 5, Color.darkgray))
|
||||
|
||||
val icons = Map(
|
||||
RSMode.ALWAYS -> te.resources.btEnabled,
|
||||
RSMode.NEVER -> te.resources.btDisabled,
|
||||
RSMode.RS_ON -> te.resources.btRsOn,
|
||||
RSMode.RS_OFF -> te.resources.btRsOff
|
||||
)
|
||||
|
||||
val next = Map(
|
||||
RSMode.ALWAYS -> RSMode.RS_ON,
|
||||
RSMode.RS_ON -> RSMode.RS_OFF,
|
||||
RSMode.RS_OFF -> RSMode.NEVER,
|
||||
RSMode.NEVER -> RSMode.ALWAYS
|
||||
)
|
||||
|
||||
override def draw(mouse: Point) {
|
||||
bt.icon = icons(cfg.rsMode)
|
||||
bt.hover = Misc.toLocal("bdlib.rsmode." + cfg.rsMode.toString.toLowerCase)
|
||||
super.draw(mouse)
|
||||
}
|
||||
|
||||
def clicked(b: WidgetButtonIcon) {
|
||||
NetHandler.sendToServer(MsgOutputCfgPower(output, next(cfg.rsMode)))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.interact
|
||||
|
||||
import net.bdew.lib.multiblock.tile.TileController
|
||||
import net.minecraftforge.fluids.{Fluid, FluidStack, FluidTankInfo}
|
||||
|
||||
trait CIFluidInput extends TileController {
|
||||
def inputFluid(resource: FluidStack, doFill: Boolean): Int
|
||||
def canInputFluid(fluid: Fluid): Boolean
|
||||
def getTankInfo: Array[FluidTankInfo]
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.interact
|
||||
|
||||
import net.bdew.lib.block.{BlockFace, BlockRef}
|
||||
import net.bdew.lib.multiblock.data._
|
||||
import net.bdew.lib.multiblock.tile.{TileController, TileModule}
|
||||
import net.minecraft.util.ChatComponentTranslation
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
trait CIOutputFaces extends TileController {
|
||||
val maxOutputs: Int
|
||||
|
||||
val outputFaces = new DataSlotBlockFaceMap("outputs", this)
|
||||
val outputConfig = new DataSlotOutputConfig("cfg", this, maxOutputs)
|
||||
|
||||
def newOutput(bp: BlockRef, face: ForgeDirection, cfg: OutputConfig): Int = {
|
||||
val bf = BlockFace(bp, face)
|
||||
if (outputFaces.contains(bf)) {
|
||||
println("Adding already registered output??? " + bf.toString)
|
||||
return outputFaces(bf)
|
||||
}
|
||||
val rv = outputFaces.inverted
|
||||
for (i <- 0 until maxOutputs if !rv.contains(i)) {
|
||||
outputFaces += (bf -> i)
|
||||
outputConfig += i -> cfg
|
||||
outputFaces.updated()
|
||||
return i
|
||||
}
|
||||
val pl = getWorldObj.getClosestPlayer(bf.x, bf.y, bf.z, 10)
|
||||
if (pl != null) pl.addChatMessage(new ChatComponentTranslation("bdlib.multiblock.toomanyoutputs"))
|
||||
return -1
|
||||
}
|
||||
|
||||
serverTick.listen(doOutputs)
|
||||
|
||||
override def moduleRemoved(module: TileModule) {
|
||||
for ((bf, n) <- outputFaces if bf.origin == module.mypos) {
|
||||
outputFaces -= bf
|
||||
outputConfig -= n
|
||||
}
|
||||
outputFaces.updated()
|
||||
outputConfig.updated()
|
||||
super.moduleRemoved(module)
|
||||
}
|
||||
|
||||
def doOutputs() {
|
||||
for ((x, n) <- outputFaces) {
|
||||
val t = x.origin.getTile[MIOutput](getWorldObj)
|
||||
if (t.isDefined) {
|
||||
if (!outputConfig.isDefinedAt(n) || outputConfig(n).isInstanceOf[OutputConfigInvalid])
|
||||
outputConfig(n) = t.get.makeCfgObject(x.face)
|
||||
t.get.doOutput(x.face, outputConfig(n))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def removeOutput(bp: BlockRef, face: ForgeDirection) {
|
||||
val bf = BlockFace(bp, face)
|
||||
outputConfig -= outputFaces(bf)
|
||||
outputFaces -= bf
|
||||
outputFaces.updated()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.interact
|
||||
|
||||
trait CIPowerProducer extends CIOutputFaces {
|
||||
def extract(v: Float, simulate: Boolean): Float
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.interact
|
||||
|
||||
import net.minecraft.inventory.Container
|
||||
|
||||
trait ContainerOutputFaces extends Container {
|
||||
def te: CIOutputFaces
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.interact
|
||||
|
||||
import net.bdew.lib.multiblock.data.OutputConfig
|
||||
import net.bdew.lib.multiblock.tile.TileModule
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
trait MIOutput extends TileModule {
|
||||
def doOutput(face: ForgeDirection, cfg: OutputConfig)
|
||||
def makeCfgObject(face: ForgeDirection): OutputConfig
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.network
|
||||
|
||||
import net.bdew.lib.network.Message
|
||||
|
||||
abstract class MsgOutputCfg extends Message {
|
||||
val output: Int
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.network
|
||||
|
||||
import net.bdew.lib.multiblock.interact.ContainerOutputFaces
|
||||
import net.bdew.lib.network.NetChannel
|
||||
import net.minecraft.entity.player.EntityPlayerMP
|
||||
|
||||
object NetHandler extends NetChannel("bdew.multiblock") {
|
||||
regServerHandler {
|
||||
case (msg: MsgOutputCfg, p: EntityPlayerMP) =>
|
||||
val te = p.openContainer.asInstanceOf[ContainerOutputFaces].te
|
||||
te.outputConfig(msg.output).handleConfigPacket(msg)
|
||||
te.outputConfig.updated()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.tile
|
||||
|
||||
import net.bdew.lib.BdLib
|
||||
import net.bdew.lib.block.BlockRef
|
||||
import net.bdew.lib.data.base.{TileDataSlots, UpdateKind}
|
||||
import net.bdew.lib.multiblock.block.BlockModule
|
||||
import net.bdew.lib.multiblock.data.DataSlotPosSet
|
||||
import net.bdew.lib.multiblock.{MachineCore, ResourceProvider, Tools}
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
|
||||
trait TileController extends TileDataSlots {
|
||||
val modules = new DataSlotPosSet("modules", this).setUpdate(UpdateKind.WORLD, UpdateKind.SAVE, UpdateKind.RENDER)
|
||||
|
||||
def resources: ResourceProvider
|
||||
def cfg: MachineCore
|
||||
|
||||
var acceptNewModules = true
|
||||
var revalidateOnNextTick = true
|
||||
var modulesChanged = true
|
||||
|
||||
lazy val mypos = BlockRef(xCoord, yCoord, zCoord)
|
||||
|
||||
def getNumOfMoudules(kind: String) = modules.map(_.getTile[TileModule](getWorldObj)).flatten.count(_.kind == kind)
|
||||
|
||||
def onModulesChanged()
|
||||
def onClick(player: EntityPlayer)
|
||||
|
||||
def moduleConnected(module: TileModule): Boolean = {
|
||||
if (acceptNewModules) {
|
||||
modules.add(BlockRef(module.xCoord, module.yCoord, module.zCoord))
|
||||
getWorldObj.markBlockForUpdate(xCoord, yCoord, zCoord)
|
||||
modulesChanged = true
|
||||
return true
|
||||
} else false
|
||||
}
|
||||
|
||||
def moduleRemoved(module: TileModule) {
|
||||
modules.remove(BlockRef(module.xCoord, module.yCoord, module.zCoord))
|
||||
getWorldObj.markBlockForUpdate(xCoord, yCoord, zCoord)
|
||||
revalidateOnNextTick = true
|
||||
modulesChanged = true
|
||||
}
|
||||
|
||||
def onBreak() {
|
||||
acceptNewModules = false
|
||||
for (x <- modules.flatMap(_.getTile[TileModule](getWorldObj)))
|
||||
x.coreRemoved()
|
||||
modules.clear()
|
||||
}
|
||||
|
||||
def validateModules() {
|
||||
modules.filter(x => {
|
||||
!x.getTile[TileModule](getWorldObj).isDefined || !x.getBlock[BlockModule[TileModule]](getWorldObj).isDefined
|
||||
}).foreach(x => {
|
||||
BdLib.logWarn("Block at %s is not a valid module, removing from machine %s at %d,%d,%d", x, this.getClass.getSimpleName, xCoord, yCoord, zCoord)
|
||||
modules.remove(x)
|
||||
})
|
||||
val reachable = Tools.findReachableModules(getWorldObj, mypos)
|
||||
val toremove = modules.filterNot(reachable.contains).flatMap(_.getTile[TileModule](getWorldObj))
|
||||
acceptNewModules = false
|
||||
toremove.foreach(moduleRemoved)
|
||||
toremove.foreach(_.coreRemoved())
|
||||
acceptNewModules = true
|
||||
modulesChanged = true
|
||||
modules.map(x =>
|
||||
(x.getBlock[BlockModule[TileModule]](getWorldObj).orNull, x.getTile[TileModule](getWorldObj).orNull)
|
||||
).filter({ case (a, b) => a.kind != b.kind }).foreach({ case (a, b) => sys.error("Type mismatch between Block/Tile Block=%s(%s) Tile=%s(%s)".format(a.kind, a, b.kind, b)) })
|
||||
}
|
||||
|
||||
serverTick.listen(() => {
|
||||
if (revalidateOnNextTick) {
|
||||
revalidateOnNextTick = false
|
||||
validateModules()
|
||||
}
|
||||
if (modulesChanged) {
|
||||
modulesChanged = false
|
||||
onModulesChanged()
|
||||
lastChange = getWorldObj.getTotalWorldTime
|
||||
getWorldObj.markBlockForUpdate(xCoord, yCoord, zCoord)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.tile
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.util.{ChatComponentTranslation, ChatStyle, EnumChatFormatting}
|
||||
|
||||
abstract class TileControllerGui extends TileController {
|
||||
def openGui(player: EntityPlayer)
|
||||
|
||||
def onClick(player: EntityPlayer) = {
|
||||
val missing = cfg.required.filter({ case (mod, cnt) => getNumOfMoudules(mod) < cnt })
|
||||
if (missing.size > 0) {
|
||||
player.addChatMessage(new ChatComponentTranslation("bdlib.multiblock.incomplete")
|
||||
.setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED)))
|
||||
for ((mod, cnt) <- missing)
|
||||
player.addChatMessage(
|
||||
new ChatComponentTranslation("- %s %s", Integer.valueOf(cnt),
|
||||
new ChatComponentTranslation(resources.getModuleName(mod)))
|
||||
.setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED)))
|
||||
} else openGui(player)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.tile
|
||||
|
||||
import net.bdew.lib.block.BlockRef
|
||||
import net.bdew.lib.data.base.{TileDataSlots, UpdateKind}
|
||||
import net.bdew.lib.multiblock.Tools
|
||||
import net.bdew.lib.multiblock.data.DataSlotPos
|
||||
|
||||
import scala.reflect.ClassTag
|
||||
|
||||
trait TileModule extends TileDataSlots {
|
||||
val kind: String
|
||||
val connected = new DataSlotPos("connected", this).setUpdate(UpdateKind.WORLD, UpdateKind.SAVE, UpdateKind.RENDER)
|
||||
|
||||
def getCoreAs[T: ClassTag] = connected flatMap (_.getTile[TileController with T](getWorldObj))
|
||||
def getCore = connected flatMap (_.getTile[TileController](getWorldObj))
|
||||
|
||||
lazy val mypos = BlockRef(xCoord, yCoord, zCoord)
|
||||
|
||||
def connect(target: TileController) {
|
||||
if (target.moduleConnected(this)) {
|
||||
connected.set(target.mypos)
|
||||
getWorldObj.markBlockForUpdate(xCoord, yCoord, zCoord)
|
||||
getWorldObj.notifyBlocksOfNeighborChange(xCoord, yCoord, zCoord, getBlockType)
|
||||
}
|
||||
}
|
||||
|
||||
def coreRemoved() {
|
||||
connected.unset()
|
||||
getWorldObj.markBlockForUpdate(xCoord, yCoord, zCoord)
|
||||
getWorldObj.notifyBlocksOfNeighborChange(xCoord, yCoord, zCoord, getBlockType)
|
||||
}
|
||||
|
||||
def onBreak() {
|
||||
getCore map (_.moduleRemoved(this))
|
||||
}
|
||||
|
||||
def tryConnect() {
|
||||
if (getCore.isEmpty) {
|
||||
for {
|
||||
conn <- Tools.findConnections(getWorldObj, mypos, kind).headOption
|
||||
core <- conn.getTile[TileController](getWorldObj)
|
||||
} {
|
||||
connect(core)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.multiblock.tile
|
||||
|
||||
import net.bdew.lib.multiblock.data.{OutputConfigPower, RSMode}
|
||||
import net.bdew.lib.multiblock.interact.{CIOutputFaces, MIOutput}
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
abstract class TileOutput extends TileModule with MIOutput {
|
||||
val unit: String
|
||||
|
||||
override def getCore = getCoreAs[CIOutputFaces]
|
||||
|
||||
def checkCanOutput(cfg: OutputConfigPower): Boolean = {
|
||||
if (cfg.rsMode == RSMode.ALWAYS) return true
|
||||
if (cfg.rsMode == RSMode.NEVER) return false
|
||||
return worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord) ^ (cfg.rsMode == RSMode.RS_OFF)
|
||||
}
|
||||
|
||||
def makeCfgObject(face: ForgeDirection) = {
|
||||
val cfg = new OutputConfigPower
|
||||
cfg.unit = unit
|
||||
cfg
|
||||
}
|
||||
|
||||
var rescanFaces = false
|
||||
|
||||
serverTick.listen(() => {
|
||||
if (rescanFaces) {
|
||||
rescanFaces = false
|
||||
doRescanFaces()
|
||||
}
|
||||
})
|
||||
|
||||
override def tryConnect() {
|
||||
super.tryConnect()
|
||||
if (connected.isDefined) rescanFaces = true
|
||||
}
|
||||
|
||||
def canConnectoToFace(d: ForgeDirection): Boolean
|
||||
|
||||
def onConnectionsChanged(added: Set[ForgeDirection], removed: Set[ForgeDirection]) {}
|
||||
|
||||
def doRescanFaces() {
|
||||
getCore map { core =>
|
||||
val connections = ForgeDirection.VALID_DIRECTIONS.filter(canConnectoToFace).toSet
|
||||
val known = core.outputFaces.filter(_._1.origin == mypos).map(_._1.face).toSet
|
||||
val toAdd = connections -- known
|
||||
val toRemove = known -- connections
|
||||
toRemove.foreach(x => core.removeOutput(mypos, x))
|
||||
toAdd.foreach(x => core.newOutput(mypos, x, makeCfgObject(x)))
|
||||
if (toAdd.size > 0 || toRemove.size > 0) {
|
||||
onConnectionsChanged(toAdd, toRemove)
|
||||
getWorldObj.markBlockForUpdate(xCoord, yCoord, zCoord)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,8 @@ case class ConfigSection(pfx: String = "") extends CfgEntry with Iterable[(Strin
|
||||
def iterator: Iterator[(String, CfgEntry)] = raw.iterator
|
||||
def filterType[T <: CfgEntry](cls: Class[T]): Iterable[(String, T)] = raw.filter(x => cls.isInstance(x._2)).map(x => x.asInstanceOf[(String, T)])
|
||||
|
||||
def keys = raw.keys
|
||||
|
||||
def rawget[T](id: String, t: Class[T]): T = {
|
||||
val v = raw(id)
|
||||
if (t.isInstance(v))
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.render.connected
|
||||
|
||||
import net.bdew.lib.gui.Color
|
||||
import net.minecraft.util.IIcon
|
||||
import net.minecraft.world.IBlockAccess
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
case class FaceOverlay(icon: IIcon, color: Color) {
|
||||
def this(icon: IIcon, color: (Float, Float, Float)) = this(icon, new Color(color._1, color._2, color._3))
|
||||
}
|
||||
|
||||
trait BlockAdditionalRender {
|
||||
def getFaceOverlays(world: IBlockAccess, x: Int, y: Int, z: Int, face: ForgeDirection): List[FaceOverlay]
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.render.connected
|
||||
|
||||
import net.bdew.lib.block.BlockRef
|
||||
import net.minecraft.client.renderer.Tessellator
|
||||
import net.minecraft.util.IIcon
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
object ConnectedHelper {
|
||||
val edgeWidth = 1 / 16F
|
||||
|
||||
// Represents the rectangles of all edges/corners on a 2d pane
|
||||
// 701
|
||||
// 6 2
|
||||
// 543
|
||||
// 8 is a special case for the full face
|
||||
val faceEdges = Array(
|
||||
RectF(0, 1 - edgeWidth, 1, 1),
|
||||
RectF(1 - edgeWidth, 1 - edgeWidth, 1, 1),
|
||||
RectF(1 - edgeWidth, 0, 1, 1),
|
||||
RectF(1 - edgeWidth, 0, 1, edgeWidth),
|
||||
RectF(0, 0, 1, edgeWidth),
|
||||
RectF(0, 0, edgeWidth, edgeWidth),
|
||||
RectF(0, 0, edgeWidth, 1),
|
||||
RectF(0, 1 - edgeWidth, edgeWidth, 1),
|
||||
RectF(0, 0, 1, 1)
|
||||
)
|
||||
|
||||
val faceAdjanced = (for (x <- ForgeDirection.VALID_DIRECTIONS) yield x -> new FaceAdjanced(x)).toMap
|
||||
|
||||
// Maps edge number + face to 3d vertices
|
||||
val draw =
|
||||
(for ((rect, n) <- faceEdges.zipWithIndex; face <- ForgeDirection.VALID_DIRECTIONS)
|
||||
yield (face, n) -> new EdgeDraw(rect, face)).toMap
|
||||
|
||||
val brightnessMultiplier = Map(
|
||||
ForgeDirection.UP -> 1F,
|
||||
ForgeDirection.DOWN -> 0.5F,
|
||||
ForgeDirection.NORTH -> 0.8F,
|
||||
ForgeDirection.SOUTH -> 0.8F,
|
||||
ForgeDirection.WEST -> 0.6F,
|
||||
ForgeDirection.EAST -> 0.6F
|
||||
)
|
||||
|
||||
case class Vec3F(x: Float, y: Float, z: Float) {
|
||||
def *(m: Float) = Vec3F(x * m, y * m, z * m)
|
||||
def +(m: Vec3F) = Vec3F(x + m.x, y + m.y, z + m.z)
|
||||
def -(m: Vec3F) = Vec3F(x - m.x, y - m.y, z - m.z)
|
||||
def +(d: ForgeDirection) = Vec3F(x + d.offsetX, y + d.offsetY, z + d.offsetZ)
|
||||
def toInts = (x.toInt, y.toInt, z.toInt)
|
||||
def asBlockRef = BlockRef(x.toInt, y.toInt, z.toInt)
|
||||
}
|
||||
|
||||
case class RectF(x1: Float, y1: Float, x2: Float, y2: Float) {
|
||||
def corners = Seq(Vec2F(x1, y1), Vec2F(x2, y1), Vec2F(x2, y2), Vec2F(x1, y2))
|
||||
}
|
||||
|
||||
case class Vec2F(u: Float, v: Float)
|
||||
|
||||
case class VecPair(pos: Vec3F, tex: Vec2F)
|
||||
|
||||
class EdgeDraw(rect: RectF, face: ForgeDirection) {
|
||||
val vertices = rect.corners map { d =>
|
||||
val v = face match {
|
||||
case ForgeDirection.UP => Vec3F(d.u, 1, 1 - d.v)
|
||||
case ForgeDirection.DOWN => Vec3F(d.u, 0, d.v)
|
||||
case ForgeDirection.NORTH => Vec3F(1 - d.u, d.v, 0)
|
||||
case ForgeDirection.SOUTH => Vec3F(d.u, d.v, 1)
|
||||
case ForgeDirection.EAST => Vec3F(1, d.v, 1 - d.u)
|
||||
case ForgeDirection.WEST => Vec3F(0, d.v, d.u)
|
||||
case _ => sys.error("Invalid face")
|
||||
}
|
||||
VecPair(extend(v, 0.001F), d)
|
||||
}
|
||||
|
||||
def doDraw(pos: Vec3F, icon: IIcon) {
|
||||
for (v <- vertices)
|
||||
addVertextWithUV(v.pos + pos, mapToIcon(v.tex, icon))
|
||||
}
|
||||
}
|
||||
|
||||
def extend(v: Vec3F, o: Float) = Vec3F(
|
||||
if (v.x == 0F) -o else if (v.x == 1F) 1 + o else v.x,
|
||||
if (v.y == 0F) -o else if (v.y == 1F) 1 + o else v.y,
|
||||
if (v.z == 0F) -o else if (v.z == 1F) 1 + o else v.z
|
||||
)
|
||||
|
||||
def mapToIcon(v: Vec2F, i: IIcon) = Vec2F(i.getInterpolatedU(v.u * 16), i.getInterpolatedV((1 - v.v) * 16))
|
||||
|
||||
def addVertextWithUV(p: Vec3F, t: Vec2F) =
|
||||
Tessellator.instance.addVertexWithUV(p.x, p.y, p.z, t.u, t.v)
|
||||
|
||||
class FaceAdjanced(d: ForgeDirection) {
|
||||
val top = d match {
|
||||
case ForgeDirection.UP => ForgeDirection.NORTH
|
||||
case ForgeDirection.DOWN => ForgeDirection.SOUTH
|
||||
case _ => ForgeDirection.UP
|
||||
}
|
||||
|
||||
val right = d match {
|
||||
case ForgeDirection.UP => ForgeDirection.EAST
|
||||
case ForgeDirection.DOWN => ForgeDirection.EAST
|
||||
case ForgeDirection.NORTH => ForgeDirection.WEST
|
||||
case ForgeDirection.WEST => ForgeDirection.SOUTH
|
||||
case ForgeDirection.SOUTH => ForgeDirection.EAST
|
||||
case ForgeDirection.EAST => ForgeDirection.NORTH
|
||||
case _ => ForgeDirection.UNKNOWN
|
||||
}
|
||||
val bottom = top.getOpposite
|
||||
val left = right.getOpposite
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.render.connected
|
||||
|
||||
import cpw.mods.fml.client.registry.{ISimpleBlockRenderingHandler, RenderingRegistry}
|
||||
import net.bdew.lib.block.BlockRef
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.client.renderer.{RenderBlocks, Tessellator}
|
||||
import net.minecraft.world.IBlockAccess
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
import org.lwjgl.opengl.GL11
|
||||
|
||||
object ConnectedRenderer extends ISimpleBlockRenderingHandler {
|
||||
val id = RenderingRegistry.getNextAvailableRenderId
|
||||
RenderingRegistry.registerBlockHandler(this)
|
||||
|
||||
def doRenderItemSide(d: ForgeDirection, r: RenderBlocks, block: Block, meta: Int) = {
|
||||
val icon = r.getBlockIconFromSideAndMetadata(block, d.ordinal(), meta)
|
||||
Tessellator.instance.setNormal(d.offsetX, d.offsetY, d.offsetZ)
|
||||
d match {
|
||||
case ForgeDirection.DOWN => r.renderFaceYNeg(block, 0.0D, 0.0D, 0.0D, icon)
|
||||
case ForgeDirection.UP => r.renderFaceYPos(block, 0.0D, 0.0D, 0.0D, icon)
|
||||
case ForgeDirection.NORTH => r.renderFaceZNeg(block, 0.0D, 0.0D, 0.0D, icon)
|
||||
case ForgeDirection.SOUTH => r.renderFaceZPos(block, 0.0D, 0.0D, 0.0D, icon)
|
||||
case ForgeDirection.WEST => r.renderFaceXNeg(block, 0.0D, 0.0D, 0.0D, icon)
|
||||
case ForgeDirection.EAST => r.renderFaceXPos(block, 0.0D, 0.0D, 0.0D, icon)
|
||||
case _ => sys.error("Invalid side")
|
||||
}
|
||||
}
|
||||
|
||||
override def renderInventoryBlock(block: Block, metadata: Int, modelID: Int, renderer: RenderBlocks) {
|
||||
val tessellator = Tessellator.instance
|
||||
GL11.glTranslatef(-0.5F, -0.5F, -0.5F)
|
||||
|
||||
val edge = block.asInstanceOf[ConnectedTextureBlock].edgeIcon
|
||||
|
||||
for (side <- ForgeDirection.VALID_DIRECTIONS) {
|
||||
tessellator.startDrawingQuads()
|
||||
doRenderItemSide(side, renderer, block, metadata)
|
||||
val m = ConnectedHelper.brightnessMultiplier(side)
|
||||
ConnectedHelper.draw(side, 8).doDraw(ConnectedHelper.Vec3F(0, 0, 0), edge)
|
||||
tessellator.draw()
|
||||
}
|
||||
|
||||
GL11.glTranslatef(0.5F, 0.5F, 0.5F)
|
||||
}
|
||||
|
||||
override def renderWorldBlock(world: IBlockAccess, x: Int, y: Int, z: Int, block: Block, modelId: Int, renderer: RenderBlocks): Boolean = {
|
||||
renderer.renderStandardBlock(block, x, y, z)
|
||||
|
||||
val pos = ConnectedHelper.Vec3F(x, y, z)
|
||||
for (face <- ForgeDirection.VALID_DIRECTIONS)
|
||||
if (block.shouldSideBeRendered(world, x + face.offsetX, y + face.offsetY, z + face.offsetZ, face.ordinal()))
|
||||
drawFaceEdges(world, pos, face, block.asInstanceOf[ConnectedTextureBlock])
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
def drawFaceEdges(world: IBlockAccess, pos: ConnectedHelper.Vec3F, face: ForgeDirection, block: ConnectedTextureBlock) {
|
||||
val edge = block.edgeIcon
|
||||
val canConnect = block.canConnect(world, pos.asBlockRef, _: BlockRef)
|
||||
val sides = ConnectedHelper.faceAdjanced(face)
|
||||
|
||||
val m = ConnectedHelper.brightnessMultiplier(face)
|
||||
Tessellator.instance.setColorOpaque_F(m, m, m)
|
||||
|
||||
val fo = pos + face
|
||||
val b = block.getMixedBrightnessForBlock(world, fo.x.toInt, fo.y.toInt, fo.z.toInt)
|
||||
Tessellator.instance.setBrightness(b)
|
||||
|
||||
val U = !canConnect((pos + sides.top).asBlockRef)
|
||||
val D = !canConnect((pos + sides.bottom).asBlockRef)
|
||||
val L = !canConnect((pos + sides.left).asBlockRef)
|
||||
val R = !canConnect((pos + sides.right).asBlockRef)
|
||||
|
||||
if (!U && !R && !canConnect((pos + sides.top + sides.right).asBlockRef))
|
||||
ConnectedHelper.draw(face, 1).doDraw(pos, edge)
|
||||
|
||||
if (!U && !L && !canConnect((pos + sides.top + sides.left).asBlockRef))
|
||||
ConnectedHelper.draw(face, 7).doDraw(pos, edge)
|
||||
|
||||
if (!D && !R && !canConnect((pos + sides.bottom + sides.right).asBlockRef))
|
||||
ConnectedHelper.draw(face, 3).doDraw(pos, edge)
|
||||
|
||||
if (!D && !L && !canConnect((pos + sides.bottom + sides.left).asBlockRef))
|
||||
ConnectedHelper.draw(face, 5).doDraw(pos, edge)
|
||||
|
||||
if (U) ConnectedHelper.draw(face, 0).doDraw(pos, edge)
|
||||
if (D) ConnectedHelper.draw(face, 4).doDraw(pos, edge)
|
||||
if (R) ConnectedHelper.draw(face, 2).doDraw(pos, edge)
|
||||
if (L) ConnectedHelper.draw(face, 6).doDraw(pos, edge)
|
||||
|
||||
if (block.isInstanceOf[BlockAdditionalRender]) {
|
||||
val overlays = block.asInstanceOf[BlockAdditionalRender].getFaceOverlays(world, pos.x.toInt, pos.y.toInt, pos.z.toInt, face)
|
||||
for (overlay <- overlays) {
|
||||
Tessellator.instance.setColorOpaque_F(overlay.color.r, overlay.color.g, overlay.color.b)
|
||||
ConnectedHelper.draw(face, 8).doDraw(pos, overlay.icon)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def shouldRender3DInInventory(modelId: Int) = true
|
||||
override def getRenderId = id
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) bdew, 2013 - 2014
|
||||
* https://github.com/bdew/bdlib
|
||||
*
|
||||
* This mod is distributed under the terms of the Minecraft Mod Public
|
||||
* License 1.0, or MMPL. Please check the contents of the license located in
|
||||
* https://raw.github.com/bdew/bdlib/master/MMPL-1.0.txt
|
||||
*/
|
||||
|
||||
package net.bdew.lib.render.connected
|
||||
|
||||
import net.bdew.lib.block.BlockRef
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.util.IIcon
|
||||
import net.minecraft.world.IBlockAccess
|
||||
|
||||
trait ConnectedTextureBlock extends Block {
|
||||
def edgeIcon: IIcon
|
||||
def canConnect(world: IBlockAccess, origin: BlockRef, target: BlockRef): Boolean
|
||||
|
||||
override def getRenderType = ConnectedRenderer.id
|
||||
}
|
||||
Reference in new issue
Block a user