Merge branch 'master' of github.com:MightyPirates/OpenComputers into MC1.7

Conflicts:
	src/main/scala/li/cil/oc/OpenComputers.scala
	src/main/scala/li/cil/oc/server/fs/CC15FileSystem.scala
This commit is contained in:
Florian Nücke 2014-04-21 16:48:00 +02:00
commit 0025fc19b0
21 changed files with 244 additions and 86 deletions

View File

@ -0,0 +1,34 @@
package stargatetech2.api;
import java.util.Collection;
import net.minecraft.item.ItemStack;
/**
* The way to get ItemStacks added to the game by StargateTech 2
*
* @author LordFokas
*/
public interface IStackManager {
/**
* Used to fetch an ItemStack by it's name, with a default size of 1.
*
* @param stack The stack we want to fetch.
* @return The stack, or null if none was found.
*/
public ItemStack get(String stack);
/**
* Used to fetch an ItemStack by it's name with a given size.
*
* @param stack The stack we want to fetch.
* @param size The size the stack comes with. Must be in the range 1 - 64.
* @return The stack, or null if none was found.
*/
public ItemStack get(String stack, int size);
/**
* @return A list with the names of all the existing stacks.
*/
public Collection<String> getAllStacks();
}

View File

@ -24,4 +24,9 @@ public interface IStargateTechAPI {
* @return The current IFactory instance.
*/
public IFactory getFactory();
/**
* @return The current IStackManager instance.
*/
public IStackManager getStackManager();
}

View File

@ -0,0 +1,37 @@
package stargatetech2.api.shields;
/**
* Implemented by the Shield Controller TileEntities.
*
* @author LordFokas
*/
public interface IShieldController {
/**
* Given the way shield emitters work together, you cannot
* directly access their ShieldPermissions object.
* This means you cannot use this method to change
* permissions on a shield.
*
* @return A deep clone of the ShieldPermissions object that
* defines this controller's shield behavior.
*/
public ShieldPermissions getPermissions();
/**
* @return True if the shield is activated, false otherwise.
*/
public boolean isShieldOn();
/**
* @return The name of the player who owns this Shield Controller.
*/
public String getOwner();
/**
* Checks if a player can access this device.
*
* @param player The player's name.
* @return Whether or not this player can access this device.
*/
public boolean hasAccess(String player);
}

View File

@ -10,16 +10,16 @@ import net.minecraft.world.World;
public interface IShieldable {
/**
* Called by shield emitters to make blocks raise their shields.
* The block on {px, py, pz} contains an ITileShieldEmitter from which
* you can get the current ShieldPermissions object.
* The block on {px, py, pz} contains an IShieldController from
* which you can get the current ShieldPermissions object.
*
* @param world The world this IShieldable is on.
* @param x This IShieldable's X Coordinate.
* @param y This IShieldable's Y Coordinate.
* @param z This IShieldable's Z Coordinate.
* @param px The X Coordinate of the shield emitter raising a shield on this block.
* @param py The Y Coordinate of the shield emitter raising a shield on this block.
* @param pz The Z Coordinate of the shield emitter raising a shield on this block.
* @param px The X Coordinate of the shield controller in charge of the shield on this block.
* @param py The Y Coordinate of the shield controller in charge of the shield on this block.
* @param pz The Z Coordinate of the shield controller in charge of the shield on this block.
*/
public void onShield(World world, int x, int y, int z, int px, int py, int pz);

View File

@ -1,6 +1,7 @@
package stargatetech2.api.shields;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityMinecart;
@ -13,21 +14,22 @@ import net.minecraft.nbt.NBTTagCompound;
public class ShieldPermissions {
// Permission Flags
public static final int PERM_PLAYER = 0x01;
public static final int PERM_VILLAGER = 0x02;
public static final int PERM_ANIMAL = 0x04;
public static final int PERM_MONSTER = 0x08;
public static final int PERM_MINECART = 0x10;
public static final int PERM_FRIEND = 0x01;
public static final int PERM_PLAYER = 0x02;
public static final int PERM_VILLAGER = 0x04;
public static final int PERM_ANIMAL = 0x08;
public static final int PERM_MONSTER = 0x10;
public static final int PERM_VESSEL = 0x20;
private int permValue = 0;
private ArrayList<String> playerExceptions = new ArrayList<String>();
private LinkedList<String> playerExceptions = new LinkedList<String>();
/**
* @return A default ShieldPermissions object.
*/
public static ShieldPermissions getDefault(){
ShieldPermissions perm = new ShieldPermissions();
perm.allow(PERM_PLAYER);
perm.allow(PERM_FRIEND | PERM_PLAYER);
return perm;
}
@ -68,7 +70,7 @@ public class ShieldPermissions {
* @return A list of strings containing the names of all the players
* who currently are exceptions to the player permission setting.
*/
public ArrayList<String> getExceptionList(){
public List<String> getExceptionList(){
return playerExceptions;
}
@ -96,7 +98,7 @@ public class ShieldPermissions {
}else if(entity instanceof EntityMob){
allow = hasBit(PERM_MONSTER);
}else if(entity instanceof EntityMinecart){
allow = hasBit(PERM_MINECART);
allow = hasBit(PERM_VESSEL);
}
if(allow && entity.riddenByEntity != null && doDismount && entity.worldObj.isRemote == false){
if(!isEntityAllowed(entity.riddenByEntity, true)){
@ -141,7 +143,7 @@ public class ShieldPermissions {
if(nbt != null){
int exceptions = nbt.getInteger("exceptions");
permissions.permValue = nbt.getInteger("permValue");
permissions.playerExceptions = new ArrayList<String>(exceptions);
permissions.playerExceptions = new LinkedList<String>();
for(int i = 0; i < exceptions; i++){
permissions.setPlayerException(nbt.getString("pex" + i));
}

View File

@ -1,8 +1,13 @@
local hookInterval = 100
local deadline = math.huge
local hitDeadline = false
local function checkDeadline()
if computer.realTime() > deadline then
debug.sethook(coroutine.running(), checkDeadline, "", 1)
if not hitDeadline then
deadline = deadline + 0.5
end
hitDeadline = true
error("too long without yielding", 0)
end
end
@ -570,6 +575,7 @@ local function main()
while true do
deadline = computer.realTime() + timeout -- timeout global is set by host
hitDeadline = false
debug.sethook(co, checkDeadline, "", hookInterval)
local result = table.pack(coroutine.resume(co, table.unpack(args, 1, args.n)))
if not result[1] then
@ -584,4 +590,4 @@ end
-- JNLua converts the coroutine to a string immediately, so we can't get the
-- traceback later. Because of that we have to do the error handling here.
return pcall(main)
return pcall(main)

View File

@ -130,7 +130,7 @@ if #args == 0 and (io.input() == io.stdin or options.i) and not options.c then
end
else
-- execute command.
local result = table.pack(execute(table.unpack(args)))
local result = table.pack(execute(...))
if not result[1] then
error(result[2])
end

View File

@ -34,6 +34,8 @@ Skynet
Terminator T-1000
Terminator T-800
Wheatley
Rosie
Uniblab
# Perry Rhodan Robots, definitly not all...
Anson Argyris

View File

@ -4,7 +4,6 @@ import li.cil.oc.client.Textures
import li.cil.oc.util.{RenderState, PackedColor}
import li.cil.oc.{OpenComputers, Settings}
import net.minecraft.client.renderer.GLAllocation
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.texture.TextureManager
import org.lwjgl.opengl.GL11
import scala.io.Source
@ -46,7 +45,6 @@ object MonospaceFontRenderer {
val s = Settings.get.fontCharScale
val dw = charWidth * s - charWidth
val dh = charHeight * s - charHeight
val t = Tessellator.instance
// Now create lists for all printable chars.
for (index <- 1 until 0xFF) {
val x = (index - 1) % cols
@ -54,12 +52,16 @@ object MonospaceFontRenderer {
val u = x * uStep
val v = y * vStep
GL11.glNewList(charLists + index, GL11.GL_COMPILE)
t.startDrawingQuads()
t.addVertexWithUV(-dw, charHeight * s, 0, u, v + vSize)
t.addVertexWithUV(charWidth * s, charHeight * s, 0, u + uSize, v + vSize)
t.addVertexWithUV(charWidth * s, -dh, 0, u + uSize, v)
t.addVertexWithUV(-dw, -dh, 0, u, v)
t.draw()
GL11.glBegin(GL11.GL_QUADS)
GL11.glTexCoord2d(u, v + vSize)
GL11.glVertex3d(-dw, charHeight * s, 0)
GL11.glTexCoord2d(u + uSize, v + vSize)
GL11.glVertex3d(charWidth * s, charHeight * s, 0)
GL11.glTexCoord2d(u + uSize, v)
GL11.glVertex3d(charWidth * s, -dh, 0)
GL11.glTexCoord2d(u, v)
GL11.glVertex3d(-dw, -dh, 0)
GL11.glEnd()
GL11.glTranslatef(charWidth, 0, 0)
GL11.glEndList()
}

View File

@ -86,13 +86,12 @@ class ClassTransformer extends IClassTransformer {
def ensureStargateTechCompatibility(basicClass: Array[Byte]): Array[Byte] = {
if (!Mods.StargateTech2.isAvailable) {
return basicClass
// No SGT2 or version is too old, abstract bus API doesn't exist.
val classNode = newClassNode(basicClass)
classNode.interfaces.remove("stargatetech2/api/bus/IBusDevice")
writeClass(classNode)
}
// Version of SGT2 is too old, abstract bus API doesn't exist.
val classNode = newClassNode(basicClass)
classNode.interfaces.remove("stargatetech2/api/bus/IBusDevice")
writeClass(classNode)
else basicClass
}
def injectEnvironmentImplementation(classNode: ClassNode, basicClass: Array[Byte]): Array[Byte] = {

View File

@ -319,7 +319,7 @@ class Player(val robot: tileentity.Robot) extends EntityPlayer(robot.world, Play
})
}
private def isItemUseAllowed(stack: ItemStack) = {
private def isItemUseAllowed(stack: ItemStack) = stack == null || {
(Settings.get.allowUseItemsWithDuration || stack.getMaxItemUseDuration <= 0) &&
(!PortalGun.isPortalGun(stack) || PortalGun.isStandardPortalGun(stack)) &&
!stack.isItemEqual(new ItemStack(Items.lead))

View File

@ -233,7 +233,8 @@ class Robot(val robot: tileentity.Robot) extends ManagedComponent {
Iterable(checkSideForFace(args, 1, facing))
}
else {
ForgeDirection.VALID_DIRECTIONS.filter(_ != facing.getOpposite).toIterable
// Always try the direction we're looking first.
Iterable(facing) ++ ForgeDirection.VALID_DIRECTIONS.filter(side => side != facing && side != facing.getOpposite).toIterable
}
val sneaky = args.isBoolean(2) && args.checkBoolean(2)
val stack = player.robotInventory.selectedItemStack
@ -339,7 +340,8 @@ class Robot(val robot: tileentity.Robot) extends ManagedComponent {
Iterable(checkSideForFace(args, 1, facing))
}
else {
ForgeDirection.VALID_DIRECTIONS.filter(_ != facing.getOpposite).toIterable
// Always try the direction we're looking first.
Iterable(facing) ++ ForgeDirection.VALID_DIRECTIONS.filter(side => side != facing && side != facing.getOpposite).toIterable
}
val sneaky = args.isBoolean(2) && args.checkBoolean(2)
@ -420,7 +422,8 @@ class Robot(val robot: tileentity.Robot) extends ManagedComponent {
Iterable(checkSideForFace(args, 1, facing))
}
else {
ForgeDirection.VALID_DIRECTIONS.filter(_ != facing.getOpposite).toIterable
// Always try the direction we're looking first.
Iterable(facing) ++ ForgeDirection.VALID_DIRECTIONS.filter(side => side != facing && side != facing.getOpposite).toIterable
}
val sneaky = args.isBoolean(2) && args.checkBoolean(2)
val duration =

View File

@ -5,13 +5,13 @@ import li.cil.oc.api.driver.Slot
import li.cil.oc.server.component
import li.cil.oc.util.mods.Mods
import net.minecraft.item.ItemStack
import net.minecraft.tileentity.{TileEntity => MCTileEntity}
import net.minecraft.tileentity.TileEntity
import stargatetech2.api.bus.IBusDevice
object AbstractBusCard extends Item {
override def worksWith(stack: ItemStack) = isOneOf(stack, Items.abstractBus)
override def createEnvironment(stack: ItemStack, container: MCTileEntity) = if (Mods.StargateTech2.isAvailable) container match {
override def createEnvironment(stack: ItemStack, container: TileEntity) = if (Mods.StargateTech2.isAvailable) container match {
case device: IBusDevice => new component.AbstractBus(device)
case _ => null
}

View File

@ -94,7 +94,7 @@ trait Buffered extends OutputStreamFileSystem {
FileUtils.deleteQuietly(childFile)
childFile.createNewFile()
val out = new io.FileOutputStream(childFile).getChannel
val in = java.nio.channels.Channels.newChannel(openInputStream(childPath).get)
val in = openInputChannel(childPath).get
out.transferFrom(in, 0, Long.MaxValue)
out.close()
in.close()

View File

@ -35,16 +35,26 @@ class CompositeReadOnlyFileSystem(factories: mutable.LinkedHashMap[String, Calla
override def lastModified(path: String) = findFileSystem(path).fold(0L)(_.lastModified(path))
override def list(path: String) = parts.values.foldLeft(Array.empty[String])((acc, fs) => {
if (fs.exists(path)) try {
val l = fs.list(path)
if (l != null) acc ++ l else acc
}
catch {
case _: Throwable => acc
}
else acc
})
override def list(path: String) = if (isDirectory(path)) {
parts.values.foldLeft(mutable.Set.empty[String])((acc, fs) => {
if (fs.exists(path)) try {
val l = fs.list(path)
if (l != null) for (e <- l) {
val f = e.stripSuffix("/")
val d = f + "/"
// Avoid duplicates and always only use the latest entry.
acc -= f
acc -= d
acc += e
}
}
catch {
case _: Throwable =>
}
acc
}).toArray
}
else null
// ----------------------------------------------------------------------- //

View File

@ -25,8 +25,8 @@ class ComputerCraftFileSystem(val mount: IMount) extends InputStreamFileSystem {
// ----------------------------------------------------------------------- //
protected def openInputStream(path: String) = try {
Some(mount.openForRead(path))
protected def openInputChannel(path: String) = try {
Some(new InputStreamChannel(mount.openForRead(path)))
} catch {
case _: Throwable => None
}

View File

@ -43,6 +43,23 @@ trait FileInputStreamFileSystem extends InputStreamFileSystem {
// ----------------------------------------------------------------------- //
override protected def openInputStream(path: String): Option[io.InputStream] =
Some(new io.FileInputStream(new io.File(root, path)))
override protected def openInputChannel(path: String) = Some(new FileChannel(new io.File(root, path)))
protected class FileChannel(file: io.File) extends InputChannel {
val channel = new io.RandomAccessFile(file, "r").getChannel
override def position(newPosition: Long) = {
channel.position(newPosition)
channel.position
}
override def position = channel.position
override def close() = channel.close()
override def isOpen = channel.isOpen
override def read(dst: Array[Byte]) = channel.read(java.nio.ByteBuffer.wrap(dst))
}
}

View File

@ -1,11 +1,13 @@
package li.cil.oc.server.fs
import java.io.{FileNotFoundException, IOException, InputStream}
import java.io.{FileNotFoundException, IOException}
import li.cil.oc.api
import li.cil.oc.api.fs.Mode
import net.minecraft.nbt.{NBTTagList, NBTTagCompound}
import net.minecraftforge.common.util.Constants.NBT
import scala.collection.mutable
import java.nio.channels.ReadableByteChannel
import java.nio.ByteBuffer
trait InputStreamFileSystem extends api.fs.FileSystem {
private val handles = mutable.Map.empty[Int, Handle]
@ -26,9 +28,9 @@ trait InputStreamFileSystem extends api.fs.FileSystem {
override def open(path: String, mode: Mode) = this.synchronized(if (mode == Mode.Read && exists(path) && !isDirectory(path)) {
val handle = Iterator.continually((Math.random() * Int.MaxValue).toInt + 1).filterNot(handles.contains).next()
openInputStream(path) match {
case Some(stream) =>
handles += handle -> new Handle(this, handle, path, stream)
openInputChannel(path) match {
case Some(channel) =>
handles += handle -> new Handle(this, handle, path, channel)
handle
case _ => throw new FileNotFoundException()
}
@ -50,10 +52,10 @@ trait InputStreamFileSystem extends api.fs.FileSystem {
val handle = handleNbt.getInteger("handle")
val path = handleNbt.getString("path")
val position = handleNbt.getLong("position")
openInputStream(path) match {
case Some(stream) =>
val fileHandle = new Handle(this, handle, path, stream)
fileHandle.position = stream.skip(position) // May be != position if the file changed since we saved.
openInputChannel(path) match {
case Some(channel) =>
val fileHandle = new Handle(this, handle, path, channel)
channel.position(position)
handles += handle -> fileHandle
case _ => // The source file seems to have disappeared since last time.
}
@ -63,7 +65,7 @@ trait InputStreamFileSystem extends api.fs.FileSystem {
override def save(nbt: NBTTagCompound) = this.synchronized {
val handlesNbt = new NBTTagList()
for (file <- handles.values) {
assert(!file.isClosed)
assert(file.channel.isOpen)
val handleNbt = new NBTTagCompound()
handleNbt.setInteger("handle", file.handle)
handleNbt.setString("path", file.path)
@ -75,34 +77,73 @@ trait InputStreamFileSystem extends api.fs.FileSystem {
// ----------------------------------------------------------------------- //
protected def openInputStream(path: String): Option[InputStream]
protected def openInputChannel(path: String): Option[InputChannel]
protected trait InputChannel extends ReadableByteChannel {
def isOpen: Boolean
def close()
def position: Long
def position(newPosition: Long): Long
def read(dst: Array[Byte]): Int
override def read(dst: ByteBuffer) = {
if (dst.hasArray) {
read(dst.array())
}
else {
val count = dst.limit - dst.position
val buffer = new Array[Byte](count)
val n = read(buffer)
dst.put(buffer, 0, n)
n
}
}
}
protected class InputStreamChannel(val inputStream: java.io.InputStream) extends InputChannel {
var isOpen = true
private var position_ = 0L
override def close() = if (isOpen) {
isOpen = false
inputStream.close()
}
override def position = position_
override def position(newPosition: Long) = {
inputStream.reset()
position_ = inputStream.skip(newPosition)
position_
}
override def read(dst: Array[Byte]) = {
val read = inputStream.read(dst)
position_ += read
read
}
}
// ----------------------------------------------------------------------- //
private class Handle(val owner: InputStreamFileSystem, val handle: Int, val path: String, val stream: InputStream) extends api.fs.Handle {
var isClosed = false
var position = 0L
private class Handle(val owner: InputStreamFileSystem, val handle: Int, val path: String, val channel: InputChannel) extends api.fs.Handle {
override def position = channel.position
override def length = owner.size(path)
override def close() = if (!isClosed) {
isClosed = true
override def close() = if (channel.isOpen) {
owner.handles -= handle
stream.close()
channel.close()
}
override def read(into: Array[Byte]) = {
val read = stream.read(into)
if (read >= 0)
position += read
read
}
override def read(into: Array[Byte]) = channel.read(into)
override def seek(to: Long) = {
stream.reset()
position = stream.skip(to)
position
}
override def seek(to: Long) = channel.position(to)
override def write(value: Array[Byte]) = throw new IOException("bad file descriptor")
}

View File

@ -98,9 +98,9 @@ trait VirtualFileSystem extends OutputStreamFileSystem {
// ----------------------------------------------------------------------- //
protected def openInputStream(path: String) =
protected def openInputChannel(path: String) =
root.get(segments(path)) match {
case Some(obj: VirtualFile) => obj.openInputStream()
case Some(obj: VirtualFile) => obj.openInputStream().map(new InputStreamChannel(_))
case _ => None
}

View File

@ -58,8 +58,8 @@ class ZipFileInputStreamFileSystem(private val archive: ArchiveDirectory) extend
// ----------------------------------------------------------------------- //
override protected def openInputStream(path: String) = ZipFileInputStreamFileSystem.synchronized {
entry(path).map(_.openStream())
override protected def openInputChannel(path: String) = ZipFileInputStreamFileSystem.synchronized {
entry(path).map(entry => new InputStreamChannel(entry.openStream()))
}
// ----------------------------------------------------------------------- //

View File

@ -220,12 +220,12 @@ object LuaStateFactory {
case 0 => lua.pushNumber(random.nextDouble())
case 1 =>
val u = lua.checkNumber(1).toInt
lua.checkArg(1, 1 < u, "interval is empty")
lua.checkArg(1, 1 <= u, "interval is empty")
lua.pushInteger(1 + random.nextInt(u))
case 2 =>
val l = lua.checkNumber(1).toInt
val u = lua.checkNumber(2).toInt
lua.checkArg(1, l < u, "interval is empty")
lua.checkArg(1, l <= u, "interval is empty")
lua.pushInteger(l + random.nextInt(u - (l - 1)))
case _ => throw new IllegalArgumentException("wrong number of arguments")
}