mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-15 10:21:45 -04:00
Merge branch 'master-MC1.7.10' of github.com:MightyPirates/OpenComputers into master-MC1.8
Conflicts: src/main/scala/li/cil/oc/common/item/Tablet.scala src/main/scala/li/cil/oc/common/tileentity/traits/Rotatable.scala src/main/scala/li/cil/oc/integration/Mods.scala src/main/scala/li/cil/oc/server/component/UpgradePiston.scala src/main/scala/li/cil/oc/util/ExtendedArguments.scala
This commit is contained in:
commit
929d9f58fe
@ -1,7 +1,7 @@
|
||||
minecraft.version=1.8
|
||||
forge.version=11.14.3.1450
|
||||
|
||||
oc.version=1.5.15
|
||||
oc.version=1.5.16
|
||||
oc.subversion=dev
|
||||
|
||||
ae2.version=rv2-beta-26
|
||||
|
@ -126,10 +126,10 @@ opencomputers {
|
||||
# happen.
|
||||
startupDelay: 0.25
|
||||
|
||||
# The maximum size of the byte array that can be stored on EEPROMs.
|
||||
# The maximum size of the byte array that can be stored on EEPROMs as executable data..
|
||||
eepromSize: 4096
|
||||
|
||||
# The maximum size of the byte array that can be stored on EEPROMs.
|
||||
# The maximum size of the byte array that can be stored on EEPROMs as configuration data.
|
||||
eepromDataSize: 256
|
||||
|
||||
# The number of components the different CPU tiers support. This list
|
||||
|
@ -241,9 +241,11 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp
|
||||
|
||||
override def facing = RotationHelper.fromYaw(player.rotationYaw)
|
||||
|
||||
override def toLocal(value: EnumFacing) = value // -T-O-D-O- do we care? no we don't
|
||||
override def toLocal(value: EnumFacing) =
|
||||
RotationHelper.toLocal(EnumFacing.NORTH, facing, value)
|
||||
|
||||
override def toGlobal(value: EnumFacing) = value // -T-O-D-O- do we care? no we don't
|
||||
override def toGlobal(value: EnumFacing) =
|
||||
RotationHelper.toGlobal(EnumFacing.NORTH, facing, value)
|
||||
|
||||
def readFromNBT() {
|
||||
if (stack.hasTagCompound) {
|
||||
|
@ -5,6 +5,7 @@ import li.cil.oc.common.block
|
||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||
import li.cil.oc.util.ExtendedEnumFacing._
|
||||
import li.cil.oc.util.ExtendedWorld._
|
||||
import li.cil.oc.util.RotationHelper
|
||||
import net.minecraft.block.state.IBlockState
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.util.EnumFacing
|
||||
@ -15,69 +16,9 @@ trait Rotatable extends RotationAware with internal.Rotatable {
|
||||
// Lookup tables
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
/**
|
||||
* Translates forge directions based on the block's pitch and yaw. The base
|
||||
* forward direction is facing south with no pitch. The outer array is for
|
||||
* the three different pitch states, the inner for the four different yaw
|
||||
* states.
|
||||
*/
|
||||
private val translations = Array(
|
||||
// Pitch = Down
|
||||
Array(
|
||||
// Yaw = North
|
||||
Array(D.south, D.north, D.up, D.down, D.east, D.west),
|
||||
// Yaw = South
|
||||
Array(D.south, D.north, D.down, D.up, D.west, D.east),
|
||||
// Yaw = West
|
||||
Array(D.south, D.north, D.west, D.east, D.up, D.down),
|
||||
// Yaw = East
|
||||
Array(D.south, D.north, D.east, D.west, D.down, D.up)),
|
||||
// Pitch = Up
|
||||
Array(
|
||||
// Yaw = North
|
||||
Array(D.north, D.south, D.down, D.up, D.east, D.west),
|
||||
// Yaw = South
|
||||
Array(D.north, D.south, D.up, D.down, D.west, D.east),
|
||||
// Yaw = West
|
||||
Array(D.north, D.south, D.west, D.east, D.down, D.up),
|
||||
// Yaw = East
|
||||
Array(D.north, D.south, D.east, D.west, D.up, D.down)),
|
||||
// Pitch = Forward (North|East|South|West)
|
||||
Array(
|
||||
// Yaw = North
|
||||
Array(D.down, D.up, D.south, D.north, D.east, D.west),
|
||||
// Yaw = South
|
||||
Array(D.down, D.up, D.north, D.south, D.west, D.east),
|
||||
// Yaw = West
|
||||
Array(D.down, D.up, D.west, D.east, D.south, D.north),
|
||||
// Yaw = East
|
||||
Array(D.down, D.up, D.east, D.west, D.north, D.south)))
|
||||
private val pitch2Direction = Array(EnumFacing.UP, EnumFacing.NORTH, EnumFacing.DOWN)
|
||||
|
||||
private val pitch2Direction = Array(D.up, D.north, D.down)
|
||||
|
||||
private val yaw2Direction = Array(D.south, D.west, D.north, D.east)
|
||||
|
||||
/** Shortcuts for forge directions to make the above more readable. */
|
||||
private object D {
|
||||
val down = EnumFacing.DOWN
|
||||
val up = EnumFacing.UP
|
||||
val north = EnumFacing.NORTH
|
||||
val south = EnumFacing.SOUTH
|
||||
val west = EnumFacing.WEST
|
||||
val east = EnumFacing.EAST
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
// State
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
/** Translation for facings based on current pitch and yaw. */
|
||||
private var cachedTranslation: Array[EnumFacing] = null
|
||||
|
||||
/** Translation from local to global coordinates. */
|
||||
private var cachedInverseTranslation: Array[EnumFacing] = null
|
||||
|
||||
protected var cacheDirty = true
|
||||
private val yaw2Direction = Array(EnumFacing.SOUTH, EnumFacing.WEST, EnumFacing.NORTH, EnumFacing.EAST)
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
// Accessors
|
||||
@ -148,17 +89,9 @@ trait Rotatable extends RotationAware with internal.Rotatable {
|
||||
else false
|
||||
}
|
||||
|
||||
override def toLocal(value: EnumFacing) = if (value != null) this.synchronized {
|
||||
updateTranslation()
|
||||
cachedTranslation(value.ordinal)
|
||||
}
|
||||
else null
|
||||
override def toLocal(value: EnumFacing) = if (value == null) null else RotationHelper.toLocal(pitch, yaw, value)
|
||||
|
||||
override def toGlobal(value: EnumFacing) = if (value != null) this.synchronized {
|
||||
updateTranslation()
|
||||
cachedInverseTranslation(value.ordinal)
|
||||
}
|
||||
else null
|
||||
override def toGlobal(value: EnumFacing) = if (value == null) null else RotationHelper.toGlobal(pitch, yaw, value)
|
||||
|
||||
def validFacings = Array(EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.WEST, EnumFacing.EAST)
|
||||
|
||||
@ -177,16 +110,9 @@ trait Rotatable extends RotationAware with internal.Rotatable {
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
/** Updates cached translation array and sends notification to clients. */
|
||||
protected def updateTranslation(): Unit = if (cacheDirty) {
|
||||
cacheDirty = false
|
||||
|
||||
val newTranslation = translations(pitch.ordinal)(yaw.ordinal - 2)
|
||||
if (cachedTranslation != newTranslation) {
|
||||
cachedTranslation = newTranslation
|
||||
cachedInverseTranslation = invert(cachedTranslation)
|
||||
if (world != null) {
|
||||
onRotationChanged()
|
||||
}
|
||||
protected def updateTranslation(): Unit = {
|
||||
if (world != null) {
|
||||
onRotationChanged()
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +122,6 @@ trait Rotatable extends RotationAware with internal.Rotatable {
|
||||
def setState(newState: IBlockState): Boolean = {
|
||||
if (oldState.hashCode() != newState.hashCode()) {
|
||||
world.setBlockState(getPos, newState)
|
||||
cacheDirty = true
|
||||
true
|
||||
}
|
||||
else false
|
||||
@ -209,7 +134,4 @@ trait Rotatable extends RotationAware with internal.Rotatable {
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
|
||||
private def invert(t: Array[EnumFacing]) =
|
||||
t.indices.map(i => EnumFacing.getFront(t.indexOf(EnumFacing.getFront(i)))).toArray
|
||||
}
|
||||
|
@ -86,7 +86,6 @@ trait RotatableTile extends Rotatable {
|
||||
_yaw = yaw
|
||||
}
|
||||
if (changed) {
|
||||
cacheDirty = true
|
||||
updateTranslation()
|
||||
}
|
||||
changed
|
||||
|
@ -21,6 +21,7 @@ object Mods {
|
||||
|
||||
val AppliedEnergistics2 = new SimpleMod(IDs.AppliedEnergistics2, version = "@[rv1,)", providesPower = true)
|
||||
val BattleGear2 = new SimpleMod(IDs.BattleGear2)
|
||||
val BetterRecords = new SimpleMod(IDs.BetterRecords)
|
||||
val BloodMagic = new SimpleMod(IDs.BloodMagic)
|
||||
val BluePower = new SimpleMod(IDs.BluePower, version = "@[0.2.928,)")
|
||||
val BuildCraft = new SimpleMod(IDs.BuildCraft)
|
||||
@ -39,7 +40,7 @@ object Mods {
|
||||
val ElectricalAge = new SimpleMod(IDs.ElectricalAge, providesPower = true)
|
||||
val EnderIO = new SimpleMod(IDs.EnderIO)
|
||||
val EnderStorage = new SimpleMod(IDs.EnderStorage)
|
||||
val ExtraCells = new SimpleMod(IDs.ExtraCells, version = "@[2.2.73,)")
|
||||
val ExtraCells = new SimpleMod(IDs.ExtraCells, version = "@[2.2.73,)")
|
||||
val Factorization = new SimpleMod(IDs.Factorization, providesPower = true)
|
||||
val Forestry = new SimpleMod(IDs.Forestry)
|
||||
val ForgeMultipart = new SimpleMod(IDs.ForgeMultipart)
|
||||
@ -85,6 +86,7 @@ object Mods {
|
||||
|
||||
val Proxies = Array(
|
||||
// integration.appeng.ModAppEng,
|
||||
// integration.betterrecords.ModBetterRecords,
|
||||
// integration.bloodmagic.ModBloodMagic,
|
||||
// integration.bluepower.ModBluePower,
|
||||
// integration.buildcraft.library.ModBuildCraftAPILibrary,
|
||||
@ -157,6 +159,7 @@ object Mods {
|
||||
object IDs {
|
||||
final val AppliedEnergistics2 = "appliedenergistics2"
|
||||
final val BattleGear2 = "battlegear2"
|
||||
final val BetterRecords = "betterrecords"
|
||||
final val BloodMagic = "AWWayofTime"
|
||||
final val BluePower = "bluepowerAPI"
|
||||
final val BuildCraft = "BuildCraft|Core"
|
||||
|
@ -0,0 +1,40 @@
|
||||
package li.cil.oc.integration.betterrecords
|
||||
|
||||
import java.util
|
||||
|
||||
import li.cil.oc.api.driver.Converter
|
||||
import li.cil.oc.util.ExtendedNBT._
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraftforge.common.util.Constants.NBT
|
||||
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
|
||||
object ConverterRecord extends Converter {
|
||||
final val UrlRecordClassName = "com.codingforcookies.betterrecords.src.items.ItemURLRecord"
|
||||
final val UrlMultiRecordClassName = "com.codingforcookies.betterrecords.src.items.ItemURLMultiRecord"
|
||||
final val FreqCrystalClassName = "com.codingforcookies.betterrecords.src.items.ItemFreqCrystal"
|
||||
|
||||
override def convert(value: scala.Any, output: util.Map[AnyRef, AnyRef]): Unit = value match {
|
||||
case stack: ItemStack if stack.getItem != null && stack.getItem.getClass.getName == UrlRecordClassName && stack.hasTagCompound =>
|
||||
convertRecord(stack.getTagCompound, output)
|
||||
case stack: ItemStack if stack.getItem != null && stack.getItem.getClass.getName == UrlMultiRecordClassName && stack.hasTagCompound =>
|
||||
output += "songs" -> stack.getTagCompound.getTagList("songs", NBT.TAG_COMPOUND).map((nbt: NBTTagCompound) => convertRecord(nbt, new util.HashMap[AnyRef, AnyRef]()))
|
||||
case stack: ItemStack if stack.getItem != null && stack.getItem.getClass.getName == FreqCrystalClassName && stack.hasTagCompound =>
|
||||
convertRecord(stack.getTagCompound, output)
|
||||
case _ =>
|
||||
}
|
||||
|
||||
private def convertRecord(nbt: NBTTagCompound, output: util.Map[AnyRef, AnyRef]) = {
|
||||
if (nbt.hasKey("url", NBT.TAG_STRING))
|
||||
output += "url" -> nbt.getString("url")
|
||||
if (nbt.hasKey("name", NBT.TAG_STRING))
|
||||
output += "filename" -> nbt.getString("name")
|
||||
if (nbt.hasKey("author", NBT.TAG_STRING))
|
||||
output += "author" -> nbt.getString("author")
|
||||
if (nbt.hasKey("local", NBT.TAG_STRING))
|
||||
output += "title" -> nbt.getString("local")
|
||||
|
||||
output
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package li.cil.oc.integration.betterrecords
|
||||
|
||||
import li.cil.oc.api.Driver
|
||||
import li.cil.oc.integration.ModProxy
|
||||
import li.cil.oc.integration.Mods
|
||||
|
||||
object ModBetterRecords extends ModProxy {
|
||||
override def getMod = Mods.BetterRecords
|
||||
|
||||
override def initialize() {
|
||||
Driver.add(ConverterRecord)
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import li.cil.oc.api
|
||||
import li.cil.oc.api.driver.EnvironmentAware
|
||||
import li.cil.oc.api.driver.EnvironmentHost
|
||||
import li.cil.oc.api.driver.item.HostAware
|
||||
import li.cil.oc.api.internal.Rotatable
|
||||
import li.cil.oc.api.internal
|
||||
import li.cil.oc.common.Slot
|
||||
import li.cil.oc.server.component
|
||||
import net.minecraft.item.ItemStack
|
||||
@ -15,7 +15,9 @@ object DriverUpgradePiston extends Item with HostAware with EnvironmentAware {
|
||||
api.Items.get(Constants.ItemName.PistonUpgrade))
|
||||
|
||||
override def createEnvironment(stack: ItemStack, host: EnvironmentHost) = host match {
|
||||
case rotatable: Rotatable with EnvironmentHost => new component.UpgradePiston(rotatable)
|
||||
case host: internal.Drone => new component.UpgradePiston.Drone(host)
|
||||
case host: internal.Tablet => new component.UpgradePiston.Tablet(host)
|
||||
case host: internal.Rotatable with EnvironmentHost => new component.UpgradePiston.Rotatable(host)
|
||||
case _ => null
|
||||
}
|
||||
|
||||
|
@ -55,22 +55,26 @@ abstract class GraphicsCard extends prefab.ManagedEnvironment {
|
||||
}
|
||||
}
|
||||
|
||||
@Callback(doc = """function(address:string):boolean -- Binds the GPU to the screen with the specified address.""")
|
||||
@Callback(doc = """function(address:string[, reset:boolean=true]):boolean -- Binds the GPU to the screen with the specified address and resets screen settings if `reset` is true.""")
|
||||
def bind(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val address = args.checkString(0)
|
||||
val reset = args.optBoolean(1, true)
|
||||
node.network.node(address) match {
|
||||
case null => result(Unit, "invalid address")
|
||||
case node: Node if node.host.isInstanceOf[TextBuffer] =>
|
||||
screenAddress = Option(address)
|
||||
screenInstance = Some(node.host.asInstanceOf[TextBuffer])
|
||||
screen(s => {
|
||||
val (gmw, gmh) = maxResolution
|
||||
val smw = s.getMaximumWidth
|
||||
val smh = s.getMaximumHeight
|
||||
s.setResolution(math.min(gmw, smw), math.min(gmh, smh))
|
||||
s.setColorDepth(ColorDepth.values.apply(math.min(maxDepth.ordinal, s.getMaximumColorDepth.ordinal)))
|
||||
s.setForegroundColor(0xFFFFFF)
|
||||
s.setBackgroundColor(0x000000)
|
||||
if (reset) {
|
||||
val (gmw, gmh) = maxResolution
|
||||
val smw = s.getMaximumWidth
|
||||
val smh = s.getMaximumHeight
|
||||
s.setResolution(math.min(gmw, smw), math.min(gmh, smh))
|
||||
s.setColorDepth(ColorDepth.values.apply(math.min(maxDepth.ordinal, s.getMaximumColorDepth.ordinal)))
|
||||
s.setForegroundColor(0xFFFFFF)
|
||||
s.setBackgroundColor(0x000000)
|
||||
}
|
||||
else context.pause(0.2) // To discourage outputting "in realtime" to multiple screens using one GPU.
|
||||
result(true)
|
||||
})
|
||||
case _ => result(Unit, "not a screen")
|
||||
|
@ -3,27 +3,34 @@ package li.cil.oc.server.component
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api.Network
|
||||
import li.cil.oc.api.driver.EnvironmentHost
|
||||
import li.cil.oc.api.internal.Rotatable
|
||||
import li.cil.oc.api.internal
|
||||
import li.cil.oc.api.machine.Arguments
|
||||
import li.cil.oc.api.machine.Callback
|
||||
import li.cil.oc.api.machine.Context
|
||||
import li.cil.oc.api.network.Visibility
|
||||
import li.cil.oc.api.prefab
|
||||
import li.cil.oc.util.BlockPosition
|
||||
import li.cil.oc.util.ExtendedArguments._
|
||||
import li.cil.oc.util.ExtendedWorld._
|
||||
import net.minecraft.init.Blocks
|
||||
import net.minecraft.util.EnumFacing
|
||||
|
||||
class UpgradePiston(val host: Rotatable with EnvironmentHost) extends prefab.ManagedEnvironment {
|
||||
abstract class UpgradePiston(val host: EnvironmentHost) extends prefab.ManagedEnvironment {
|
||||
override val node = Network.newNode(this, Visibility.Network).
|
||||
withComponent("piston").
|
||||
withConnector().
|
||||
create()
|
||||
|
||||
@Callback(doc = """function():boolean -- Tries to push the block in front of the container of the upgrade.""")
|
||||
def pushDirection(args: Arguments, index: Int): EnumFacing
|
||||
|
||||
def pushOrigin(side: EnumFacing) = BlockPosition(host)
|
||||
|
||||
@Callback(doc = """function([side:number]):boolean -- Tries to push the block on the specified side of the container of the upgrade. Defaults to front.""")
|
||||
def push(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val hostPos = BlockPosition(host)
|
||||
val blockPos = hostPos.offset(host.facing)
|
||||
if (!host.world.isAirBlock(blockPos) && node.tryChangeBuffer(-Settings.get.pistonCost) && Blocks.piston.doMove(host.world, hostPos.toBlockPos, host.facing, true)) {
|
||||
val side = pushDirection(args, 0)
|
||||
val hostPos = pushOrigin(side)
|
||||
val blockPos = hostPos.offset(side)
|
||||
if (!host.world.isAirBlock(blockPos) && node.tryChangeBuffer(-Settings.get.pistonCost) && Blocks.piston.doMove(host.world, hostPos.toBlockPos, side, true)) {
|
||||
host.world.setBlockToAir(blockPos)
|
||||
host.world.playSoundEffect(host.xPosition, host.yPosition, host.zPosition, "tile.piston.out", 0.5f, host.world.rand.nextFloat() * 0.25f + 0.6f)
|
||||
context.pause(0.5)
|
||||
@ -32,3 +39,21 @@ class UpgradePiston(val host: Rotatable with EnvironmentHost) extends prefab.Man
|
||||
else result(false)
|
||||
}
|
||||
}
|
||||
|
||||
object UpgradePiston {
|
||||
|
||||
class Drone(drone: internal.Drone) extends UpgradePiston(drone) {
|
||||
override def pushDirection(args: Arguments, index: Int) = args.optSide(index, EnumFacing.SOUTH, EnumFacing.values: _*)
|
||||
}
|
||||
|
||||
class Tablet(tablet: internal.Tablet) extends Rotatable(tablet) {
|
||||
override def pushOrigin(side: EnumFacing) =
|
||||
if (side == EnumFacing.DOWN && tablet.player.getEyeHeight > 1) super.pushOrigin(side).offset(EnumFacing.DOWN)
|
||||
else super.pushOrigin(side)
|
||||
}
|
||||
|
||||
class Rotatable(val rotatable: internal.Rotatable with EnvironmentHost) extends UpgradePiston(rotatable) {
|
||||
override def pushDirection(args: Arguments, index: Int) = rotatable.toGlobal(args.optSideForAction(index, EnumFacing.SOUTH))
|
||||
}
|
||||
|
||||
}
|
@ -50,7 +50,7 @@ trait InventoryControl extends InventoryAware {
|
||||
@Callback(doc = "function(toSlot:number[, amount:number]):boolean -- Move up to the specified amount of items from the selected slot into the specified slot.")
|
||||
def transferTo(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val slot = args.checkSlot(inventory, 0)
|
||||
val count = args.optionalItemCount(1)
|
||||
val count = args.optItemCount(1)
|
||||
if (slot == selectedSlot || count == 0) {
|
||||
result(true)
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ trait InventoryWorldControl extends InventoryAware with WorldAware with SideRest
|
||||
@Callback(doc = "function(side:number[, count:number=64]):boolean -- Drops items from the selected slot towards the specified side.")
|
||||
def drop(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val facing = checkSideForAction(args, 0)
|
||||
val count = args.optionalItemCount(1)
|
||||
val count = args.optItemCount(1)
|
||||
val stack = inventory.getStackInSlot(selectedSlot)
|
||||
if (stack != null && stack.stackSize > 0) {
|
||||
val blockPos = position.offset(facing)
|
||||
@ -69,7 +69,7 @@ trait InventoryWorldControl extends InventoryAware with WorldAware with SideRest
|
||||
@Callback(doc = "function(side:number[, count:number=64]):boolean -- Suck up items from the specified side.")
|
||||
def suck(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val facing = checkSideForAction(args, 0)
|
||||
val count = args.optionalItemCount(1)
|
||||
val count = args.optItemCount(1)
|
||||
|
||||
val blockPos = position.offset(facing)
|
||||
if (InventoryUtils.inventoryAt(blockPos).exists(inventory => {
|
||||
|
@ -14,7 +14,7 @@ trait InventoryWorldControlMk2 extends InventoryAware with WorldAware with SideR
|
||||
@Callback(doc = """function(facing:number, slot:number[, count:number]):boolean -- Drops the selected item stack into the specified slot of an inventory.""")
|
||||
def dropIntoSlot(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val facing = checkSideForAction(args, 0)
|
||||
val count = args.optionalItemCount(2)
|
||||
val count = args.optItemCount(2)
|
||||
val stack = inventory.getStackInSlot(selectedSlot)
|
||||
if (stack != null && stack.stackSize > 0) {
|
||||
withInventory(facing, inventory => {
|
||||
@ -43,7 +43,7 @@ trait InventoryWorldControlMk2 extends InventoryAware with WorldAware with SideR
|
||||
@Callback(doc = """function(facing:number, slot:number[, count:number]):boolean -- Sucks items from the specified slot of an inventory.""")
|
||||
def suckFromSlot(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val facing = checkSideForAction(args, 0)
|
||||
val count = args.optionalItemCount(2)
|
||||
val count = args.optItemCount(2)
|
||||
withInventory(facing, inventory => {
|
||||
val slot = args.checkSlot(inventory, 1)
|
||||
if (InventoryUtils.extractFromInventorySlot(InventoryUtils.insertIntoInventory(_, this.inventory, slots = Option(insertionSlots)), inventory, facing.getOpposite, slot, count)) {
|
||||
|
@ -53,7 +53,7 @@ trait TankControl extends TankAware {
|
||||
@Callback(doc = "function(index:number[, count:number=1000]):boolean -- Move the specified amount of fluid from the selected tank into the specified tank.")
|
||||
def transferFluidTo(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val index = args.checkTank(tank, 0)
|
||||
val count = args.optionalFluidCount(1)
|
||||
val count = args.optFluidCount(1)
|
||||
if (index == selectedTank || count == 0) {
|
||||
result(true)
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ trait TankInventoryControl extends WorldAware with InventoryAware with TankAware
|
||||
|
||||
@Callback(doc = """function([amount:number]):boolean -- Transfers fluid from a tank in the selected inventory slot to the selected tank.""")
|
||||
def drain(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val amount = args.optionalFluidCount(0)
|
||||
val amount = args.optFluidCount(0)
|
||||
Option(tank.getFluidTank(selectedTank)) match {
|
||||
case Some(into) => inventory.getStackInSlot(selectedSlot) match {
|
||||
case stack: ItemStack =>
|
||||
@ -77,7 +77,7 @@ trait TankInventoryControl extends WorldAware with InventoryAware with TankAware
|
||||
|
||||
@Callback(doc = """function([amount:number]):boolean -- Transfers fluid from the selected tank to a tank in the selected inventory slot.""")
|
||||
def fill(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val amount = args.optionalFluidCount(0)
|
||||
val amount = args.optFluidCount(0)
|
||||
Option(tank.getFluidTank(selectedTank)) match {
|
||||
case Some(from) => inventory.getStackInSlot(selectedSlot) match {
|
||||
case stack: ItemStack =>
|
||||
|
@ -36,7 +36,7 @@ trait TankWorldControl extends TankAware with WorldAware with SideRestricted {
|
||||
@Callback(doc = "function(side:boolean[, amount:number=1000]):boolean, number or string -- Drains the specified amount of fluid from the specified side. Returns the amount drained, or an error message.")
|
||||
def drain(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val facing = checkSideForAction(args, 0)
|
||||
val count = args.optionalFluidCount(1)
|
||||
val count = args.optFluidCount(1)
|
||||
getTank(selectedTank) match {
|
||||
case Some(tank) =>
|
||||
val space = tank.getCapacity - tank.getFluidAmount
|
||||
@ -97,7 +97,7 @@ trait TankWorldControl extends TankAware with WorldAware with SideRestricted {
|
||||
@Callback(doc = "function(side:number[, amount:number=1000]):boolean, number of string -- Eject the specified amount of fluid to the specified side. Returns the amount ejected or an error message.")
|
||||
def fill(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
val facing = checkSideForAction(args, 0)
|
||||
val count = args.optionalFluidCount(1)
|
||||
val count = args.optFluidCount(1)
|
||||
getTank(selectedTank) match {
|
||||
case Some(tank) =>
|
||||
val amount = math.min(count, tank.getFluidAmount)
|
||||
|
@ -12,17 +12,13 @@ object ExtendedArguments {
|
||||
implicit def extendedArguments(args: Arguments): ExtendedArguments = new ExtendedArguments(args)
|
||||
|
||||
class ExtendedArguments(val args: Arguments) {
|
||||
def optionalItemCount(n: Int) =
|
||||
if (args.count > n && args.checkAny(n) != null) {
|
||||
math.max(0, math.min(64, args.checkInteger(n)))
|
||||
}
|
||||
else 64
|
||||
def optItemCount(index: Int, default: Int = 64) =
|
||||
if (!isDefined(index) || !hasValue(index)) default
|
||||
else math.max(0, math.min(64, args.checkInteger(index)))
|
||||
|
||||
def optionalFluidCount(n: Int) =
|
||||
if (args.count > n && args.checkAny(n) != null) {
|
||||
math.max(0, args.checkInteger(n))
|
||||
}
|
||||
else 1000
|
||||
def optFluidCount(index: Int, default: Int = 1000) =
|
||||
if (!isDefined(index) || !hasValue(index)) default
|
||||
else math.max(0, args.checkInteger(index))
|
||||
|
||||
def checkSlot(inventory: IInventory, n: Int) = {
|
||||
val slot = args.checkInteger(n) - 1
|
||||
@ -32,9 +28,9 @@ object ExtendedArguments {
|
||||
slot
|
||||
}
|
||||
|
||||
def optSlot(inventory: IInventory, n: Int, default: Int) = {
|
||||
if (n >= 0 && n < args.count()) checkSlot(inventory, n)
|
||||
else default
|
||||
def optSlot(inventory: IInventory, index: Int, default: Int) = {
|
||||
if (!isDefined(index)) default
|
||||
else checkSlot(inventory, index)
|
||||
}
|
||||
|
||||
def checkTank(multi: MultiTank, n: Int) = {
|
||||
@ -45,14 +41,26 @@ object ExtendedArguments {
|
||||
tank
|
||||
}
|
||||
|
||||
def checkSideForAction(n: Int) = checkSide(n, EnumFacing.SOUTH, EnumFacing.UP, EnumFacing.DOWN)
|
||||
def checkSideForAction(index: Int) = checkSide(index, EnumFacing.SOUTH, EnumFacing.UP, EnumFacing.DOWN)
|
||||
|
||||
def checkSideForMovement(n: Int) = checkSide(n, EnumFacing.SOUTH, EnumFacing.NORTH, EnumFacing.UP, EnumFacing.DOWN)
|
||||
def optSideForAction(index: Int, default: EnumFacing) =
|
||||
if (!isDefined(index)) default
|
||||
else checkSideForAction(index)
|
||||
|
||||
def checkSideForFace(n: Int, facing: EnumFacing) = checkSide(n, EnumFacing.values.filter(_ != facing.getOpposite): _*)
|
||||
def checkSideForMovement(index: Int) = checkSide(index, EnumFacing.SOUTH, EnumFacing.NORTH, EnumFacing.UP, EnumFacing.DOWN)
|
||||
|
||||
def checkSide(n: Int, allowed: EnumFacing*) = {
|
||||
val side = args.checkInteger(n)
|
||||
def optSideForMovement(index: Int, default: EnumFacing) =
|
||||
if (!isDefined(index)) default
|
||||
else checkSideForMovement(index)
|
||||
|
||||
def checkSideForFace(index: Int, facing: EnumFacing) = checkSide(index, EnumFacing.values.filter(_ != facing.getOpposite): _*)
|
||||
|
||||
def optSideForFace(index: Int, default: EnumFacing) =
|
||||
if (!isDefined(index)) default
|
||||
else checkSideForAction(index)
|
||||
|
||||
def checkSide(index: Int, allowed: EnumFacing*) = {
|
||||
val side = args.checkInteger(index)
|
||||
if (side < 0 || side > 5) {
|
||||
throw new IllegalArgumentException("invalid side")
|
||||
}
|
||||
@ -60,6 +68,15 @@ object ExtendedArguments {
|
||||
if (allowed.isEmpty || (allowed contains direction)) direction
|
||||
else throw new IllegalArgumentException("unsupported side")
|
||||
}
|
||||
|
||||
def optSide(index: Int, default: EnumFacing, allowed: EnumFacing*) = {
|
||||
if (!isDefined(index)) default
|
||||
else checkSide(index, allowed: _*)
|
||||
}
|
||||
|
||||
private def isDefined(index: Int) = index >= 0 && index < args.count()
|
||||
|
||||
private def hasValue(index: Int) = args.checkAny(index) != null
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package li.cil.oc.util
|
||||
|
||||
import net.minecraft.util.EnumFacing
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
object RotationHelper {
|
||||
def fromYaw(yaw: Float) = {
|
||||
(yaw / 360 * 4).round & 3 match {
|
||||
@ -11,4 +13,81 @@ object RotationHelper {
|
||||
case 3 => EnumFacing.EAST
|
||||
}
|
||||
}
|
||||
|
||||
def toLocal(pitch: EnumFacing, yaw: EnumFacing, value: EnumFacing) =
|
||||
translationFor(pitch, yaw)(value.ordinal)
|
||||
|
||||
def toGlobal(pitch: EnumFacing, yaw: EnumFacing, value: EnumFacing) =
|
||||
inverseTranslationFor(pitch, yaw)(value.ordinal)
|
||||
|
||||
def translationFor(pitch: EnumFacing, yaw: EnumFacing) =
|
||||
translationCache.
|
||||
getOrElseUpdate(pitch, mutable.Map.empty).
|
||||
getOrElseUpdate(yaw, translations(pitch.ordinal)(yaw.ordinal - 2))
|
||||
|
||||
def inverseTranslationFor(pitch: EnumFacing, yaw: EnumFacing) =
|
||||
inverseTranslationCache.
|
||||
getOrElseUpdate(pitch, mutable.Map.empty).
|
||||
getOrElseUpdate(yaw, {
|
||||
val t = translationFor(pitch, yaw)
|
||||
t.indices.
|
||||
map(EnumFacing.getFront).
|
||||
map(t.indexOf).
|
||||
map(EnumFacing.getFront).
|
||||
toArray
|
||||
})
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
private val translationCache = mutable.Map.empty[EnumFacing, mutable.Map[EnumFacing, Array[EnumFacing]]]
|
||||
private val inverseTranslationCache = mutable.Map.empty[EnumFacing, mutable.Map[EnumFacing, Array[EnumFacing]]]
|
||||
|
||||
/**
|
||||
* Translates forge directions based on the block's pitch and yaw. The base
|
||||
* forward direction is facing south with no pitch. The outer array is for
|
||||
* the three different pitch states, the inner for the four different yaw
|
||||
* states.
|
||||
*/
|
||||
private val translations = Array(
|
||||
// Pitch = Down
|
||||
Array(
|
||||
// Yaw = North
|
||||
Array(D.south, D.north, D.up, D.down, D.east, D.west),
|
||||
// Yaw = South
|
||||
Array(D.south, D.north, D.down, D.up, D.west, D.east),
|
||||
// Yaw = West
|
||||
Array(D.south, D.north, D.west, D.east, D.up, D.down),
|
||||
// Yaw = East
|
||||
Array(D.south, D.north, D.east, D.west, D.down, D.up)),
|
||||
// Pitch = Up
|
||||
Array(
|
||||
// Yaw = North
|
||||
Array(D.north, D.south, D.down, D.up, D.east, D.west),
|
||||
// Yaw = South
|
||||
Array(D.north, D.south, D.up, D.down, D.west, D.east),
|
||||
// Yaw = West
|
||||
Array(D.north, D.south, D.west, D.east, D.down, D.up),
|
||||
// Yaw = East
|
||||
Array(D.north, D.south, D.east, D.west, D.up, D.down)),
|
||||
// Pitch = Forward (North|East|South|West)
|
||||
Array(
|
||||
// Yaw = North
|
||||
Array(D.down, D.up, D.south, D.north, D.east, D.west),
|
||||
// Yaw = South
|
||||
Array(D.down, D.up, D.north, D.south, D.west, D.east),
|
||||
// Yaw = West
|
||||
Array(D.down, D.up, D.west, D.east, D.south, D.north),
|
||||
// Yaw = East
|
||||
Array(D.down, D.up, D.east, D.west, D.north, D.south)))
|
||||
|
||||
/** Shortcuts for forge directions to make the above more readable. */
|
||||
private object D {
|
||||
val down = EnumFacing.DOWN
|
||||
val up = EnumFacing.UP
|
||||
val north = EnumFacing.NORTH
|
||||
val south = EnumFacing.SOUTH
|
||||
val west = EnumFacing.WEST
|
||||
val east = EnumFacing.EAST
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user