defaulting to standard lua string functions and making unicode ones available prefixed with a u (uchar, ulen, usub, ureverse); fixed event erroring being weird; fixed wrong case check order in kernel; fixed error when netsplitting a component from a computer; fixed localization for disk drive; config for name to provide when running command in command block; increased range of keyboards; adapter blocks re-use the same addresses for the blocks attached to them to avoid computers losing track of those nodes after reloading

This commit is contained in:
Florian Nücke 2013-10-19 15:55:59 +02:00
parent 87aa1f44a9
commit ccf53d6b85
20 changed files with 187 additions and 133 deletions

View File

@ -1,9 +1,10 @@
oc.block.Adapter.name=Adapter oc.block.Adapter.name=Adapter
oc.block.Computer.name=Computer oc.block.Computer.name=Computer
oc.block.DiskDrive.name=Diskettenlaufwerk
oc.block.Keyboard.name=Tastatur oc.block.Keyboard.name=Tastatur
oc.block.Screen.name=Bildschirm oc.block.Screen.name=Bildschirm
oc.container.computer=Computer oc.container.Computer=Computer
oc.container.disk_drive=Diskettenlaufwerk oc.container.DiskDrive=Diskettenlaufwerk
oc.item.Disk.name=Diskette oc.item.Disk.name=Diskette
oc.item.GraphicsCard.name=Grafikkarte oc.item.GraphicsCard.name=Grafikkarte
oc.item.HardDiskDrive2m.name=Festplatte (2MB) oc.item.HardDiskDrive2m.name=Festplatte (2MB)

View File

@ -1,9 +1,10 @@
oc.block.Adapter.name=Adapter oc.block.Adapter.name=Adapter
oc.block.Computer.name=Computer oc.block.Computer.name=Computer
oc.block.DiskDrive.name=Disk Drive
oc.block.Keyboard.name=Keyboard oc.block.Keyboard.name=Keyboard
oc.block.Screen.name=Screen oc.block.Screen.name=Screen
oc.container.computer=Computer oc.container.Computer=Computer
oc.container.disk_drive=Disk Drive oc.container.DiskDrive=Disk Drive
oc.item.Disk.name=Floppy Disk oc.item.Disk.name=Floppy Disk
oc.item.GraphicsCard.name=Graphics Card oc.item.GraphicsCard.name=Graphics Card
oc.item.HardDiskDrive2m.name=Hard Disk Drive (2MB) oc.item.HardDiskDrive2m.name=Hard Disk Drive (2MB)

View File

@ -181,7 +181,7 @@ function driver.filesystem.isDirectory(path)
if node.fs and rest then if node.fs and rest then
return send(node.fs, "fs.isDirectory", rest) return send(node.fs, "fs.isDirectory", rest)
else else
return not rest or rest:len() == 0 return not rest or rest:ulen() == 0
end end
end end
@ -339,12 +339,12 @@ function file:read(...)
local function readBytesOrChars(n) local function readBytesOrChars(n)
local len, sub local len, sub
if self.mode == "r" then if self.mode == "r" then
len = string.len len = string.ulen
sub = string.sub sub = string.usub
else else
assert(self.mode == "rb") assert(self.mode == "rb")
len = rawlen len = rawlen
sub = string.bsub sub = string.sub
end end
local buffer = "" local buffer = ""
repeat repeat
@ -370,8 +370,8 @@ function file:read(...)
while true do while true do
local l = self.buffer:find("\n", start, true) local l = self.buffer:find("\n", start, true)
if l then if l then
local result = self.buffer:bsub(1, l + (chop and -1 or 0)) local result = self.buffer:sub(1, l + (chop and -1 or 0))
self.buffer = self.buffer:bsub(l + 1) self.buffer = self.buffer:sub(l + 1)
return result return result
else else
start = #self.buffer start = #self.buffer
@ -405,10 +405,10 @@ function file:read(...)
if type(format) == "number" then if type(format) == "number" then
return readBytesOrChars(format) return readBytesOrChars(format)
else else
if type(format) ~= "string" or format:sub(1, 1) ~= "*" then if type(format) ~= "string" or format:usub(1, 1) ~= "*" then
error("bad argument #" .. n .. " (invalid option)") error("bad argument #" .. n .. " (invalid option)")
end end
format = format:sub(2, 2) format = format:usub(2, 2)
if format == "n" then if format == "n" then
--[[ TODO ]] --[[ TODO ]]
error("not implemented") error("not implemented")
@ -529,11 +529,11 @@ function file:write(...)
end end
end end
if l then if l then
result, reason = self.stream:write(arg:bsub(1, l)) result, reason = self.stream:write(arg:sub(1, l))
if not result then if not result then
return nil, reason return nil, reason
end end
arg = arg:bsub(l + 1) arg = arg:sub(l + 1)
end end
if #arg > self.bufferSize then if #arg > self.bufferSize then
result, reason = self.stream:write(arg) result, reason = self.stream:write(arg)

View File

@ -100,8 +100,6 @@ local sandbox = {
}, },
string = { string = {
breverse = string.breverse,
bsub = string.bsub,
byte = string.byte, byte = string.byte,
char = string.char, char = string.char,
dump = string.dump, dump = string.dump,
@ -115,7 +113,11 @@ local sandbox = {
rep = string.rep, rep = string.rep,
reverse = string.reverse, reverse = string.reverse,
sub = string.sub, sub = string.sub,
upper = string.upper upper = string.upper,
uchar = string.uchar,
ulen = string.ulen,
ureverse = string.breverse,
usub = string.bsub
}, },
table = { table = {
@ -180,12 +182,12 @@ local function main(args)
debug.sethook(co, checkDeadline, "", 10000) debug.sethook(co, checkDeadline, "", 10000)
end end
local result = table.pack(coroutine.resume(co, table.unpack(args, 1, args.n))) local result = table.pack(coroutine.resume(co, table.unpack(args, 1, args.n)))
if coroutine.status(co) == "dead" then if not result[1] then
error(result[2] or "unknown error", 0)
elseif coroutine.status(co) == "dead" then
error("computer stopped unexpectedly", 0) error("computer stopped unexpectedly", 0)
elseif result[1] then
args = table.pack(coroutine.yield(result[2])) -- system yielded value
else else
error(result[2], 0) args = table.pack(coroutine.yield(result[2])) -- system yielded value
end end
end end
end end
@ -267,7 +269,8 @@ do
return debug.traceback(msg, 2) return debug.traceback(msg, 2)
end) end)
if not result then if not result then
print("Failed initializing driver '" .. name .. "': " .. reason) print("Failed initializing driver '" .. name .. "': " ..
(reason or "unknown error"))
end end
end end
end end

View File

@ -24,8 +24,18 @@ function component.primary(componentType, ...)
local args = table.pack(...) local args = table.pack(...)
if args.n > 0 then if args.n > 0 then
checkArg(2, args[1], "string", "nil") checkArg(2, args[1], "string", "nil")
local address
if args[1] ~= nil then
for c in component.list(componentType) do
if c:usub(1, args[1]:ulen()) == args[1] then
address = c
break
end
end
assert(address, "no such component")
end
local wasAvailable = component.isAvailable(componentType) local wasAvailable = component.isAvailable(componentType)
primaries[componentType] = args[1] primaries[componentType] = address
if not wasAvailable and component.isAvailable(componentType) then if not wasAvailable and component.isAvailable(componentType) then
event.fire("component_available", componentType) event.fire("component_available", componentType)
elseif wasAvailable and not component.isAvailable(componentType) then elseif wasAvailable and not component.isAvailable(componentType) then
@ -45,6 +55,9 @@ end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
local function onComponentAdded(_, address) local function onComponentAdded(_, address)
if components[address] then
return false -- cancel this event, it is invalid
end
local componentType = driver.componentType(address) local componentType = driver.componentType(address)
components[address] = componentType components[address] = componentType
if not component.isAvailable(componentType) then if not component.isAvailable(componentType) then
@ -53,16 +66,15 @@ local function onComponentAdded(_, address)
end end
local function onComponentRemoved(_, address) local function onComponentRemoved(_, address)
if not components[address] then
return false -- cancel this event, it is invalid
end
local componentType = component.type(address) local componentType = component.type(address)
components[address] = nil components[address] = nil
if primaries[componentType] == address then if primaries[componentType] == address then
component.primary(componentType, nil) component.primary(componentType, nil)
for address in component.list() do address = component.list(componentType)()
if component.type(address) == componentType then component.primary(componentType, address)
component.primary(componentType, address)
return
end
end
end end
end end

View File

@ -2,14 +2,18 @@ local listeners = {}
local weakListeners = {} local weakListeners = {}
local timers = {} local timers = {}
local function listenersFor(name, weak) local function listenersFor(name, weak, create)
checkArg(1, name, "string") checkArg(1, name, "string")
if weak then if weak then
weakListeners[name] = weakListeners[name] or setmetatable({}, {__mode = "v"}) if not weakListeners[name] and create then
return weakListeners[name] weakListeners[name] = weakListeners[name] or setmetatable({}, {__mode = "v"})
end
return weakListeners[name] or {}
else else
listeners[name] = listeners[name] or {} if not listeners[name] and create then
return listeners[name] listeners[name] = listeners[name] or {}
end
return listeners[name] or {}
end end
end end
@ -28,16 +32,20 @@ function event.fire(name, ...)
-- timer check (for example if we had no signal in event.wait()). -- timer check (for example if we had no signal in event.wait()).
if name then if name then
checkArg(1, name, "string") checkArg(1, name, "string")
for _, callback in ipairs(listenersFor(name, false)) do local function copy(listA, listB)
local result, message = xpcall(callback, event.error, name, ...) local result = {}
if not result and message then for _, v in ipairs(listA) do table.insert(result, v) end
error(message, 0) for _, v in ipairs(listB) do table.insert(result, v) end
end return result
end end
for _, callback in ipairs(listenersFor(name, true)) do -- Copy the listener lists because they may be changed by callbacks.
local listeners = copy(listenersFor(name, false), listenersFor(name, true))
for _, callback in ipairs(listeners) do
local result, message = xpcall(callback, event.error, name, ...) local result, message = xpcall(callback, event.error, name, ...)
if not result and message then if not result and message then -- only if handler returned something.
error(message, 0) error(message, 0)
elseif result and message == false then
break
end end
end end
end end
@ -50,7 +58,7 @@ function event.fire(name, ...)
end end
for _, callback in ipairs(elapsed) do for _, callback in ipairs(elapsed) do
local result, message = xpcall(callback, event.error) local result, message = xpcall(callback, event.error)
if not result and message then if not result and message then -- only if handler returned something.
error(message, 0) error(message, 0)
end end
end end
@ -71,7 +79,7 @@ end
function event.listen(name, callback, weak) function event.listen(name, callback, weak)
checkArg(2, callback, "function") checkArg(2, callback, "function")
local list = listenersFor(name, weak) local list = listenersFor(name, weak, true)
for i = 1, #list do for i = 1, #list do
if list[i] == callback then if list[i] == callback then
return return

View File

@ -28,9 +28,9 @@ local function onComponentAdded(_, address)
address ~= os.romAddress() and address ~= os.romAddress() and
address ~= os.tmpAddress() address ~= os.tmpAddress()
then then
local name = address:sub(1, 3) local name = address:usub(1, 3)
repeat repeat
name = address:sub(1, name:len() + 1) name = address:usub(1, name:ulen() + 1)
until not fs.exists("/mnt/" .. name) until not fs.exists("/mnt/" .. name)
fs.mount(address, "/mnt/" .. name) fs.mount(address, "/mnt/" .. name)
if isAutorunEnabled then if isAutorunEnabled then

View File

@ -47,7 +47,7 @@ function term.cursorBlink(enabled)
if not cursorBlink then if not cursorBlink then
cursorBlink = event.interval(0.5, toggleBlink) cursorBlink = event.interval(0.5, toggleBlink)
cursorBlink.state = false cursorBlink.state = false
cursorBlink.solid = string.char(0x2588) -- 0x2588 is a solid block. cursorBlink.solid = string.uchar(0x2588) -- 0x2588 is a solid block.
elseif cursorBlink.state then elseif cursorBlink.state then
toggleBlink() toggleBlink()
end end
@ -67,10 +67,10 @@ function term.cursorBlink(enabled)
stop() stop()
end end
elseif type(enabled) == "string" and elseif type(enabled) == "string" and
(not cursorBlink or enabled:sub(1, 1) ~= cursorBlink.alt) (not cursorBlink or enabled:usub(1, 1) ~= cursorBlink.alt)
then then
if enabled:len() > 0 then if enabled:ulen() > 0 then
start(enabled:sub(1, 1)) start(enabled:usub(1, 1))
else else
stop() stop()
end end
@ -85,63 +85,68 @@ function term.read(history)
table.insert(history, "") table.insert(history, "")
local current = #history local current = #history
local keys = driver.keyboard.keys local keys = driver.keyboard.keys
local start, y = term.cursor() local start = term.cursor()
local cursor, scroll = 1, 0 local cursor, scroll = 1, 0
local keyRepeat = nil local keyRepeat = nil
local result = nil local result = nil
local function remove() local function remove()
local x = start - 1 + cursor - scroll local x = start - 1 + cursor - scroll
local _, y = term.cursor()
local w = gpu.resolution() local w = gpu.resolution()
gpu.copy(x + 1, y, w - x, 1, -1, 0) gpu.copy(x + 1, y, w - x, 1, -1, 0)
local cursor = cursor + (w - x) local cursor = cursor + (w - x)
local char = history[current]:sub(cursor, cursor) local char = history[current]:usub(cursor, cursor)
if char:len() == 0 then if char:ulen() == 0 then
char = " " char = " "
end end
gpu.set(w, y, char) gpu.set(w, y, char)
end end
local function render() local function render()
local _, y = term.cursor()
local w = gpu.resolution() local w = gpu.resolution()
local str = history[current]:sub(1 + scroll, 1 + scroll + w - (start - 1)) local str = history[current]:usub(1 + scroll, 1 + scroll + w - (start - 1))
str = str .. string.rep(" ", (w - (start - 1)) - str:len()) str = str .. string.rep(" ", (w - (start - 1)) - str:ulen())
gpu.set(start, y, str) gpu.set(start, y, str)
end end
local function scrollEnd() local function scrollEnd()
local w = gpu.resolution() local w = gpu.resolution()
cursor = history[current]:len() + 1 cursor = history[current]:ulen() + 1
scroll = math.max(0, cursor - (w - (start - 1))) scroll = math.max(0, cursor - (w - (start - 1)))
render() render()
end end
local function scrollLeft() local function scrollLeft()
scroll = scroll - 1 scroll = scroll - 1
local _, y = term.cursor()
local w = gpu.resolution() local w = gpu.resolution()
gpu.copy(start, y, w - start - 1, 1, 1, 0) gpu.copy(start, y, w - start - 1, 1, 1, 0)
local cursor = w - (start - 1) + scroll local cursor = w - (start - 1) + scroll
local char = history[current]:sub(cursor, cursor) local char = history[current]:usub(cursor, cursor)
if char:len() == 0 then if char:ulen() == 0 then
char = " " char = " "
end end
gpu.set(1, y, char) gpu.set(1, y, char)
end end
local function scrollRight() local function scrollRight()
scroll = scroll + 1 scroll = scroll + 1
local _, y = term.cursor()
local w = gpu.resolution() local w = gpu.resolution()
gpu.copy(start + 1, y, w - start, 1, -1, 0) gpu.copy(start + 1, y, w - start, 1, -1, 0)
local cursor = w - (start - 1) + scroll local cursor = w - (start - 1) + scroll
local char = history[current]:sub(cursor, cursor) local char = history[current]:usub(cursor, cursor)
if char:len() == 0 then if char:ulen() == 0 then
char = " " char = " "
end end
gpu.set(w, y, char) gpu.set(w, y, char)
end end
local function update() local function update()
local _, y = term.cursor()
local w = gpu.resolution() local w = gpu.resolution()
local cursor = cursor - 1 local cursor = cursor - 1
local x = start - 1 + cursor - scroll local x = start - 1 + cursor - scroll
if cursor < history[current]:len() then if cursor < history[current]:ulen() then
gpu.copy(x, y, w - x, 1, 1, 0) gpu.copy(x, y, w - x, 1, 1, 0)
end end
gpu.set(x, y, history[current]:sub(cursor, cursor)) gpu.set(x, y, history[current]:usub(cursor, cursor))
end end
local function copyIfNecessary() local function copyIfNecessary()
if current ~= #history then if current ~= #history then
@ -150,9 +155,10 @@ function term.read(history)
end end
end end
local function updateCursor() local function updateCursor()
local _, y = term.cursor()
term.cursor(start - 1 + cursor - scroll, y) term.cursor(start - 1 + cursor - scroll, y)
term.cursorBlink(cursor <= history[current]:len() and term.cursorBlink(cursor <= history[current]:ulen() and
history[current]:sub(cursor, cursor) or " ") history[current]:usub(cursor, cursor) or " ")
end end
local function handleKeyPress(char, code) local function handleKeyPress(char, code)
if not term.isAvailable() then return end if not term.isAvailable() then return end
@ -162,8 +168,8 @@ function term.read(history)
if code == keys.back then if code == keys.back then
if cursor > 1 then if cursor > 1 then
copyIfNecessary() copyIfNecessary()
history[current] = history[current]:sub(1, cursor - 2) .. history[current] = history[current]:usub(1, cursor - 2) ..
history[current]:sub(cursor) history[current]:usub(cursor)
cursor = cursor - 1 cursor = cursor - 1
if cursor - scroll < 1 then if cursor - scroll < 1 then
scrollLeft() scrollLeft()
@ -172,13 +178,13 @@ function term.read(history)
end end
cancel = cursor == 1 cancel = cursor == 1
elseif code == keys.delete then elseif code == keys.delete then
if cursor <= history[current]:len() then if cursor <= history[current]:ulen() then
copyIfNecessary() copyIfNecessary()
history[current] = history[current]:sub(1, cursor - 1) .. history[current] = history[current]:usub(1, cursor - 1) ..
history[current]:sub(cursor + 1) history[current]:usub(cursor + 1)
remove() remove()
end end
cancel = cursor == history[current]:len() + 1 cancel = cursor == history[current]:ulen() + 1
elseif code == keys.left then elseif code == keys.left then
if cursor > 1 then if cursor > 1 then
cursor = cursor - 1 cursor = cursor - 1
@ -188,13 +194,13 @@ function term.read(history)
end end
cancel = cursor == 1 cancel = cursor == 1
elseif code == keys.right then elseif code == keys.right then
if cursor < history[current]:len() + 1 then if cursor < history[current]:ulen() + 1 then
cursor = cursor + 1 cursor = cursor + 1
if cursor - scroll > w - (start - 1) then if cursor - scroll > w - (start - 1) then
scrollRight() scrollRight()
end end
end end
cancel = cursor == history[current]:len() + 1 cancel = cursor == history[current]:ulen() + 1
elseif code == keys.home then elseif code == keys.home then
if cursor > 1 then if cursor > 1 then
cursor, scroll = 1, 0 cursor, scroll = 1, 0
@ -202,7 +208,7 @@ function term.read(history)
end end
cancel = true cancel = true
elseif code == keys["end"] then elseif code == keys["end"] then
if cursor < history[current]:len() + 1 then if cursor < history[current]:ulen() + 1 then
scrollEnd() scrollEnd()
end end
cancel = true cancel = true
@ -225,15 +231,15 @@ function term.read(history)
current = #history current = #history
end end
result = history[current] .. "\n" result = history[current] .. "\n"
if history[current]:len() == 0 then if history[current]:ulen() == 0 then
table.remove(history, current) table.remove(history, current)
end end
return true return true
elseif not keys.isControl(char) then elseif not keys.isControl(char) then
copyIfNecessary() copyIfNecessary()
history[current] = history[current]:sub(1, cursor - 1) .. history[current] = history[current]:usub(1, cursor - 1) ..
string.char(char) .. string.uchar(char) ..
history[current]:sub(cursor) history[current]:usub(cursor)
cursor = cursor + 1 cursor = cursor + 1
update() update()
if cursor - scroll > w - (start - 1) then if cursor - scroll > w - (start - 1) then
@ -281,7 +287,7 @@ function term.read(history)
term.cursorBlink(false) term.cursorBlink(false)
local l = value:find("\n", 1, true) local l = value:find("\n", 1, true)
if l then if l then
history[current] = history[current] .. value:sub(1, l - 1) history[current] = history[current] .. value:usub(1, l - 1)
result = history[current] .. "\n" result = history[current] .. "\n"
else else
history[current] = history[current] .. value history[current] = history[current] .. value
@ -312,7 +318,7 @@ end
function term.write(value, wrap) function term.write(value, wrap)
value = tostring(value) value = tostring(value)
if value:len() == 0 or not term.isAvailable() then if value:ulen() == 0 or not term.isAvailable() then
return return
end end
value = value:gsub("\t", " ") value = value:gsub("\t", " ")
@ -329,18 +335,18 @@ function term.write(value, wrap)
end end
end end
for line, nl in value:gmatch("([^\r\n]*)([\r\n]?)") do for line, nl in value:gmatch("([^\r\n]*)([\r\n]?)") do
while wrap and line:len() > w - cursorX + 1 do while wrap and line:ulen() > w - cursorX + 1 do
local partial = line:sub(1, w - cursorX + 1) local partial = line:usub(1, w - cursorX + 1)
line = line:sub(partial:len() + 1) line = line:usub(partial:ulen() + 1)
gpu.set(cursorX, cursorY, partial) gpu.set(cursorX, cursorY, partial)
cursorX = cursorX + partial:len() cursorX = cursorX + partial:ulen()
checkCursor() checkCursor()
end end
if line:len() > 0 then if line:ulen() > 0 then
gpu.set(cursorX, cursorY, line) gpu.set(cursorX, cursorY, line)
cursorX = cursorX + line:len() cursorX = cursorX + line:ulen()
end end
if nl:len() == 1 then if nl:ulen() == 1 then
cursorX = 1 cursorX = 1
cursorY = cursorY + 1 cursorY = cursorY + 1
checkCursor() checkCursor()

View File

@ -24,6 +24,7 @@ object Config {
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
var baseMemory = 0 var baseMemory = 0
var commandUser = "OpenComputers"
var fileCost = 512 var fileCost = 512
var filesBuffered = true var filesBuffered = true
var maxScreenHeight = 6 var maxScreenHeight = 6
@ -83,6 +84,12 @@ object Config {
"global and applies to all computers!"). "global and applies to all computers!").
getInt(baseMemory) getInt(baseMemory)
commandUser = config.get("server", "commandUser", commandUser, "" +
"The user name to specify when executing a command via a command block. If\n" +
"you leave this empty it will use the address of the network node that sent\n" +
"the execution request - which will usually be a computer.").
getString
fileCost = config.get("server", "fileCost", fileCost, "" + fileCost = config.get("server", "fileCost", fileCost, "" +
"The base 'cost' of a single file or directory on a limited file system,\n" + "The base 'cost' of a single file or directory on a limited file system,\n" +
"such as hard drives. When computing the used space we add this cost to\n" + "such as hard drives. When computing the used space we add this cost to\n" +

View File

@ -84,7 +84,7 @@ trait Component extends Node {
def canBeSeenBy(other: Node) = componentVisibility match { def canBeSeenBy(other: Node) = componentVisibility match {
case Visibility.None => false case Visibility.None => false
case Visibility.Network => true case Visibility.Network => true
case Visibility.Neighbors => network.exists(_.neighbors(other).exists(_ == this)) case Visibility.Neighbors => other.network.exists(_.neighbors(other).exists(_ == this))
} }
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //

View File

@ -9,7 +9,7 @@ class Computer(playerInventory: InventoryPlayer, val computer: tileentity.Comput
override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = { override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
super.drawGuiContainerForegroundLayer(mouseX, mouseY) super.drawGuiContainerForegroundLayer(mouseX, mouseY)
fontRenderer.drawString( fontRenderer.drawString(
StatCollector.translateToLocal("oc.container.computer"), StatCollector.translateToLocal("oc.container.Computer"),
8, 6, 0x404040) 8, 6, 0x404040)
} }

View File

@ -9,7 +9,7 @@ class DiskDrive(playerInventory: InventoryPlayer, val drive: tileentity.DiskDriv
override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = { override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
super.drawGuiContainerForegroundLayer(mouseX, mouseY) super.drawGuiContainerForegroundLayer(mouseX, mouseY)
fontRenderer.drawString( fontRenderer.drawString(
StatCollector.translateToLocal("oc.container.disk_drive"), StatCollector.translateToLocal("oc.container.DiskDrive"),
8, 6, 0x404040) 8, 6, 0x404040)
} }
} }

View File

@ -9,10 +9,6 @@ class Keyboard(val parent: SpecialDelegator) extends SpecialDelegate {
val unlocalizedName = "Keyboard" val unlocalizedName = "Keyboard"
// ----------------------------------------------------------------------- //
// Tile entity
// ----------------------------------------------------------------------- //
override def hasTileEntity = true override def hasTileEntity = true
override def createTileEntity(world: World, metadata: Int) = Some(new tileentity.Keyboard) override def createTileEntity(world: World, metadata: Int) = Some(new tileentity.Keyboard)

View File

@ -4,9 +4,9 @@ import dan200.computer.api.{ILuaContext, IComputerAccess, IPeripheral}
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.api.network.{Message, Visibility, Node} import li.cil.oc.api.network.{Message, Visibility, Node}
import li.cil.oc.server.driver import li.cil.oc.server.driver
import net.minecraft.nbt.{NBTTagString, NBTTagList, NBTTagCompound}
import net.minecraftforge.common.ForgeDirection import net.minecraftforge.common.ForgeDirection
import scala.collection.mutable import scala.collection.mutable
import net.minecraft.nbt.NBTTagCompound
class Adapter extends Rotatable with Node with IPeripheral { class Adapter extends Rotatable with Node with IPeripheral {
val name = "adapter" val name = "adapter"
@ -15,6 +15,8 @@ class Adapter extends Rotatable with Node with IPeripheral {
private val blocks = Array.fill[Option[(Node, api.driver.Block)]](6)(None) private val blocks = Array.fill[Option[(Node, api.driver.Block)]](6)(None)
private val blocksAddresses = Array.fill[String](6)(java.util.UUID.randomUUID.toString)
private val computers = mutable.ArrayBuffer.empty[IComputerAccess] private val computers = mutable.ArrayBuffer.empty[IComputerAccess]
private val openPorts = mutable.Map.empty[IComputerAccess, mutable.Set[Int]] private val openPorts = mutable.Map.empty[IComputerAccess, mutable.Set[Int]]
@ -52,12 +54,14 @@ class Adapter extends Rotatable with Node with IPeripheral {
// This is... odd. // This is... odd.
network.foreach(_.disconnect(this, node)) network.foreach(_.disconnect(this, node))
val newNode = newDriver.node(worldObj, x, y, z) val newNode = newDriver.node(worldObj, x, y, z)
newNode.address = Some(blocksAddresses(d.ordinal()))
network.foreach(_.connect(this, newNode)) network.foreach(_.connect(this, newNode))
blocks(d.ordinal()) = Some((newNode, newDriver)) blocks(d.ordinal()) = Some((newNode, newDriver))
} // else: the more things change, the more they stay the same. } // else: the more things change, the more they stay the same.
case _ => case _ =>
// A challenger appears. // A challenger appears.
val node = newDriver.node(worldObj, x, y, z) val node = newDriver.node(worldObj, x, y, z)
node.address = Some(blocksAddresses(d.ordinal()))
network.foreach(_.connect(this, node)) network.foreach(_.connect(this, node))
blocks(d.ordinal()) = Some((node, newDriver)) blocks(d.ordinal()) = Some((node, newDriver))
} }
@ -75,14 +79,29 @@ class Adapter extends Rotatable with Node with IPeripheral {
override def readFromNBT(nbt: NBTTagCompound) { override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt) super.readFromNBT(nbt)
load(nbt.getCompoundTag("node")) load(nbt.getCompoundTag("node"))
val addressesNbt = nbt.getTagList("addresses")
(0 until (addressesNbt.tagCount min blocksAddresses.length)).
map(addressesNbt.tagAt).
map(_.asInstanceOf[NBTTagString].data).
zipWithIndex.
foreach {
case (a, i) => blocksAddresses(i) = a
}
} }
override def writeToNBT(nbt: NBTTagCompound) { override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt) super.writeToNBT(nbt)
val nodeNbt = new NBTTagCompound val nodeNbt = new NBTTagCompound()
save(nodeNbt) save(nodeNbt)
nbt.setCompoundTag("node", nodeNbt) nbt.setCompoundTag("node", nodeNbt)
val addressesNbt = new NBTTagList()
for (i <- 0 until blocksAddresses.length) {
addressesNbt.appendTag(new NBTTagString(null, blocksAddresses(i)))
}
nbt.setTag("addresses", addressesNbt)
} }
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //

View File

@ -88,7 +88,7 @@ class Computer(isClient: Boolean) extends Rotatable with component.Computer.Envi
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
def getInvName = "oc.container.computer" def getInvName = "oc.container.Computer"
def getSizeInventory = 8 def getSizeInventory = 8

View File

@ -46,7 +46,7 @@ class DiskDrive extends Rotatable with Component with ComponentInventory {
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
def getInvName = "oc.container.disk_drive" def getInvName = "oc.container.DiskDrive"
def getSizeInventory = 1 def getSizeInventory = 1

View File

@ -44,5 +44,5 @@ class Keyboard extends Rotatable with Component {
} }
def isUseableByPlayer(p: Player) = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) == this && def isUseableByPlayer(p: Player) = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) == this &&
p.asInstanceOf[EntityPlayer].getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) < 16 p.asInstanceOf[EntityPlayer].getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) < 64
} }

View File

@ -1,5 +1,6 @@
package li.cil.oc.server.component package li.cil.oc.server.component
import li.cil.oc.Config
import li.cil.oc.api.network.{Component, Message, Visibility} import li.cil.oc.api.network.{Component, Message, Visibility}
import net.minecraft.tileentity.TileEntityCommandBlock import net.minecraft.tileentity.TileEntityCommandBlock
@ -19,7 +20,11 @@ class CommandBlock(entity: TileEntityCommandBlock) extends Component {
entity.worldObj.markBlockForUpdate(entity.xCoord, entity.yCoord, entity.zCoord) entity.worldObj.markBlockForUpdate(entity.xCoord, entity.yCoord, entity.zCoord)
result(true) result(true)
case Array() if message.name == "command.run" => case Array() if message.name == "command.run" =>
entity.setCommandSenderName(message.source.address.get) val name = if (Config.commandUser != null && !Config.commandUser.trim.isEmpty)
Config.commandUser.trim
else
message.source.address.get
entity.setCommandSenderName(name)
result(entity.executeCommandOnPowered(entity.worldObj) != 0) result(entity.executeCommandOnPowered(entity.worldObj) != 0)
case _ => None case _ => None
} }

View File

@ -606,8 +606,13 @@ class Computer(val owner: Computer.Environment) extends Persistable with Runnabl
lua.pushScalaFunction(lua => { lua.pushScalaFunction(lua => {
owner.network.fold(None: Option[Node])(_.node(lua.checkString(1))) match { owner.network.fold(None: Option[Node])(_.node(lua.checkString(1))) match {
case None => 0 case Some(node: Component) if node.canBeSeenBy(this.owner) =>
case Some(node) => lua.pushString(node.name); 1 lua.pushString(node.name)
1
case None =>
lua.pushNil()
lua.pushString("invalid address")
2
} }
}) })
lua.setGlobal("nodeName") lua.setGlobal("nodeName")
@ -865,7 +870,10 @@ object Computer {
message.data match { message.data match {
case Array() if message.name == "system.disconnect" && computer.isRunning => case Array() if message.name == "system.disconnect" && computer.isRunning =>
message.source match { message.source match {
case node: Component if node.canBeSeenBy(this) => case node: Component =>
// This is also generated for components that were never added,
// because the node has already been removed from the network at
// this point, so we cannot check for visibility anymore.
computer.signal("component_removed", message.source.address.get); None computer.signal("component_removed", message.source.address.get); None
case _ => None case _ => None
} }

View File

@ -142,10 +142,6 @@ object LuaStateFactory {
state.setGlobal("dofile") state.setGlobal("dofile")
state.pushNil() state.pushNil()
state.setGlobal("loadfile") state.setGlobal("loadfile")
state.pushNil()
state.setGlobal("module")
state.pushNil()
state.setGlobal("require")
// Push a couple of functions that override original Lua API functions or // Push a couple of functions that override original Lua API functions or
// that add new functionality to it. // that add new functionality to it.
@ -218,20 +214,6 @@ object LuaStateFactory {
// Provide some better Unicode support. // Provide some better Unicode support.
state.getGlobal("string") state.getGlobal("string")
// Rename stuff for binary functionality, to allow byte-wise operations
// operations on the string.
state.getField(-1, "sub")
state.setField(-2, "bsub")
state.getField(-1, "reverse")
state.setField(-2, "breverse")
state.pushScalaFunction(lua => {
lua.pushString(String.valueOf((1 to lua.getTop).map(lua.checkInteger).map(_.toChar).toArray))
1
})
state.setField(-2, "char")
// TODO find (probably not necessary?) // TODO find (probably not necessary?)
// TODO format (probably not necessary?) // TODO format (probably not necessary?)
@ -240,11 +222,7 @@ object LuaStateFactory {
// TODO gsub (probably not necessary?) // TODO gsub (probably not necessary?)
state.pushScalaFunction(lua => { // TODO match (probably not necessary?)
lua.pushInteger(lua.checkString(1).length)
1
})
state.setField(-2, "len")
state.pushScalaFunction(lua => { state.pushScalaFunction(lua => {
lua.pushString(lua.checkString(1).toLowerCase) lua.pushString(lua.checkString(1).toLowerCase)
@ -252,13 +230,29 @@ object LuaStateFactory {
}) })
state.setField(-2, "lower") state.setField(-2, "lower")
// TODO match (probably not necessary?) state.pushScalaFunction(lua => {
lua.pushString(lua.checkString(1).toUpperCase)
1
})
state.setField(-2, "upper")
state.pushScalaFunction(lua => {
lua.pushString(String.valueOf((1 to lua.getTop).map(lua.checkInteger).map(_.toChar).toArray))
1
})
state.setField(-2, "uchar")
state.pushScalaFunction(lua => {
lua.pushInteger(lua.checkString(1).length)
1
})
state.setField(-2, "ulen")
state.pushScalaFunction(lua => { state.pushScalaFunction(lua => {
lua.pushString(lua.checkString(1).reverse) lua.pushString(lua.checkString(1).reverse)
1 1
}) })
state.setField(-2, "reverse") state.setField(-2, "ureverse")
state.pushScalaFunction(lua => { state.pushScalaFunction(lua => {
val string = lua.checkString(1) val string = lua.checkString(1)
@ -276,13 +270,7 @@ object LuaStateFactory {
else lua.pushString(string.substring(start, end)) else lua.pushString(string.substring(start, end))
1 1
}) })
state.setField(-2, "sub") state.setField(-2, "usub")
state.pushScalaFunction(lua => {
lua.pushString(lua.checkString(1).toUpperCase)
1
})
state.setField(-2, "upper")
// Pop the string table. // Pop the string table.
state.pop(1) state.pop(1)