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

# Conflicts:
#	src/main/scala/li/cil/oc/server/component/InternetCard.scala
This commit is contained in:
Florian Nücke 2016-06-25 13:19:57 +02:00
commit ba0145c5b7
9 changed files with 95 additions and 29 deletions

View File

@ -31,13 +31,16 @@ if options.setlabel then
end
if options.setboot then
computer.setBootAddress(options.target.dev.address)
local address = options.target.dev.address
if computer.setBootAddress(address) then
write("Boot address set to " .. address)
end
end
if options.reboot then
write("Reboot now? [Y/n] ")
local result = read()
if not result or result == "" or result:sub(1, 1):lower() == "y" then
local result = read() or "n"
if result:sub(1, 1):lower() == "y" then
write("\nRebooting now!\n")
computer.shutdown(true)
end

View File

@ -284,7 +284,7 @@ local function displayDirList(dirs)
end
end
end
local tr,cp={},{path=os.getenv("PWD")}
local tr,cp={},{path=shell.getWorkingDirectory()}
for _,dir in ipairs(dirsArg) do
local path = shell.resolve(dir)
if not fs.exists(path) then

View File

@ -44,7 +44,7 @@ local function load(name, args)
return nil, reason
end
function unload(name)
function rc.unload(name)
rc.loaded[name] = nil
end
@ -60,15 +60,15 @@ local function rawRunCommand(conf, name, cmd, args, ...)
end
return true
elseif type(result[cmd]) == "function" then
res, what = xpcall(result[cmd], debug.traceback, ...)
if res then
result, what = xpcall(result[cmd], debug.traceback, ...)
if result then
return true
end
elseif cmd == "restart" and type(result["stop"]) == "function" and type(result["start"]) == "function" then
res, what = xpcall(result["stop"], debug.traceback, ...)
if res then
res, what = xpcall(result["start"], debug.traceback, ...)
if res then
result, what = xpcall(result["stop"], debug.traceback, ...)
if result then
result, what = xpcall(result["start"], debug.traceback, ...)
if result then
return true
end
end

View File

@ -73,7 +73,7 @@ function buffer:read(...)
if computer.uptime() > timeout then
error("timeout")
end
local result, reason = self.stream:read(self.bufferSize)
local result, reason = self.stream:read(math.max(1,self.bufferSize))
if result then
self.bufferRead = self.bufferRead .. result
return self

View File

@ -61,15 +61,13 @@ end
local delay_data = {}
local delay_tools = setmetatable({},{__mode="v"})
package.delay_data = delay_data
function delay_data.__index(tbl,key)
delay_data.lookup = delay_data.lookup or loadfile("/lib/tools/delayLookup.lua")
return delay_data.lookup(delay_data, tbl, key)
end
delay_data.__pairs = delay_data.__index -- nil key acts like pairs
function delaySearcher(module)
local function delaySearcher(module)
if not delayed[module] then
return "\tno field package.delayed['" .. module .. "']"
end

View File

@ -367,7 +367,7 @@ function plib.popen(prog, mode, env)
pm.pco=plib.internal.create(pm.root)
local pfd = require("buffer").new(mode, pipeStream.new(pm))
pfd:setvbuf("no", nil) -- 2nd are to read chunk size
pfd:setvbuf("no", 0) -- 2nd are to read chunk size
-- popen processes start on create (which is LAME :P)
pfd.stream:resume()

View File

@ -12,8 +12,8 @@ sh.internal = {}
-- --[[@@]] are not just comments, but custom annotations for delayload methods.
-- See package.lua and the api wiki for more information
function isWordOf(w, vs) return w and #w == 1 and not w[1].qr and tx.first(vs,{{w[1].txt}}) ~= nil end
function isWord(w,v) return isWordOf(w,{v}) end
local function isWordOf(w, vs) return w and #w == 1 and not w[1].qr and tx.first(vs,{{w[1].txt}}) ~= nil end
local function isWord(w,v) return isWordOf(w,{v}) end
local local_env = {event=event,fs=fs,process=process,shell=shell,term=term,text=text,tx=tx,unicode=unicode,isWordOf=isWordOf,isWord=isWord}
-------------------------------------------------------------------------------
@ -424,7 +424,7 @@ function --[[@delayloaded-start@]] sh.internal.buildPipeChain(threads)
local pipe
if i < #threads then
pipe = require("buffer").new("rw", sh.internal.newMemoryStream())
pipe:setvbuf("no")
pipe:setvbuf("no", 0)
-- buffer close flushes the buffer, but we have no buffer
-- also, when the buffer is closed, read and writes don't pass through
-- simply put, we don't want buffer:close
@ -461,7 +461,7 @@ function --[[@delayloaded-start@]] sh.internal.glob(glob_pattern)
end
local is_abs = glob_pattern:sub(1, 1) == "/"
local root = is_abs and '' or shell.getWorkingDirectory()
local root = is_abs and '' or shell.getWorkingDirectory():gsub("([^/])$","%1/")
local paths = {is_abs and "/" or ''}
local relative_separator = ''

View File

@ -10,6 +10,7 @@ import net.minecraftforge.fml.common.event.FMLInterModComms.IMCEvent
import net.minecraftforge.fml.common.event._
import net.minecraftforge.fml.common.network.FMLEventChannel
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
@Mod(modid = OpenComputers.ID, name = OpenComputers.Name,
version = OpenComputers.Version,
@ -21,7 +22,9 @@ object OpenComputers {
final val Version = "@VERSION@"
var log = LogManager.getLogger(Name)
def log = logger.getOrElse(LogManager.getLogger(Name))
var logger: Option[Logger] = None
@SidedProxy(clientSide = "li.cil.oc.client.Proxy", serverSide = "li.cil.oc.server.Proxy")
var proxy: Proxy = null
@ -30,7 +33,7 @@ object OpenComputers {
@EventHandler
def preInit(e: FMLPreInitializationEvent) {
log = e.getModLog
logger = Option(e.getModLog)
proxy.preInit(e)
OpenComputers.log.info("Done with pre init phase.")
}

View File

@ -7,17 +7,20 @@ import java.io.InputStream
import java.io.OutputStreamWriter
import java.net._
import java.nio.ByteBuffer
import java.nio.channels.SelectionKey
import java.nio.channels.Selector
import java.nio.channels.SocketChannel
import java.util
import java.util.concurrent.Callable
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.ExecutionException
import java.util.concurrent.Future
import java.util.UUID
import java.util.concurrent._
import li.cil.oc.Constants
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api.Network
import li.cil.oc.api.driver.DeviceInfo
import li.cil.oc.api.driver.DeviceInfo.DeviceAttribute
import li.cil.oc.api.driver.DeviceInfo.DeviceClass
import li.cil.oc.Settings
import li.cil.oc.api.Network
import li.cil.oc.api.driver.DeviceInfo
import li.cil.oc.api.machine.Arguments
@ -183,6 +186,41 @@ object InternetCard {
def close(): Unit
}
object TCPNotifier extends Thread {
private val selector = Selector.open()
private val toAccept = new ConcurrentLinkedQueue[(SocketChannel, () => Unit)]
override def run(): Unit = {
while (true) {
try {
Stream.continually(toAccept.poll).takeWhile(_ != null).foreach({
case (channel: SocketChannel, action: (() => Unit)) =>
channel.register(selector, SelectionKey.OP_READ, action)
})
selector.select()
import scala.collection.JavaConversions._
val selectedKeys = selector.selectedKeys
selectedKeys.filter(_.isReadable).foreach(key => {
key.cancel()
key.attachment().asInstanceOf[() => Unit].apply()
})
} catch {
case e: IOException =>
OpenComputers.log.error("Error in TCP selector loop.", e)
}
}
}
def add(e: (SocketChannel, () => Unit)) {
toAccept.offer(e)
selector.wakeup()
}
}
TCPNotifier.start()
class TCPSocket extends AbstractValue with Closable {
def this(owner: InternetCard, uri: URI, port: Int) {
this()
@ -196,9 +234,25 @@ object InternetCard {
private var address: Future[InetAddress] = null
private var channel: SocketChannel = null
private var isAddressResolved = false
private val id = UUID.randomUUID()
private def setupSelector() {
TCPNotifier.add((channel, () => {
owner match {
case Some(internetCard) =>
internetCard.node.sendToVisible("computer.signal", "internet_ready", internetCard.node.address(), id.toString)
case _ =>
channel.close()
}
}))
}
@Callback(doc = """function():boolean -- Ensures a socket is connected. Errors if the connection failed.""")
def finishConnect(context: Context, args: Arguments): Array[AnyRef] = this.synchronized(result(checkConnected()))
def finishConnect(context: Context, args: Arguments): Array[AnyRef] = {
val r = this.synchronized(result(checkConnected()))
setupSelector()
r
}
@Callback(doc = """function([n:number]):string -- Tries to read data from the socket stream. Returns the read byte array.""")
def read(context: Context, args: Arguments): Array[AnyRef] = this.synchronized {
@ -207,7 +261,10 @@ object InternetCard {
val buffer = ByteBuffer.allocate(n)
val read = channel.read(buffer)
if (read == -1) result(Unit)
else result(buffer.array.view(0, read).toArray)
else {
setupSelector()
result(buffer.array.view(0, read).toArray)
}
}
else result(Array.empty[Byte])
}
@ -227,6 +284,11 @@ object InternetCard {
null
}
@Callback(direct = true, doc = """function():string -- Returns connection ID.""")
def id(context: Context, args: Arguments): Array[AnyRef] = this.synchronized {
result(id.toString)
}
override def dispose(context: Context): Unit = {
super.dispose(context)
close()