Merge branch 'master-MC1.7.10' of github.com:MightyPirates/OpenComputers into master-MC1.8

Conflicts:
	src/main/scala/li/cil/oc/common/inventory/Inventory.scala
	src/main/scala/li/cil/oc/common/tileentity/Hologram.scala
	src/main/scala/li/cil/oc/common/tileentity/Robot.scala
This commit is contained in:
Florian Nücke 2015-09-11 01:13:57 +02:00
commit b0950d73b2
26 changed files with 351 additions and 196 deletions

View File

@ -1,7 +1,7 @@
minecraft.version=1.8
forge.version=11.14.3.1450
oc.version=1.5.17
oc.version=1.5.18
oc.subversion=dev
ae2.version=rv2-beta-26

View File

@ -54,6 +54,8 @@ object PacketHandler extends CommonPacketHandler {
case PacketType.HologramClear => onHologramClear(p)
case PacketType.HologramColor => onHologramColor(p)
case PacketType.HologramPowerChange => onHologramPowerChange(p)
case PacketType.HologramRotation => onHologramRotation(p)
case PacketType.HologramRotationSpeed => onHologramRotationSpeed(p)
case PacketType.HologramScale => onHologramScale(p)
case PacketType.HologramTranslation => onHologramPositionOffsetY(p)
case PacketType.HologramValues => onHologramValues(p)
@ -254,6 +256,26 @@ object PacketHandler extends CommonPacketHandler {
case _ => // Invalid packet.
}
def onHologramRotation(p: PacketParser) =
p.readTileEntity[Hologram]() match {
case Some(t) =>
t.rotationAngle = p.readFloat()
t.rotationX = p.readFloat()
t.rotationY = p.readFloat()
t.rotationZ = p.readFloat()
case _ => // Invalid packet.
}
def onHologramRotationSpeed(p: PacketParser) =
p.readTileEntity[Hologram]() match {
case Some(t) =>
t.rotationSpeed = p.readFloat()
t.rotationSpeedX = p.readFloat()
t.rotationSpeedY = p.readFloat()
t.rotationSpeedZ = p.readFloat()
case _ => // Invalid packet.
}
def onLootDisk(p: PacketParser) = {
val stack = p.readItemStack()
if (stack != null) {

View File

@ -2,7 +2,7 @@ package li.cil.oc.client.renderer.font
import li.cil.oc.Settings
import li.cil.oc.client.renderer.font.DynamicFontRenderer.CharTexture
import li.cil.oc.util.FontUtil
import li.cil.oc.util.FontUtils
import li.cil.oc.util.RenderState
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.GlStateManager
@ -76,7 +76,7 @@ class DynamicFontRenderer extends TextureFontRenderer with IResourceManagerReloa
}
private def createCharIcon(char: Char): DynamicFontRenderer.CharIcon = {
if (FontUtil.wcwidth(char) < 1 || glyphProvider.getGlyph(char) == null) {
if (FontUtils.wcwidth(char) < 1 || glyphProvider.getGlyph(char) == null) {
if (char == '?') null
else charMap.getOrElseUpdate('?', createCharIcon('?'))
}
@ -123,10 +123,10 @@ object DynamicFontRenderer {
RenderState.bindTexture(id)
}
def isFull(char: Char) = chars + FontUtil.wcwidth(char) > capacity
def isFull(char: Char) = chars + FontUtils.wcwidth(char) > capacity
def add(char: Char) = {
val glyphWidth = FontUtil.wcwidth(char)
val glyphWidth = FontUtils.wcwidth(char)
val w = owner.charWidth * glyphWidth
val h = owner.charHeight
// Force line break if we have a char that's wider than what space remains in this row.

View File

@ -2,7 +2,7 @@ package li.cil.oc.client.renderer.font;
import li.cil.oc.OpenComputers;
import li.cil.oc.Settings;
import li.cil.oc.util.FontUtil;
import li.cil.oc.util.FontUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.BufferUtils;
@ -35,7 +35,7 @@ public class FontParserUnifont implements IGlyphProvider {
while ((line = input.readLine()) != null) {
final String[] info = line.split(":");
final int charCode = Integer.parseInt(info[0], 16);
final int expectedWidth = FontUtil.wcwidth(charCode);
final int expectedWidth = FontUtils.wcwidth(charCode);
if (expectedWidth < 1) continue; // Skip control characters.
final byte[] glyph = new byte[info[1].length() >> 1];
final int glyphWidth = glyph.length / getGlyphHeight();

View File

@ -39,7 +39,7 @@ public interface IGlyphProvider {
* <p/>
* Each glyph provided is expected to have the same width multiplier; i.e.
* a glyphs actual width (in pixels) is expected to be this value times
* {@link li.cil.oc.util.FontUtil#wcwidth(int)} (for a specific char).
* {@link li.cil.oc.util.FontUtils#wcwidth(int)} (for a specific char).
*/
public int getGlyphWidth();

View File

@ -99,6 +99,9 @@ object HologramRenderer extends TileEntitySpecialRenderer with Callable[Int] wit
case _ => // No pitch.
}
GL11.glRotatef(hologram.rotationAngle, hologram.rotationX, hologram.rotationY, hologram.rotationZ)
GL11.glRotatef(hologram.rotationSpeed * (hologram.getWorld.getTotalWorldTime % (360 * 20 - 1) + f) / 20f, hologram.rotationSpeedX, hologram.rotationSpeedY, hologram.rotationSpeedZ)
GL11.glScaled(1.001, 1.001, 1.001) // Avoid z-fighting with other blocks.
GL11.glTranslated(
(hologram.translation.xCoord * hologram.width / 16 - 1.5) * hologram.scale,

View File

@ -26,7 +26,6 @@ import li.cil.oc.util._
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.entity.player.EntityPlayerMP
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.server.MinecraftServer
import net.minecraft.tileentity.TileEntity
import net.minecraftforge.common.util.FakePlayer
@ -199,13 +198,9 @@ object EventHandler {
def onEntityJoinWorld(e: EntityJoinWorldEvent): Unit = {
if (Settings.get.giveManualToNewPlayers && !e.world.isRemote) e.entity match {
case player: EntityPlayer if !player.isInstanceOf[FakePlayer] =>
val nbt = player.getEntityData
if (!nbt.hasKey(EntityPlayer.PERSISTED_NBT_TAG)) {
nbt.setTag(EntityPlayer.PERSISTED_NBT_TAG, new NBTTagCompound())
}
val ocData = nbt.getCompoundTag(EntityPlayer.PERSISTED_NBT_TAG)
if (!ocData.getBoolean(Settings.namespace + "receivedManual")) {
ocData.setBoolean(Settings.namespace + "receivedManual", true)
val persistedData = PlayerUtils.persistedData(player)
if (!persistedData.getBoolean(Settings.namespace + "receivedManual")) {
persistedData.setBoolean(Settings.namespace + "receivedManual", true)
player.inventory.addItemStackToInventory(api.Items.get(Constants.ItemName.Manual).createItemStack(1))
}
case _ =>

View File

@ -16,6 +16,8 @@ object PacketType extends Enumeration {
HologramClear,
HologramColor,
HologramPowerChange,
HologramRotation,
HologramRotationSpeed,
HologramScale,
HologramTranslation,
HologramValues,

View File

@ -1,15 +1,12 @@
package li.cil.oc.common.inventory
import li.cil.oc.Localization
import li.cil.oc.Settings
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.util.Constants.NBT
trait Inventory extends IInventory {
trait Inventory extends SimpleInventory {
def items: Array[Option[ItemStack]]
def updateItems(slot: Int, stack: ItemStack) = items(slot) = Option(stack)
@ -20,24 +17,6 @@ trait Inventory extends IInventory {
if (slot >= 0 && slot < getSizeInventory) items(slot).orNull
else null
override def decrStackSize(slot: Int, amount: Int) =
if (slot >= 0 && slot < getSizeInventory) {
(items(slot) match {
case Some(stack) if stack.stackSize - amount < getInventoryStackRequired =>
setInventorySlotContents(slot, null)
stack
case Some(stack) =>
val result = stack.splitStack(amount)
markDirty()
result
case _ => null
}) match {
case stack: ItemStack if stack.stackSize > 0 => stack
case _ => null
}
}
else null
override def setInventorySlotContents(slot: Int, stack: ItemStack): Unit = {
if (slot >= 0 && slot < getSizeInventory) {
if (stack == null && items(slot).isEmpty) {
@ -67,30 +46,10 @@ trait Inventory extends IInventory {
}
}
def getInventoryStackRequired = 1
override def getStackInSlotOnClosing(slot: Int) = null
override def openInventory(player: EntityPlayer) {}
override def closeInventory(player: EntityPlayer) {}
override def clear() {} // TODO implement?
override def getName = Settings.namespace + "container." + inventoryName
override def hasCustomName = false
override def getDisplayName = Localization.localizeLater(getName)
protected def inventoryName = getClass.getSimpleName
override def getField(id: Int) = 0
override def setField(id: Int, value: Int) {}
override def getFieldCount = 0
// ----------------------------------------------------------------------- //
def load(nbt: NBTTagCompound) {

View File

@ -0,0 +1,67 @@
package li.cil.oc.common.inventory
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
trait InventoryProxy extends IInventory {
def inventory: IInventory
def offset = 0
override def getSizeInventory = inventory.getSizeInventory
override def getInventoryStackLimit = inventory.getInventoryStackLimit
override def getName = inventory.getName
override def getDisplayName = inventory.getDisplayName
override def hasCustomName = inventory.hasCustomName
override def isUseableByPlayer(player: EntityPlayer) = inventory.isUseableByPlayer(player)
override def isItemValidForSlot(slot: Int, stack: ItemStack) = {
val offsetSlot = slot + offset
isValidSlot(offsetSlot) && inventory.isItemValidForSlot(offsetSlot, stack)
}
override def getStackInSlot(slot: Int) = {
val offsetSlot = slot + offset
if (isValidSlot(offsetSlot)) inventory.getStackInSlot(offsetSlot)
else null
}
override def decrStackSize(slot: Int, amount: Int) = {
val offsetSlot = slot + offset
if (isValidSlot(offsetSlot)) inventory.decrStackSize(offsetSlot, amount)
else null
}
override def getStackInSlotOnClosing(slot: Int) = {
val offsetSlot = slot + offset
if (isValidSlot(offsetSlot)) inventory.getStackInSlotOnClosing(offsetSlot)
else null
}
override def setInventorySlotContents(slot: Int, stack: ItemStack) = {
val offsetSlot = slot + offset
if (isValidSlot(offsetSlot)) inventory.setInventorySlotContents(offsetSlot, stack)
}
override def markDirty() = inventory.markDirty()
override def openInventory(player: EntityPlayer) = inventory.openInventory(player)
override def closeInventory(player: EntityPlayer) = inventory.closeInventory(player)
override def setField(id: Int, value: Int) = inventory.setField(id, value)
override def clear() = inventory.clear()
override def getFieldCount = inventory.getFieldCount
override def getField(id: Int) = inventory.getField(id)
private def isValidSlot(slot: Int) = slot >= 0 && slot < getSizeInventory
}

View File

@ -0,0 +1,61 @@
package li.cil.oc.common.inventory
import li.cil.oc.Localization
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
trait SimpleInventory extends IInventory {
override def hasCustomName = false
override def getDisplayName = Localization.localizeLater(getName)
override def getInventoryStackLimit = 64
// Items required in a slot before it's set to null (for ghost stacks).
def getInventoryStackRequired = 1
override def openInventory(player: EntityPlayer): Unit = {}
override def closeInventory(player: EntityPlayer): Unit = {}
override def decrStackSize(slot: Int, amount: Int): ItemStack = {
if (slot >= 0 && slot < getSizeInventory) {
(getStackInSlot(slot) match {
case stack: ItemStack if stack.stackSize - amount < getInventoryStackRequired =>
setInventorySlotContents(slot, null)
stack
case stack: ItemStack =>
val result = stack.splitStack(amount)
markDirty()
result
case _ => null
}) match {
case stack: ItemStack if stack.stackSize > 0 => stack
case _ => null
}
}
else null
}
override def getStackInSlotOnClosing(slot: Int) = {
if (slot >= 0 && slot < getSizeInventory) {
val stack = getStackInSlot(slot)
setInventorySlotContents(slot, null)
stack
}
else null
}
override def clear(): Unit = {
for (slot <- 0 until getSizeInventory) {
setInventorySlotContents(slot, null)
}
}
override def getField(id: Int) = 0
override def setField(id: Int, value: Int) {}
override def getFieldCount = 0
}

View File

@ -155,8 +155,6 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
override def getSizeInventory = 1
override def getInventoryStackLimit = 64
override def isItemValidForSlot(i: Int, stack: ItemStack) =
allowDisassembling(stack) &&
(((Settings.get.disassembleAllTheThings || api.Items.get(stack) != null) && ItemUtils.getIngredients(stack).nonEmpty) ||

View File

@ -63,6 +63,16 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
var hasPower = true
// Rotation base state. Current rotation is based on world time. See HologramRenderer.
var rotationAngle = 0f
var rotationX = 0f
var rotationY = 0f
var rotationZ = 0f
var rotationSpeed = 0f
var rotationSpeedX = 0f
var rotationSpeedY = 0f
var rotationSpeedZ = 0f
final val colorsByTier = Array(Array(0x00FF00), Array(0x0000FF, 0x00FF00, 0xFF0000)) // 0xBBGGRR for rendering convenience
// This is a def and not a val for loading (where the tier comes from the nbt and is always 0 here).
@ -293,6 +303,44 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
result(oldValue)
}
@Callback(doc = """function(angle:number, x:number, y:number, z:number):boolean -- Set the base rotation of the displayed hologram.""")
def setRotation(context: Context, args: Arguments): Array[AnyRef] = {
if (tier > 0) {
val r = args.checkDouble(0) % 360
val x = args.checkDouble(1)
val y = args.checkDouble(2)
val z = args.checkDouble(3)
rotationAngle = r.toFloat
rotationX = x.toFloat
rotationY = y.toFloat
rotationZ = z.toFloat
ServerPacketSender.sendHologramRotation(this)
result(true)
}
else result(null, "not supported")
}
@Callback(doc = """function(speed:number, x:number, y:number, z:number):boolean -- Set the rotation speed of the displayed hologram.""")
def setRotationSpeed(context: Context, args: Arguments): Array[AnyRef] = {
if (tier > 0) {
val v = args.checkDouble(0) max -360 * 4 min 360 * 4
val x = args.checkDouble(1)
val y = args.checkDouble(2)
val z = args.checkDouble(3)
rotationSpeed = v.toFloat
rotationSpeedX = x.toFloat
rotationSpeedY = y.toFloat
rotationSpeedZ = z.toFloat
ServerPacketSender.sendHologramRotationSpeed(this)
result(true)
}
else result(null, "not supported")
}
private def checkCoordinates(args: Arguments, idxX: Int = 0, idxY: Int = 1, idxZ: Int = 2) = {
val x = if (idxX >= 0) args.checkInteger(idxX) - 1 else 0
if (x < 0 || x >= width) throw new ArrayIndexOutOfBoundsException("x")
@ -370,12 +418,14 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
def getFadeStartDistanceSquared = scale / Settings.get.hologramMaxScaleByTier.max * Settings.get.hologramFadeStartDistance * Settings.get.hologramFadeStartDistance
private final val Sqrt2 = Math.sqrt(2)
override def getRenderBoundingBox = {
val cx = x + 0.5
val cy = y + 0.5
val cz = z + 0.5
val sh = width / 16 * scale
val sv = height / 16 * scale
val sh = width / 16 * scale * Sqrt2 // overscale to take into account 45 degree rotation
val sv = height / 16 * scale * Sqrt2
AxisAlignedBB.fromBounds(
cx + (-0.5 + translation.xCoord) * sh,
cy + translation.yCoord * sv,
@ -398,6 +448,14 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
val ty = nbt.getDouble(Settings.namespace + "offsetY")
val tz = nbt.getDouble(Settings.namespace + "offsetZ")
translation = new Vec3(tx, ty, tz)
rotationAngle = nbt.getFloat(Settings.namespace + "rotationAngle")
rotationX = nbt.getFloat(Settings.namespace + "rotationX")
rotationY = nbt.getFloat(Settings.namespace + "rotationY")
rotationZ = nbt.getFloat(Settings.namespace + "rotationZ")
rotationSpeed = nbt.getFloat(Settings.namespace + "rotationSpeed")
rotationSpeedX = nbt.getFloat(Settings.namespace + "rotationSpeedX")
rotationSpeedY = nbt.getFloat(Settings.namespace + "rotationSpeedY")
rotationSpeedZ = nbt.getFloat(Settings.namespace + "rotationSpeedZ")
}
override def writeToNBTForServer(nbt: NBTTagCompound) = this.synchronized {
@ -413,6 +471,14 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
nbt.setDouble(Settings.namespace + "offsetX", translation.xCoord)
nbt.setDouble(Settings.namespace + "offsetY", translation.yCoord)
nbt.setDouble(Settings.namespace + "offsetZ", translation.zCoord)
nbt.setFloat(Settings.namespace + "rotationAngle", rotationAngle)
nbt.setFloat(Settings.namespace + "rotationX", rotationX)
nbt.setFloat(Settings.namespace + "rotationY", rotationY)
nbt.setFloat(Settings.namespace + "rotationZ", rotationZ)
nbt.setFloat(Settings.namespace + "rotationSpeed", rotationSpeed)
nbt.setFloat(Settings.namespace + "rotationSpeedX", rotationSpeedX)
nbt.setFloat(Settings.namespace + "rotationSpeedY", rotationSpeedY)
nbt.setFloat(Settings.namespace + "rotationSpeedZ", rotationSpeedZ)
}
@SideOnly(Side.CLIENT)
@ -426,6 +492,14 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
val ty = nbt.getDouble("offsetY")
val tz = nbt.getDouble("offsetZ")
translation = new Vec3(tx, ty, tz)
rotationAngle = nbt.getFloat("rotationAngle")
rotationX = nbt.getFloat("rotationX")
rotationY = nbt.getFloat("rotationY")
rotationZ = nbt.getFloat("rotationZ")
rotationSpeed = nbt.getFloat("rotationSpeed")
rotationSpeedX = nbt.getFloat("rotationSpeedX")
rotationSpeedY = nbt.getFloat("rotationSpeedY")
rotationSpeedZ = nbt.getFloat("rotationSpeedZ")
}
override def writeToNBTForClient(nbt: NBTTagCompound) {
@ -437,5 +511,13 @@ class Hologram(var tier: Int) extends traits.Environment with SidedEnvironment w
nbt.setDouble("offsetX", translation.xCoord)
nbt.setDouble("offsetY", translation.yCoord)
nbt.setDouble("offsetZ", translation.zCoord)
nbt.setFloat("rotationAngle", rotationAngle)
nbt.setFloat("rotationX", rotationX)
nbt.setFloat("rotationY", rotationY)
nbt.setFloat("rotationZ", rotationZ)
nbt.setFloat("rotationSpeed", rotationSpeed)
nbt.setFloat("rotationSpeedX", rotationSpeedX)
nbt.setFloat("rotationSpeedY", rotationSpeedY)
nbt.setFloat("rotationSpeedZ", rotationSpeedZ)
}
}

View File

@ -235,6 +235,9 @@ class Microcontroller extends traits.PowerAcceptor with traits.Hub with traits.C
// Nope.
override def decrStackSize(slot: Int, amount: Int) = null
// Nope.
override def getStackInSlotOnClosing(slot: Int) = null
// For hotswapping EEPROMs.
def changeEEPROM(newEeprom: ItemStack) = {
val oldEepromIndex = info.components.indexWhere(api.Items.get(_) == api.Items.get(Constants.ItemName.EEPROM))

View File

@ -325,8 +325,6 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
override def getSizeInventory = 3
override def getInventoryStackLimit = 64
override def isItemValidForSlot(slot: Int, stack: ItemStack) =
if (slot == slotMaterial)
PrintData.materialValue(stack) > 0

View File

@ -14,6 +14,7 @@ import li.cil.oc.client.gui
import li.cil.oc.common.EventHandler
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
import li.cil.oc.common.inventory.InventoryProxy
import li.cil.oc.common.inventory.InventorySelection
import li.cil.oc.common.inventory.TankSelection
import li.cil.oc.common.item.data.RobotData
@ -32,7 +33,6 @@ import net.minecraft.block.BlockLiquid
import net.minecraft.client.Minecraft
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.init.Blocks
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.AxisAlignedBB
@ -68,87 +68,19 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
def isCreative = tier == Tier.Four
val equipmentInventory = new IInventory {
val equipmentInventory = new InventoryProxy {
override def inventory = Robot.this
override def getSizeInventory = 4
override def getInventoryStackLimit = Robot.this.getInventoryStackLimit
override def markDirty() = Robot.this.markDirty()
override def isItemValidForSlot(slot: Int, stack: ItemStack) =
slot >= 0 && slot < getSizeInventory && Robot.this.isItemValidForSlot(slot, stack)
override def getStackInSlot(slot: Int) =
if (slot >= 0 && slot < getSizeInventory) Robot.this.getStackInSlot(slot)
else null
override def setInventorySlotContents(slot: Int, stack: ItemStack) =
if (slot >= 0 && slot < getSizeInventory) Robot.this.setInventorySlotContents(slot, stack)
override def decrStackSize(slot: Int, amount: Int) =
if (slot >= 0 && slot < getSizeInventory) Robot.this.decrStackSize(slot, amount)
else null
override def getName = Robot.this.getName
override def hasCustomName = Robot.this.hasCustomName
override def openInventory(player: EntityPlayer): Unit = {}
override def closeInventory(player: EntityPlayer): Unit = {}
override def getStackInSlotOnClosing(slot: Int): ItemStack = null
override def isUseableByPlayer(player: EntityPlayer) = Robot.this.isUseableByPlayer(player)
override def getField(id: Int) = Robot.this.getField(id)
override def setField(id: Int, value: Int) = Robot.this.setField(id, value)
override def getFieldCount = Robot.this.getFieldCount
override def clear() = Robot.this.clear()
override def getDisplayName = Robot.this.getDisplayName
}
// Wrapper for the part of the inventory that is mutable.
val mainInventory = new IInventory {
val mainInventory = new InventoryProxy {
override def inventory = Robot.this
override def getSizeInventory = Robot.this.inventorySize
override def getInventoryStackLimit = Robot.this.getInventoryStackLimit
override def markDirty() = Robot.this.markDirty()
override def isItemValidForSlot(slot: Int, stack: ItemStack) = Robot.this.isItemValidForSlot(equipmentInventory.getSizeInventory + slot, stack)
override def getStackInSlot(slot: Int) = Robot.this.getStackInSlot(equipmentInventory.getSizeInventory + slot)
override def setInventorySlotContents(slot: Int, stack: ItemStack) = Robot.this.setInventorySlotContents(equipmentInventory.getSizeInventory + slot, stack)
override def decrStackSize(slot: Int, amount: Int) = Robot.this.decrStackSize(equipmentInventory.getSizeInventory + slot, amount)
override def getName = Robot.this.getName
override def hasCustomName = Robot.this.hasCustomName
override def openInventory(player: EntityPlayer): Unit = {}
override def closeInventory(player: EntityPlayer): Unit = {}
override def getStackInSlotOnClosing(slot: Int): ItemStack = null
override def isUseableByPlayer(player: EntityPlayer) = Robot.this.isUseableByPlayer(player)
override def getField(id: Int) = Robot.this.getField(id)
override def setField(id: Int, value: Int) = Robot.this.setField(id, value)
override def getFieldCount = Robot.this.getFieldCount
override def clear() = Robot.this.clear()
override def getDisplayName = Robot.this.getDisplayName
override def offset = equipmentInventory.getSizeInventory
}
val actualInventorySize = 100
@ -760,8 +692,6 @@ class Robot extends traits.Computer with traits.PowerInformation with traits.Rot
var getSizeInventory = actualInventorySize
override def getInventoryStackLimit = 64
override def getStackInSlot(slot: Int) = {
if (slot >= getSizeInventory) null // Required to always show 16 inventory slots in GUI.
else if (slot >= getSizeInventory - componentCount) {

View File

@ -215,6 +215,30 @@ object PacketSender {
pb.sendToPlayersNearTileEntity(t)
}
def sendHologramRotation(t: tileentity.Hologram) {
val pb = new SimplePacketBuilder(PacketType.HologramRotation)
pb.writeTileEntity(t)
pb.writeFloat(t.rotationAngle)
pb.writeFloat(t.rotationX)
pb.writeFloat(t.rotationY)
pb.writeFloat(t.rotationZ)
pb.sendToPlayersNearTileEntity(t)
}
def sendHologramRotationSpeed(t: tileentity.Hologram) {
val pb = new SimplePacketBuilder(PacketType.HologramRotationSpeed)
pb.writeTileEntity(t)
pb.writeFloat(t.rotationSpeed)
pb.writeFloat(t.rotationSpeedX)
pb.writeFloat(t.rotationSpeedY)
pb.writeFloat(t.rotationSpeedZ)
pb.sendToPlayersNearTileEntity(t)
}
def sendLootDisks(p: EntityPlayerMP): Unit = {
// Sending as separate packets, because CompressedStreamTools hiccups otherwise...
val stacks = Loot.worldDisks.values.map(_._1)

View File

@ -527,7 +527,12 @@ class Player(val agent: internal.Agent) extends FakePlayer(agent.world.asInstanc
override def onItemPickup(entity: Entity, count: Int) {}
override def setCurrentItemOrArmor(slot: Int, stack: ItemStack) {}
override def setCurrentItemOrArmor(slot: Int, stack: ItemStack): Unit = {
if (slot == 0 && agent.equipmentInventory.getSizeInventory > 0) {
agent.equipmentInventory.setInventorySlotContents(slot, stack)
}
// else: armor slots, which are unsupported in agents.
}
override def setRevengeTarget(entity: EntityLivingBase) {}

View File

@ -24,8 +24,8 @@ class OSAPI(owner: NativeLuaArchitecture) extends NativeLuaAPI(owner) {
if (lua.getTop > 0 && lua.isString(1)) lua.toString(1)
else "%d/%m/%y %H:%M:%S"
val time =
if (lua.getTop > 1 && lua.isNumber(2)) lua.toNumber(2) * 1000 / 60 / 60
else machine.worldTime + 6000
if (lua.getTop > 1 && lua.isNumber(2)) lua.toNumber(2)
else (machine.worldTime + 6000) * 60 * 60 / 1000
val dt = GameTimeFormatter.parse(time)
def fmt(format: String) {

View File

@ -1,7 +1,7 @@
package li.cil.oc.server.machine.luac
import li.cil.oc.util.ExtendedLuaState.extendLuaState
import li.cil.oc.util.FontUtil
import li.cil.oc.util.FontUtils
class UnicodeAPI(owner: NativeLuaArchitecture) extends NativeLuaAPI(owner) {
override def initialize() {
@ -57,20 +57,20 @@ class UnicodeAPI(owner: NativeLuaArchitecture) extends NativeLuaAPI(owner) {
lua.setField(-2, "upper")
lua.pushScalaFunction(lua => {
lua.pushBoolean(FontUtil.wcwidth(lua.checkString(1).codePointAt(0)) > 1)
lua.pushBoolean(FontUtils.wcwidth(lua.checkString(1).codePointAt(0)) > 1)
1
})
lua.setField(-2, "isWide")
lua.pushScalaFunction(lua => {
lua.pushInteger(FontUtil.wcwidth(lua.checkString(1).codePointAt(0)))
lua.pushInteger(FontUtils.wcwidth(lua.checkString(1).codePointAt(0)))
1
})
lua.setField(-2, "charWidth")
lua.pushScalaFunction(lua => {
val value = lua.checkString(1)
lua.pushInteger(value.toCharArray.map(ch => math.max(1, FontUtil.wcwidth(ch))).sum)
lua.pushInteger(value.toCharArray.map(ch => math.max(1, FontUtils.wcwidth(ch))).sum)
1
})
lua.setField(-2, "wlen")
@ -81,7 +81,7 @@ class UnicodeAPI(owner: NativeLuaArchitecture) extends NativeLuaAPI(owner) {
var width = 0
var end = 0
while (width < count) {
width += FontUtil.wcwidth(value(end))
width += FontUtils.wcwidth(value(end))
end += 1
}
if (end > 1) lua.pushString(value.substring(0, end - 1))

View File

@ -17,8 +17,8 @@ class OSAPI(owner: LuaJLuaArchitecture) extends LuaJAPI(owner) {
if (args.narg > 0 && args.isstring(1)) args.tojstring(1)
else "%d/%m/%y %H:%M:%S"
val time =
if (args.narg > 1 && args.isnumber(2)) args.todouble(2) * 1000 / 60 / 60
else machine.worldTime + 6000
if (args.narg > 1 && args.isnumber(2)) args.todouble(2)
else (machine.worldTime + 6000) * 60 * 60 / 1000
val dt = GameTimeFormatter.parse(time)
def fmt(format: String) = {

View File

@ -1,6 +1,6 @@
package li.cil.oc.server.machine.luaj
import li.cil.oc.util.FontUtil
import li.cil.oc.util.FontUtils
import li.cil.oc.util.ScalaClosure._
import li.cil.repack.org.luaj.vm2.LuaValue
import li.cil.repack.org.luaj.vm2.Varargs
@ -37,14 +37,14 @@ class UnicodeAPI(owner: LuaJLuaArchitecture) extends LuaJAPI(owner) {
})
unicode.set("isWide", (args: Varargs) =>
LuaValue.valueOf(FontUtil.wcwidth(args.checkjstring(1).codePointAt(0)) > 1))
LuaValue.valueOf(FontUtils.wcwidth(args.checkjstring(1).codePointAt(0)) > 1))
unicode.set("charWidth", (args: Varargs) =>
LuaValue.valueOf(FontUtil.wcwidth(args.checkjstring(1).codePointAt(0))))
LuaValue.valueOf(FontUtils.wcwidth(args.checkjstring(1).codePointAt(0))))
unicode.set("wlen", (args: Varargs) => {
val value = args.checkjstring(1)
LuaValue.valueOf(value.toCharArray.map(ch => math.max(1, FontUtil.wcwidth(ch))).sum)
LuaValue.valueOf(value.toCharArray.map(ch => math.max(1, FontUtils.wcwidth(ch))).sum)
})
unicode.set("wtrunc", (args: Varargs) => {
@ -53,7 +53,7 @@ class UnicodeAPI(owner: LuaJLuaArchitecture) extends LuaJAPI(owner) {
var width = 0
var end = 0
while (width < count) {
width += FontUtil.wcwidth(value(end))
width += FontUtils.wcwidth(value(end))
end += 1
}
if (end > 1) LuaValue.valueOf(value.substring(0, end - 1))

View File

@ -4,14 +4,14 @@ import java.io.IOException
import li.cil.oc.OpenComputers
object FontUtil {
object FontUtils {
// Note: we load the widths from a file (one byte per width) because the Scala
// compiler craps its pants when we try to have it as an array in the source
// file... seems having an array with 0x10000 entries leads to stack overflows,
// who would have known!
private val widths = {
val ba = Array.fill[Byte](0x10000)(-1)
val is = FontUtil.getClass.getResourceAsStream("/assets/opencomputers/wcwidth.bin")
val is = FontUtils.getClass.getResourceAsStream("/assets/opencomputers/wcwidth.bin")
if (is != null) {
try {
is.read(ba)

View File

@ -1,5 +1,8 @@
package li.cil.oc.util
import java.util.Calendar
import java.util.GregorianCalendar
import scala.collection.mutable
object GameTimeFormatter {
@ -56,34 +59,19 @@ object GameTimeFormatter {
'%' -> (t => "%")
)
private val monthLengths = Array(
Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31))
private def monthLengthsForYear(year: Int) = {
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) monthLengths(0) else monthLengths(1)
}
def parse(time: Double) = {
var day = (time / 24000).toLong
val weekDay = ((4 + day) % 7).toInt
val year = 1970 + (day / 364.2425).toInt
val yearDay = (day % 364.2425).toInt
day = yearDay
val monthLengths = monthLengthsForYear(year)
var month = 0
while (day >= monthLengths(month)) {
day = day - monthLengths(month)
month = month + 1
}
val calendar = new GregorianCalendar()
calendar.setTimeInMillis((time * 1000).toLong)
var seconds = ((time % 24000) * 60 * 60 / 1000).toInt
var minutes = seconds / 60
seconds = seconds % 60
val hours = (minutes / 60) % 24
minutes = minutes % 60
new DateTime(year, month + 1, day.toInt + 1, weekDay + 1, yearDay + 1, hours, minutes, seconds)
new DateTime(
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH) + 1,
calendar.get(Calendar.DAY_OF_MONTH),
calendar.get(Calendar.DAY_OF_WEEK),
calendar.get(Calendar.DAY_OF_YEAR),
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
calendar.get(Calendar.SECOND))
}
def format(format: String, time: DateTime) = {
@ -103,10 +91,14 @@ object GameTimeFormatter {
}
def mktime(year: Int, mon: Int, mday: Int, hour: Int, min: Int, sec: Int): Option[Int] = {
if (year < 1970 || mon < 1 || mon > 12) return None
val monthLengths = monthLengthsForYear(year)
val days = ((year - 1970) * 365.2425).ceil.toInt + (0 until mon - 1).foldLeft(0)((d, m) => d + monthLengths(m)) + mday - 1
val secs = sec + (min + (hour - 1 + days * 24) * 60) * 60
Option(secs)
val calendar = new GregorianCalendar()
calendar.set(Calendar.YEAR, year)
calendar.set(Calendar.MONTH, mon - 1)
calendar.set(Calendar.DAY_OF_MONTH, mday)
calendar.set(Calendar.HOUR_OF_DAY, hour)
calendar.set(Calendar.MINUTE, min)
calendar.set(Calendar.SECOND, sec)
Option((calendar.getTimeInMillis / 1000).toInt)
}
}

View File

@ -0,0 +1,14 @@
package li.cil.oc.util
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.NBTTagCompound
object PlayerUtils {
def persistedData(player: EntityPlayer): NBTTagCompound = {
val nbt = player.getEntityData
if (!nbt.hasKey(EntityPlayer.PERSISTED_NBT_TAG)) {
nbt.setTag(EntityPlayer.PERSISTED_NBT_TAG, new NBTTagCompound())
}
nbt.getCompoundTag(EntityPlayer.PERSISTED_NBT_TAG)
}
}

View File

@ -129,7 +129,7 @@ class TextBuffer(var width: Int, var height: Int, initialFormat: PackedColor.Col
val c = s(x - col)
changed = changed || (line(bx) != c) || (lineColor(bx) != packed)
setChar(line, lineColor, bx, c)
bx += math.max(1, FontUtil.wcwidth(c))
bx += math.max(1, FontUtils.wcwidth(c))
}
changed
}
@ -148,7 +148,7 @@ class TextBuffer(var width: Int, var height: Int, initialFormat: PackedColor.Col
for (x <- bx until math.min(col + w, width) if bx < line.length) {
changed = changed || (line(bx) != c) || (lineColor(bx) != packed)
setChar(line, lineColor, bx, c)
bx += math.max(1, FontUtil.wcwidth(c))
bx += math.max(1, FontUtils.wcwidth(c))
}
}
changed
@ -185,7 +185,7 @@ class TextBuffer(var width: Int, var height: Int, initialFormat: PackedColor.Col
changed = changed || (nl(nx) != ol(ox)) || (nc(nx) != oc(ox))
nl(nx) = ol(ox)
nc(nx) = oc(ox)
for (offset <- 1 until FontUtil.wcwidth(nl(nx))) {
for (offset <- 1 until FontUtils.wcwidth(nl(nx))) {
nl(nx + offset) = ol(' ')
nc(nx + offset) = oc(nx)
}
@ -198,17 +198,17 @@ class TextBuffer(var width: Int, var height: Int, initialFormat: PackedColor.Col
}
private def setChar(line: Array[Char], lineColor: Array[Short], x: Int, c: Char) {
if (FontUtil.wcwidth(c) > 1 && x >= line.length - 1) {
if (FontUtils.wcwidth(c) > 1 && x >= line.length - 1) {
// Don't allow setting wide chars in right-most col.
return
}
if (x > 0 && line(x) == ' ' && FontUtil.wcwidth(line(x - 1)) > 1) {
if (x > 0 && line(x) == ' ' && FontUtils.wcwidth(line(x - 1)) > 1) {
// Don't allow setting the cell following a wide char.
return
}
line(x) = c
lineColor(x) = packed
for (x1 <- x + 1 until x + FontUtil.wcwidth(c)) {
for (x1 <- x + 1 until x + FontUtils.wcwidth(c)) {
line(x1) = ' '
lineColor(x1) = packed
}