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

Conflicts:
	build.properties
This commit is contained in:
Florian Nücke 2015-04-01 00:02:12 +02:00
commit 4259c8aaf3
23 changed files with 494 additions and 165 deletions

View File

@ -118,27 +118,27 @@ repositories {
ivy {
name 'CoFHLib'
artifactPattern "http://addons.cursecdn.com/files/${config.cofhlib.cf}/[module]-[revision].[ext]"
artifactPattern "http://addons-origin.cursecdn.com/files/${config.cofhlib.cf}/[module]-[revision].[ext]"
}
ivy {
name 'MineFactoryReloaded'
artifactPattern "http://addons.cursecdn.com/files/${config.mfr.cf}/[module]-[revision].[ext]"
artifactPattern "http://addons-origin.cursecdn.com/files/${config.mfr.cf}/[module]-[revision].[ext]"
}
ivy {
name 'ComputerCraft'
artifactPattern "http://addons.cursecdn.com/files/${config.cc.cf}/[module][revision].[ext]"
artifactPattern "http://addons-origin.cursecdn.com/files/${config.cc.cf}/[module][revision].[ext]"
}
ivy {
name 'EnderIO'
artifactPattern "http://addons.cursecdn.com/files/${config.eio.cf}/[module]-[revision].[ext]"
artifactPattern "http://addons-origin.cursecdn.com/files/${config.eio.cf}/[module]-[revision].[ext]"
}
ivy {
name 'Railcraft'
artifactPattern "http://addons.cursecdn.com/files/${config.rc.cf}/[module]_[revision].[ext]"
artifactPattern "http://addons-origin.cursecdn.com/files/${config.rc.cf}/[module]_[revision].[ext]"
}
ivy {
name 'BloodMagic'
artifactPattern "http://addons.cursecdn.com/files/${config.bloodmagic.cf}/[module]-${config.minecraft.version}-[revision].[ext]"
artifactPattern "http://addons-origin.cursecdn.com/files/${config.bloodmagic.cf}/[module]-${config.minecraft.version}-[revision].[ext]"
}
}
@ -149,7 +149,7 @@ configurations {
}
dependencies {
provided "api:rotarycraft:${config.rotc.version}"
provided "appeng:RotaryCraft:${config.rotc.version}:api"
provided "appeng:appliedenergistics2:${config.ae2.version}:dev"
provided "codechicken:CodeChickenLib:${config.minecraft.version}-${config.ccl.version}:dev"
provided "codechicken:EnderStorage:${config.minecraft.version}-${config.es.version}:dev"

View File

@ -1,18 +1,18 @@
minecraft.version=1.7.10
forge.version=10.13.2.1236
forge.version=10.13.2.1291
oc.version=1.5.4
oc.version=1.5.5
oc.subversion=
ae2.version=rv1-stable-1
bc.version=6.2.6
ae2.version=rv2-beta-22
bc.version=6.4.5
bloodmagic.cf=2223/203
bloodmagic.version=1.3.0a-1
cc.cf=2216/236
cc.version=1.65
ccl.version=1.1.1.104
cofhlib.cf=2218/257
cofhlib.version=[1.7.10]1.0.0B7-dev-29
cofhlib.cf=2230/207
cofhlib.version=[1.7.10]1.0.0RC7-127
eio.cf=2219/296
eio.version=1.7.10-2.2.1.276
es.version=1.4.5.24
@ -24,14 +24,14 @@ gt.version=5.04.06
ic2.version=2.2.654-experimental
mekanism.build=5
mekanism.version=7.1.2
mfr.cf=2213/46
mfr.version=[1.7.10]2.8.0RC3-dev-591
mfr.cf=2229/626
mfr.version=[1.7.10]2.8.0RC8-86
nei.version=1.0.3.57
projred.version=4.5.8.59
rc.cf=2219/321
rc.version=1.7.10-9.4.0.0
redlogic.version=59.0.3
rotc.version=1
rotc.version=V5c
tmech.version=75.0afb56c
re.version=3.0.0.342
waila.version=1.5.8a

View File

@ -1035,6 +1035,12 @@ opencomputers {
# this many shapes *per state* (the reasoning being that only one state
# will ever be visible at a time).
maxPrinterShapes: 24
# How much of the material used to print a model is refunded when using
# the model to refuel a printer. This the value the original material
# cost is multiplied with, so 1 is a full refund, 0 disables the
# functionality (won't be able to put prints into the material input).
printRecycleRate: 0.75
}
# Settings for mod integration (the mod previously known as OpenComponents).

View File

@ -1,6 +1,11 @@
--[[
OpenPrograms package manager, browser and downloader, for easy access to many programs
Author: Vexatos
Warning! This file is just an auto-installer for OPPM!
DO NOT EVER TRY TO INSTALL A PACKAGE WITH THIS!
Once you ran OPPM once, you can remove the floppy disk
and run the installed OPPM version just fine.
]]
local component = require("component")
local event = require("event")
@ -10,18 +15,22 @@ local serial = require("serialization")
local shell = require("shell")
local term = require("term")
local wget = loadfile("/bin/wget.lua")
local gpu = component.gpu
if not component.isAvailable("internet") then
io.stderr:write("This program requires an internet card to run.")
return
end
local internet = require("internet")
local internet
local wget
local args, options = shell.parse(...)
local function getInternet()
if not component.isAvailable("internet") then
io.stderr:write("This program requires an internet card to run.")
return false
end
internet = require("internet")
wget = loadfile("/bin/wget.lua")
return true
end
local function printUsage()
print("OpenPrograms Package Manager, use this to browse through and download OpenPrograms programs easily")
@ -43,9 +52,9 @@ local function getContent(url)
if not result then
return nil
end
for chunk in response do
sContent = sContent..chunk
end
for chunk in response do
sContent = sContent..chunk
end
return sContent
end
@ -80,6 +89,9 @@ local function downloadFile(url,path,force)
if options.f or force then
return wget("-fq",url,path)
else
if fs.exists(path) then
error("file already exists and option -f is not enabled")
end
return wget("-q",url,path)
end
end
@ -209,6 +221,67 @@ local function printPackages(packs)
end
end
local function parseFolders(pack, repo, info)
local function getFolderTable(repo, namePath, branch)
local success, filestring = pcall(getContent,"https://api.github.com/repos/"..repo.."/contents/"..namePath.."?ref="..branch)
if not success or filestring:find('"message": "Not Found"') then
io.stderr:write("Error while trying to parse folder names in declaration of package "..pack..".\n")
if filestring:find('"message": "Not Found"') then
io.stderr:write("Folder "..namePath.." does not exist.\n")
else
io.stderr:write(filestring.."\n")
end
io.stderr:write("Please contact the author of that package.\n")
return nil
end
return serial.unserialize(filestring:gsub("%[", "{"):gsub("%]", "}"):gsub("(\"[^%s,]-\")%s?:", "[%1] = "), nil)
end
local function nonSpecial(text)
return text:gsub("([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1")
end
local function unserializeFiles(files, repo, namePath, branch, relPath)
if not files then return nil end
local tFiles = {}
for _,v in pairs(files) do
if v["type"] == "file" then
local newPath = v["download_url"]:gsub("https?://raw.githubusercontent.com/"..nonSpecial(repo).."(.+)$", "%1"):gsub("/*$",""):gsub("^/*","")
tFiles[newPath] = relPath
elseif v["type"] == "dir" then
local newFiles = unserializeFiles(getFolderTable(repo, relPath.."/"..v["name"], branch), repo, branch, fs.concat(relPath, v["name"]))
for p,q in pairs(newFiles) do
tFiles[p] = q
end
end
end
return tFiles
end
local newInfo = info
for i,j in pairs(info.files) do
if string.find(i,"^:") then
local iPath = i:gsub("^:","")
local branch = string.gsub(iPath,"^(.-)/.+","%1"):gsub("/*$",""):gsub("^/*","")
local namePath = string.gsub(iPath,".-(/.+)$","%1"):gsub("/*$",""):gsub("^/*","")
local absolutePath = j:find("^//")
local files = unserializeFiles(getFolderTable(repo, namePath, branch), repo, namePath, branch, j:gsub("^//","/"))
if not files then return nil end
for p,q in pairs(files) do
if absolutePath then
newInfo.files[p] = "/"..q
else
newInfo.files[p] = q
end
end
newInfo.files[i] = nil
end
end
return newInfo
end
local function getInformation(pack)
local success, repos = pcall(getRepos)
if not success or repos==-1 then
@ -223,7 +296,7 @@ local function getInformation(pack)
elseif type(lPacks) == "table" then
for k in pairs(lPacks) do
if k==pack then
return lPacks[k],j.repo
return parseFolders(pack, j.repo, lPacks[k]),j.repo
end
end
end
@ -234,7 +307,7 @@ local function getInformation(pack)
for i,j in pairs(lRepos.repos) do
for k in pairs(j) do
if k==pack then
return j[k],i
return parseFolders(pack, i, j[k]),i
end
end
end
@ -271,14 +344,17 @@ local function provideInfo(pack)
print("Note: "..info.note)
done = true
end
if info.files then
print("Number of files: "..tostring(#info.files))
done = true
end
if not done then
print("No information provided.")
end
end
local tPacks = readFromFile(1)
local function installPackage(pack,path,update)
local tPacks = readFromFile(1)
update = update or false
if not pack then
printUsage()
@ -309,8 +385,12 @@ local function installPackage(pack,path,update)
if update then
print("Updating package "..pack)
path = nil
if not tPacks[pack] then
io.stderr:write("error while checking update path")
return
end
for i,j in pairs(info.files) do
if tPacks[pack] then
if not string.find(j,"^//") then
for k,v in pairs(tPacks[pack]) do
if k==i then
path = string.gsub(fs.path(v),j.."/?$","/")
@ -320,9 +400,6 @@ local function installPackage(pack,path,update)
if path then
break
end
else
io.stderr:write("error while checking update path")
return
end
end
path = shell.resolve(string.gsub(path,"^/?","/"),nil)
@ -381,7 +458,8 @@ local function installPackage(pack,path,update)
if success and response then
tPacks[pack][i] = nPath
else
term.write("Error while installing files for package '"..pack.."'. Reverting installation... ")
response = response or "no error message"
term.write("Error while installing files for package '"..pack.."': "..response..". Reverting installation... ")
fs.remove(nPath)
for o,p in pairs(tPacks[pack]) do
fs.remove(p)
@ -405,7 +483,8 @@ local function installPackage(pack,path,update)
if success and response then
tPacks[pack][i] = nPath
else
term.write("Error while installing dependency package '"..i.."'. Reverting installation... ")
response = response or "no error message"
term.write("Error while installing files for package '"..pack.."': "..response..". Reverting installation... ")
fs.remove(nPath)
for o,p in pairs(tPacks[pack]) do
fs.remove(p)
@ -429,11 +508,6 @@ local function installPackage(pack,path,update)
end
local function uninstallPackage(pack)
local info,repo = getInformation(pack)
if not info then
print("Package does not exist")
return
end
local tFiles = readFromFile(1)
if not tFiles then
io.stderr:write("Error while trying to read package names")
@ -443,7 +517,8 @@ local function uninstallPackage(pack)
end
if not tFiles[pack] then
print("Package has not been installed.")
print("If it has, you have to remove it manually.")
print("If it has, the package could not be identified.")
print("In this case you have to remove it manually.")
return
end
term.write("Removing package files...")
@ -482,13 +557,17 @@ end
if options.iKnowWhatIAmDoing then
if args[1] == "list" then
if not getInternet() then return end
local packs = listPackages(args[2])
printPackages(packs)
elseif args[1] == "info" then
if not getInternet() then return end
provideInfo(args[2])
elseif args[1] == "install" then
if not getInternet() then return end
installPackage(args[2],args[3],false)
elseif args[1] == "update" then
if not getInternet() then return end
updatePackage(args[2])
elseif args[1] == "uninstall" then
uninstallPackage(args[2])

View File

@ -21,5 +21,6 @@ else
io.write(line)
end
until not line
file:close()
end
end
end

View File

@ -908,7 +908,7 @@ wrappedUserdataMeta = {
local wrappedUserdata = setmetatable({}, wrappedUserdataMeta)
local function processResult(result)
wrapUserdata(result) -- needed for metamethods.
result = wrapUserdata(result) -- needed for metamethods.
if not result[1] then -- error that should be re-thrown.
error(result[2], 0)
else -- success or already processed error.
@ -920,8 +920,9 @@ local function invoke(target, direct, ...)
local result
if direct then
local args = table.pack(...) -- for unwrapping
unwrapUserdata(args)
args = unwrapUserdata(args)
result = table.pack(target.invoke(table.unpack(args, 1, args.n)))
args = nil -- clear upvalue, avoids trying to persist it
if result.n == 0 then -- limit for direct calls reached
result = nil
end
@ -930,9 +931,10 @@ local function invoke(target, direct, ...)
if not result then
local args = table.pack(...) -- for access in closure
result = select(1, coroutine.yield(function()
unwrapUserdata(args)
args = unwrapUserdata(args)
local result = table.pack(target.invoke(table.unpack(args, 1, args.n)))
wrapUserdata(result)
args = nil -- clear upvalue, avoids trying to persist it
result = wrapUserdata(result)
return result
end))
end
@ -941,8 +943,9 @@ end
local function udinvoke(f, data, ...)
local args = table.pack(...)
unwrapUserdata(args)
args = unwrapUserdata(args)
local result = table.pack(f(data, table.unpack(args)))
args = nil -- clear upvalue, avoids trying to persist it
return processResult(result)
end
@ -1035,7 +1038,7 @@ function wrapUserdata(values)
end
return value
end
wrapRecursively(values)
return wrapRecursively(values)
end
function unwrapUserdata(values)
@ -1054,7 +1057,7 @@ function unwrapUserdata(values)
end
return value
end
unwrapRecursively(values)
return unwrapRecursively(values)
end
-------------------------------------------------------------------------------
@ -1343,13 +1346,14 @@ local function main()
debug.sethook(co, checkDeadline, "", hookInterval)
local result = table.pack(coroutine.resume(co, table.unpack(args, 1, args.n)))
args = nil -- clear upvalue, avoids trying to persist it
if not result[1] then
error(tostring(result[2]), 0)
elseif coroutine.status(co) == "dead" then
error("computer halted", 0)
else
args = table.pack(coroutine.yield(result[2])) -- system yielded value
wrapUserdata(args)
args = wrapUserdata(args)
end
end
end

View File

@ -294,6 +294,7 @@ class Settings(val config: Config) {
val assemblerBlacklist = config.getStringList("misc.assemblerBlacklist")
val threadPriority = config.getInt("misc.threadPriority")
val maxPrintComplexity = config.getInt("misc.maxPrinterShapes")
val printRecycleRate = config.getDouble("misc.printRecycleRate")
// ----------------------------------------------------------------------- //
// integration

View File

@ -141,7 +141,8 @@ object BlockRenderer extends ISimpleBlockRenderingHandler {
}
// The texture flip this works around only seems to occur for blocks with custom block renderers?
def patchedRenderer(renderer: RenderBlocks, block: Block) = if (block.isInstanceOf[Hologram] || block.isInstanceOf[Printer]) {
def patchedRenderer(renderer: RenderBlocks, block: Block) =
if (block.isInstanceOf[Hologram] || block.isInstanceOf[Printer] || block.isInstanceOf[Print]) {
PatchedRenderBlocks.blockAccess = renderer.blockAccess
PatchedRenderBlocks.overrideBlockTexture = renderer.overrideBlockTexture
PatchedRenderBlocks.flipTexture = renderer.flipTexture

View File

@ -258,24 +258,24 @@ object ItemRenderer extends IItemRenderer {
// Front.
GL11.glNormal3f(0, 0, 1)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.minY * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(16 - bounds.minY * 16))
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.maxZ)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.minY * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(16 - bounds.minY * 16))
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.maxZ)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.maxY * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(16 - bounds.maxY * 16))
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.maxZ)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.maxY * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(16 - bounds.maxY * 16))
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.maxZ)
// Back.
GL11.glNormal3f(0, 0, -1)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.minY * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(16 - bounds.minY * 16))
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.minZ)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.minY * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(16 - bounds.minY * 16))
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.minZ)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.maxY * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(16 - bounds.maxY * 16))
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.minZ)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.maxY * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(16 - bounds.maxY * 16))
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.minZ)
// Top.
@ -302,24 +302,24 @@ object ItemRenderer extends IItemRenderer {
// Left.
GL11.glNormal3f(1, 0, 0)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxY * 16), texture.getInterpolatedV(bounds.maxZ * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxZ * 16), texture.getInterpolatedV(16 - bounds.maxY * 16))
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.maxZ)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minY * 16), texture.getInterpolatedV(bounds.maxZ * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxZ * 16), texture.getInterpolatedV(16 - bounds.minY * 16))
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.maxZ)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minY * 16), texture.getInterpolatedV(bounds.minZ * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minZ * 16), texture.getInterpolatedV(16 - bounds.minY * 16))
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.minZ)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxY * 16), texture.getInterpolatedV(bounds.minZ * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minZ * 16), texture.getInterpolatedV(16 - bounds.maxY * 16))
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.minZ)
// Right.
GL11.glNormal3f(-1, 0, 0)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minY * 16), texture.getInterpolatedV(bounds.maxZ * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxZ * 16), texture.getInterpolatedV(16 - bounds.minY * 16))
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.maxZ)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxY * 16), texture.getInterpolatedV(bounds.maxZ * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxZ * 16), texture.getInterpolatedV(16 - bounds.maxY * 16))
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.maxZ)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxY * 16), texture.getInterpolatedV(bounds.minZ * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minZ * 16), texture.getInterpolatedV(16 - bounds.maxY * 16))
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.minZ)
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minY * 16), texture.getInterpolatedV(bounds.minZ * 16))
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minZ * 16), texture.getInterpolatedV(16 - bounds.minY * 16))
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.minZ)
GL11.glEnd()

View File

@ -22,6 +22,7 @@ import li.cil.oc.common.tileentity.traits.power
import li.cil.oc.integration.Mods
import li.cil.oc.integration.util
import li.cil.oc.server.component.Keyboard
import li.cil.oc.server.machine.Machine
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util._
import net.minecraft.client.Minecraft
@ -49,12 +50,16 @@ object EventHandler {
private val keyboards = java.util.Collections.newSetFromMap[Keyboard](new java.util.WeakHashMap[Keyboard, java.lang.Boolean])
private val machines = mutable.Set.empty[Machine]
def onRobotStart(robot: Robot): Unit = runningRobots += robot
def onRobotStopped(robot: Robot): Unit = runningRobots -= robot
def addKeyboard(keyboard: Keyboard): Unit = keyboards += keyboard
def scheduleClose(machine: Machine) = machines += machine
def schedule(tileEntity: TileEntity) {
if (SideTracker.isServer) pending.synchronized {
pending += (() => Network.joinOrCreateNetwork(tileEntity))
@ -130,6 +135,10 @@ object EventHandler {
else if (robot.world != null) robot.machine.update()
})
runningRobots --= invalid
val closed = mutable.ArrayBuffer.empty[Machine]
machines.foreach(machine => if (machine.tryClose()) closed += machine)
machines --= closed
}
@SubscribeEvent
@ -243,7 +252,7 @@ object EventHandler {
didRecraft = recraft(e, tablet, stack => {
// Restore EEPROM currently used in tablet.
new TabletData(stack).items.collect { case Some(item) => item}.find(api.Items.get(_) == eeprom)
new TabletData(stack).items.collect { case Some(item) => item }.find(api.Items.get(_) == eeprom)
}) || didRecraft
// Presents?

View File

@ -16,6 +16,7 @@ import net.minecraft.util.IChatComponent
import net.minecraftforge.common.util.Constants.NBT
import scala.collection.mutable
import scala.language.existentials
object AssemblerTemplates {
val NoSlot = new Slot(Slot.None, Tier.None, None, None)

View File

@ -188,10 +188,36 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
// ----------------------------------------------------------------------- //
override def canUpdate = isServer
def computeCosts(data: PrintData) = {
val totalVolume = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.volume)
val totalSurface = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.surface)
if (totalVolume > 0) {
val materialRequired = (totalVolume / 2) max 1
val inkRequired = (totalSurface / 6) max 1
Option((materialRequired, inkRequired))
}
else None
}
def materialValue(stack: ItemStack) = {
if (api.Items.get(stack) == api.Items.get("chamelium"))
materialPerItem
else if (api.Items.get(stack) == api.Items.get("print")) {
val data = new PrintData(stack)
computeCosts(data) match {
case Some((materialRequired, inkRequired)) => (materialRequired * Settings.get.printRecycleRate).toInt
case _ => 0
}
}
else 0
}
// ----------------------------------------------------------------------- //
override def canUpdate = isServer
override def updateEntity() {
super.updateEntity()
@ -202,28 +228,22 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
}
if (isActive && output.isEmpty && canMergeOutput) {
val totalVolume = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.volume)
val totalSurface = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.surface)
computeCosts(data) match {
case Some((materialRequired, inkRequired)) =>
totalRequiredEnergy = Settings.get.printCost
requiredEnergy = totalRequiredEnergy
if (totalVolume == 0) {
isActive = false
data = new PrintData()
}
else {
val materialRequired = (totalVolume / 2) max 1
val inkRequired = (totalSurface / 6) max 1
totalRequiredEnergy = Settings.get.printCost
requiredEnergy = totalRequiredEnergy
if (amountMaterial >= materialRequired && amountInk >= inkRequired) {
amountMaterial -= materialRequired
amountInk -= inkRequired
limit -= 1
output = Option(data.createItemStack())
if (limit < 1) isActive = false
ServerPacketSender.sendPrinting(this, printing = true)
}
if (amountMaterial >= materialRequired && amountInk >= inkRequired) {
amountMaterial -= materialRequired
amountInk -= inkRequired
limit -= 1
output = Option(data.createItemStack())
if (limit < 1) isActive = false
ServerPacketSender.sendPrinting(this, printing = true)
}
case _ =>
isActive = false
data = new PrintData()
}
}
@ -249,10 +269,11 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
ServerPacketSender.sendPrinting(this, have > 0.5 && output.isDefined)
}
if (maxAmountMaterial - amountMaterial >= materialPerItem) {
val inputValue = materialValue(getStackInSlot(slotMaterial))
if (inputValue > 0 && maxAmountMaterial - amountMaterial >= inputValue) {
val material = decrStackSize(slotMaterial, 1)
if (material != null) {
amountMaterial += materialPerItem
amountMaterial += inputValue
}
}
@ -310,9 +331,9 @@ class Printer extends traits.Environment with traits.Inventory with traits.Rotat
override def getInventoryStackLimit = 64
override def isItemValidForSlot(slot: Int, stack: ItemStack) =
if (slot == 0)
api.Items.get(stack) == api.Items.get("chamelium")
else if (slot == 1)
if (slot == slotMaterial)
materialValue(stack) > 0
else if (slot == slotInk)
api.Items.get(stack) == api.Items.get("inkCartridge")
else false

View File

@ -127,6 +127,13 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
ServerPacketSender.sendComputerState(this)
}
override def dispose(): Unit = {
super.dispose()
if (machine != null && !this.isInstanceOf[RobotProxy]) {
machine.stop()
}
}
// ----------------------------------------------------------------------- //
override def readFromNBTForServer(nbt: NBTTagCompound) {

View File

@ -3,7 +3,7 @@ package li.cil.oc.integration;
public interface Mod {
String id();
boolean isAvailable();
boolean isModAvailable();
boolean providesPower();
}

View File

@ -56,10 +56,12 @@ object Mods {
val StargateTech2 = new ModBase {
def id = IDs.StargateTech2
protected override lazy val isModAvailable = Loader.isModLoaded(IDs.StargateTech2) && {
private lazy val isModAvailable_ = Loader.isModLoaded(IDs.StargateTech2) && {
val mod = Loader.instance.getIndexedModList.get(IDs.StargateTech2)
mod.getVersion.startsWith("0.7.")
}
override def isModAvailable: Boolean = isModAvailable_
}
val Thaumcraft = new SimpleMod(IDs.Thaumcraft)
val ThermalExpansion = new SimpleMod(IDs.ThermalExpansion, providesPower = true)
@ -121,7 +123,7 @@ object Mods {
private def tryInit(mod: ModProxy) {
val isBlacklisted = Settings.get.modBlacklist.contains(mod.getMod.id)
val alwaysEnabled = mod.getMod == null || mod.getMod == Mods.Minecraft
if (!isBlacklisted && (alwaysEnabled || mod.getMod.isAvailable) && handlers.add(mod)) {
if (!isBlacklisted && (alwaysEnabled || mod.getMod.isModAvailable) && handlers.add(mod)) {
li.cil.oc.OpenComputers.log.info(s"Initializing mod integration for '${mod.getMod.id}'.")
try mod.initialize() catch {
case e: Throwable =>
@ -188,7 +190,7 @@ object Mods {
protected lazy val isPowerModEnabled = !providesPower || (!Settings.get.pureIgnorePower && !Settings.get.powerModBlacklist.contains(id))
protected def isModAvailable: Boolean
def isModAvailable: Boolean
def id: String
@ -199,21 +201,29 @@ object Mods {
// This is called from the class transformer when injecting an interface of
// this power type fails, to avoid class not found / class cast exceptions.
def disablePower() = powerDisabled = true
def container = Option(Loader.instance.getIndexedModList.get(id))
def version = container.map(_.getProcessedVersion)
}
class SimpleMod(val id: String, override val providesPower: Boolean = false, version: String = "") extends ModBase {
override protected lazy val isModAvailable = {
private lazy val isModAvailable_ = {
val version = VersionParser.parseVersionReference(id + this.version)
if (Loader.isModLoaded(version.getLabel))
version.containsVersion(Loader.instance.getIndexedModList.get(version.getLabel).getProcessedVersion)
else ModAPIManager.INSTANCE.hasAPI(version.getLabel)
}
def isModAvailable = isModAvailable_
}
class ClassBasedMod(val id: String, val classNames: String*)(override val providesPower: Boolean = false) extends ModBase {
override protected lazy val isModAvailable = classNames.forall(className => try Class.forName(className) != null catch {
private lazy val isModAvailable_ = classNames.forall(className => try Class.forName(className) != null catch {
case _: Throwable => false
})
def isModAvailable = isModAvailable_
}
}

View File

@ -7,12 +7,12 @@ import appeng.api.networking.crafting.ICraftingRequester
import appeng.api.networking.security.IActionHost
import appeng.api.networking.security.MachineSource
import appeng.api.storage.data.IAEItemStack
import appeng.core.Api
import appeng.me.helpers.IGridProxyable
import appeng.tile.misc.TileInterface
import appeng.tile.networking.TileController
import appeng.util.item.AEItemStack
import com.google.common.collect.ImmutableSet
import cpw.mods.fml.common.Loader
import cpw.mods.fml.common.versioning.VersionRange
import li.cil.oc.OpenComputers
import li.cil.oc.api.driver.EnvironmentAware
import li.cil.oc.api.driver.NamedBlock
@ -24,9 +24,11 @@ import li.cil.oc.api.prefab.AbstractValue
import li.cil.oc.api.prefab.DriverTileEntity
import li.cil.oc.common.EventHandler
import li.cil.oc.integration.ManagedTileEntityEnvironment
import li.cil.oc.integration.Mods
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ResultWrapper._
import net.minecraft.block.Block
import net.minecraft.item.Item
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.tileentity.TileEntity
@ -40,14 +42,24 @@ import scala.collection.convert.WrapAsScala._
import scala.collection.mutable
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.language.existentials
object DriverController extends DriverTileEntity with EnvironmentAware {
private type AETile = TileEntity with IGridProxyable with IActionHost
def getTileEntityClass = {
if (AEApi.instance != null && AEApi.instance.blocks != null) {
val versionsWithNewItemDefinitionAPI = VersionRange.createFromVersionSpec("[rv2-beta-20,)")
def getTileEntityClass: Class[_] = {
if (versionsWithNewItemDefinitionAPI.containsVersion(Loader.instance.getIndexedModList.get(Mods.AppliedEnergistics2.id).getProcessedVersion)) {
if (AEApi.instance.definitions.blocks.controller.maybeStack(0).isPresent)
AEApi.instance.definitions.blocks.controller.maybeEntity.orNull
else
AEApi.instance.definitions.blocks.iface.maybeEntity.orNull
}
else if (AEApi.instance != null && AEApi.instance.blocks != null) {
if (AEApi.instance.blocks.blockController != null && AEApi.instance.blocks.blockController.item != null)
classOf[TileController]
// Not classOf[TileController] because that derps the compiler when it tries to resolve the class (says can't find API classes from RotaryCraft).
Class.forName("appeng.tile.networking.TileController")
else
classOf[TileInterface]
}
@ -78,10 +90,13 @@ object DriverController extends DriverTileEntity with EnvironmentAware {
"coprocessors" -> cpu.getCoProcessors,
"busy" -> cpu.isBusy)))
@Callback(doc = "function():table -- Get a list of known item recipes. These can be used to issue crafting requests.")
@Callback(doc = "function([filter:table]):table -- Get a list of known item recipes. These can be used to issue crafting requests.")
def getCraftables(context: Context, args: Arguments): Array[AnyRef] = {
val filter = args.optTable(0, Map.empty[AnyRef, AnyRef]).collect {
case (key: String, value: AnyRef) => (key, value)
}
result(tileEntity.getProxy.getStorage.getItemInventory.getStorageList.
filter(_.isCraftable).map(stack => {
filter(_.isCraftable).filter(stack => matches(stack, filter)).map(stack => {
val patterns = tileEntity.getProxy.getCrafting.getCraftingFor(stack, null, 0, tileEntity.getWorldObj)
val result = patterns.find(pattern => pattern.getOutputs.exists(_.isSameType(stack))) match {
case Some(pattern) => pattern.getOutputs.find(_.isSameType(stack)).get
@ -91,9 +106,13 @@ object DriverController extends DriverTileEntity with EnvironmentAware {
}).toArray)
}
@Callback(doc = "function():table -- Get a list of the stored items in the network.")
def getItemsInNetwork(context: Context, args: Arguments): Array[AnyRef] =
result(tileEntity.getProxy.getStorage.getItemInventory.getStorageList.map(_.getItemStack).toArray)
@Callback(doc = "function([filter:table]):table -- Get a list of the stored items in the network.")
def getItemsInNetwork(context: Context, args: Arguments): Array[AnyRef] = {
val filter = args.optTable(0, Map.empty[AnyRef, AnyRef]).collect {
case (key: String, value: AnyRef) => (key, value)
}
result(tileEntity.getProxy.getStorage.getItemInventory.getStorageList.filter(stack => matches(stack, filter)).map(_.getItemStack).toArray)
}
@Callback(doc = "function():table -- Get a list of the stored fluids in the network.")
def getFluidsInNetwork(context: Context, args: Arguments): Array[AnyRef] =
@ -118,6 +137,17 @@ object DriverController extends DriverTileEntity with EnvironmentAware {
@Callback(doc = "function():number -- Get the stored power in the network. ")
def getStoredPower(context: Context, args: Arguments): Array[AnyRef] =
result(tileEntity.getProxy.getEnergy.getStoredPower)
private def matches(stack: IAEItemStack, filter: scala.collection.mutable.Map[String, AnyRef]) = {
stack != null &&
filter.get("damage").forall(_.equals(stack.getItemDamage.toDouble)) &&
filter.get("maxDamage").forall(_.equals(stack.getItemStack.getMaxDamage.toDouble)) &&
filter.get("size").forall(_.equals(stack.getStackSize.toDouble)) &&
filter.get("maxSize").forall(_.equals(stack.getItemStack.getMaxStackSize.toDouble)) &&
filter.get("hasTag").forall(_.equals(stack.hasTagCompound)) &&
filter.get("name").forall(_.equals(Item.itemRegistry.getNameForObject(stack.getItem))) &&
filter.get("label").forall(_.equals(stack.getItemStack.getDisplayName))
}
}
class Craftable(var controller: AETile, var stack: IAEItemStack) extends AbstractValue with ICraftingRequester {
@ -210,7 +240,7 @@ object DriverController extends DriverTileEntity with EnvironmentAware {
})
}
links ++= nbt.getTagList("links", NBT.TAG_COMPOUND).map(
(nbt: NBTTagCompound) => Api.instance.storage.loadCraftingLink(nbt, this))
(nbt: NBTTagCompound) => AEApi.instance.storage.loadCraftingLink(nbt, this))
}
override def save(nbt: NBTTagCompound) {

View File

@ -0,0 +1,52 @@
package li.cil.oc.integration.cofh.energy;
import cofh.api.energy.IEnergyProvider;
import cofh.api.energy.IEnergyReceiver;
import li.cil.oc.api.machine.Arguments;
import li.cil.oc.api.machine.Callback;
import li.cil.oc.api.machine.Context;
import li.cil.oc.api.network.ManagedEnvironment;
import li.cil.oc.api.prefab.DriverTileEntity;
import li.cil.oc.integration.ManagedTileEntityEnvironment;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public final class DriverEnergyProvider extends DriverTileEntity {
@Override
public Class<?> getTileEntityClass() {
return IEnergyProvider.class;
}
@Override
public ManagedEnvironment createEnvironment(final World world, final int x, final int y, final int z) {
return new Environment((IEnergyProvider) world.getTileEntity(x, y, z));
}
public static final class Environment extends ManagedTileEntityEnvironment<IEnergyProvider> {
public Environment(final IEnergyProvider tileEntity) {
super(tileEntity, "energy_handler");
}
@Callback(doc = "function([direction:number=6]):number -- Returns the amount of stored energy for the given side.")
public Object[] getEnergyStored(final Context context, final Arguments args) {
final ForgeDirection side = args.count() > 0 ? ForgeDirection.getOrientation(args.checkInteger(0)) : ForgeDirection.UNKNOWN;
return new Object[]{tileEntity.getEnergyStored(side)};
}
@Callback(doc = "function([direction:number=6]):number -- Returns the maximum amount of stored energy for the given side.")
public Object[] getMaxEnergyStored(final Context context, final Arguments args) {
final ForgeDirection side = args.count() > 0 ? ForgeDirection.getOrientation(args.checkInteger(0)) : ForgeDirection.UNKNOWN;
return new Object[]{tileEntity.getMaxEnergyStored(side)};
}
@Callback(doc = "function():number -- Returns whether this component can provide energy.")
public Object[] isEnergyProvider(final Context context, final Arguments args) {
return new Object[]{true};
}
@Callback(doc = "function():number -- Returns whether this component can receive energy.")
public Object[] isEnergyReceiver(final Context context, final Arguments args) {
return new Object[]{tileEntity instanceof IEnergyReceiver};
}
}
}

View File

@ -0,0 +1,57 @@
package li.cil.oc.integration.cofh.energy;
import cofh.api.energy.IEnergyProvider;
import cofh.api.energy.IEnergyReceiver;
import li.cil.oc.api.machine.Arguments;
import li.cil.oc.api.machine.Callback;
import li.cil.oc.api.machine.Context;
import li.cil.oc.api.network.ManagedEnvironment;
import li.cil.oc.api.prefab.DriverTileEntity;
import li.cil.oc.integration.ManagedTileEntityEnvironment;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public final class DriverEnergyReceiver extends DriverTileEntity {
@Override
public Class<?> getTileEntityClass() {
return IEnergyReceiver.class;
}
@Override
public boolean worksWith(World world, int x, int y, int z) {
return super.worksWith(world, x, y, z) && !(world.getTileEntity(x, y, z) instanceof IEnergyProvider);
}
@Override
public ManagedEnvironment createEnvironment(final World world, final int x, final int y, final int z) {
return new Environment((IEnergyReceiver) world.getTileEntity(x, y, z));
}
public static final class Environment extends ManagedTileEntityEnvironment<IEnergyReceiver> {
public Environment(final IEnergyReceiver tileEntity) {
super(tileEntity, "energy_handler");
}
@Callback(doc = "function([direction:number=6]):number -- Returns the amount of stored energy for the given side.")
public Object[] getEnergyStored(final Context context, final Arguments args) {
final ForgeDirection side = args.count() > 0 ? ForgeDirection.getOrientation(args.checkInteger(0)) : ForgeDirection.UNKNOWN;
return new Object[]{tileEntity.getEnergyStored(side)};
}
@Callback(doc = "function([direction:number=6]):number -- Returns the maximum amount of stored energy for the given side.")
public Object[] getMaxEnergyStored(final Context context, final Arguments args) {
final ForgeDirection side = args.count() > 0 ? ForgeDirection.getOrientation(args.checkInteger(0)) : ForgeDirection.UNKNOWN;
return new Object[]{tileEntity.getMaxEnergyStored(side)};
}
@Callback(doc = "function():number -- Returns whether this component can provide energy.")
public Object[] isEnergyProvider(final Context context, final Arguments args) {
return new Object[]{false};
}
@Callback(doc = "function():number -- Returns whether this component can receive energy.")
public Object[] isEnergyReceiver(final Context context, final Arguments args) {
return new Object[]{true};
}
}
}

View File

@ -1,20 +1,33 @@
package li.cil.oc.integration.cofh.energy
import cpw.mods.fml.common.ModAPIManager
import cpw.mods.fml.common.event.FMLInterModComms
import cpw.mods.fml.common.versioning.VersionRange
import li.cil.oc.api.Driver
import li.cil.oc.integration.ModProxy
import li.cil.oc.integration.Mods
import net.minecraftforge.common.MinecraftForge
import scala.collection.convert.WrapAsScala._
object ModCoFHEnergy extends ModProxy {
override def getMod = Mods.CoFHEnergy
private val versionsUsingSplitEnergyAPI = VersionRange.createFromVersionSpec("[1.0.0,)")
override def initialize() {
FMLInterModComms.sendMessage(Mods.IDs.OpenComputers, "registerToolDurabilityProvider", "li.cil.oc.integration.cofh.energy.EventHandlerRedstoneFlux.getDurability")
MinecraftForge.EVENT_BUS.register(EventHandlerRedstoneFlux)
Driver.add(new DriverEnergyHandler)
val apiVersion = ModAPIManager.INSTANCE.getAPIList.find(_.getModId == Mods.IDs.CoFHEnergy).map(_.getProcessedVersion)
if (apiVersion.exists(versionsUsingSplitEnergyAPI.containsVersion)) {
Driver.add(new DriverEnergyProvider)
Driver.add(new DriverEnergyReceiver)
}
else {
Driver.add(new DriverEnergyHandler)
}
Driver.add(new ConverterEnergyContainerItem)
}

View File

@ -25,6 +25,7 @@ import net.minecraftforge.common.util.ForgeDirection
import scala.collection.convert.WrapAsJava._
import scala.collection.convert.WrapAsScala._
import scala.language.existentials
class Geolyzer(val host: EnvironmentHost) extends prefab.ManagedEnvironment {
override val node = api.Network.newNode(this, Visibility.Network).

View File

@ -1,27 +1,15 @@
package li.cil.oc.server.component
import java.io.BufferedWriter
import java.io.FileNotFoundException
import java.io.IOException
import java.io.InputStream
import java.io.OutputStreamWriter
import java.io.{BufferedWriter, FileNotFoundException, IOException, InputStream, OutputStreamWriter}
import java.net._
import java.nio.ByteBuffer
import java.nio.channels.SocketChannel
import java.util.concurrent.Callable
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.ExecutionException
import java.util.concurrent.Future
import java.util.concurrent.{Callable, ConcurrentLinkedQueue, ExecutionException, Future}
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.Network
import li.cil.oc.api.machine.Arguments
import li.cil.oc.api.machine.Callback
import li.cil.oc.api.machine.Context
import li.cil.oc.{OpenComputers, Settings, api}
import li.cil.oc.api.machine.{Arguments, Callback, Context}
import li.cil.oc.api.network._
import li.cil.oc.api.prefab
import li.cil.oc.api.{Network, prefab}
import li.cil.oc.api.prefab.AbstractValue
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ThreadPoolFactory
@ -239,28 +227,30 @@ object InternetCard {
})
}
private def checkConnected() = try {
private def checkConnected() = {
if (owner.isEmpty) throw new IOException("connection lost")
if (isAddressResolved) channel.finishConnect()
else if (address.isCancelled) {
// I don't think this can ever happen, Justin Case.
channel.close()
throw new IOException("bad connection descriptor")
}
else if (address.isDone) {
// Check for errors.
try address.get catch {
case e: ExecutionException => throw e.getCause
try {
if (isAddressResolved) channel.finishConnect()
else if (address.isCancelled) {
// I don't think this can ever happen, Justin Case.
channel.close()
throw new IOException("bad connection descriptor")
}
isAddressResolved = true
false
else if (address.isDone) {
// Check for errors.
try address.get catch {
case e: ExecutionException => throw e.getCause
}
isAddressResolved = true
false
}
else false
}
catch {
case t: Throwable =>
close()
false
}
else false
}
catch {
case t: Throwable =>
close()
false
}
// This has to be an explicit internal class instead of an anonymous one
@ -430,6 +420,7 @@ object InternetCard {
throw new IOException(Option(e.getMessage).getOrElse(e.toString))
}
}
}
}

View File

@ -2,12 +2,16 @@ package li.cil.oc.server.component
import cpw.mods.fml.common.eventhandler.Event
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.internal
import li.cil.oc.api.network.Message
import li.cil.oc.api.prefab
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.tileentity.TileEntitySign
import net.minecraft.world.WorldServer
import net.minecraftforge.common.MinecraftForge
@ -62,4 +66,20 @@ abstract class UpgradeSign extends prefab.ManagedEnvironment {
MinecraftForge.EVENT_BUS.post(event)
!(event.isCanceled || event.getResult == Event.Result.DENY)
}
override def onMessage(message: Message): Unit = {
super.onMessage(message)
if (message.name == "tablet.use") message.source.host match {
case machine: api.machine.Machine => (machine.host, message.data) match {
case (tablet: internal.Tablet, Array(nbt: NBTTagCompound, stack: ItemStack, player: EntityPlayer, blockPos: BlockPosition, side: ForgeDirection, hitX: java.lang.Float, hitY: java.lang.Float, hitZ: java.lang.Float)) =>
host.world.getTileEntity(blockPos) match {
case sign: TileEntitySign =>
nbt.setString("signText", sign.signText.mkString("\n"))
case _ =>
}
case _ => // Ignore.
}
case _ => // Ignore.
}
}
}

View File

@ -23,6 +23,7 @@ import li.cil.oc.api.network.Message
import li.cil.oc.api.network.Node
import li.cil.oc.api.network.Visibility
import li.cil.oc.api.prefab
import li.cil.oc.common.EventHandler
import li.cil.oc.common.SaveHandler
import li.cil.oc.common.Slot
import li.cil.oc.common.tileentity
@ -257,12 +258,21 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
false
case _ =>
state.push(Machine.State.Stopping)
EventHandler.scheduleClose(this)
true
})
override def crash(message: String) = {
this.message = Option(message)
stop()
state.synchronized {
val result = stop()
if (state.top == Machine.State.Stopping) {
// When crashing, make sure there's no "Running" left in the stack.
state.clear()
state.push(Machine.State.Stopping)
}
result
}
}
override def signal(name: String, args: AnyRef*) = state.synchronized(state.top match {
@ -392,6 +402,8 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
// ----------------------------------------------------------------------- //
def isExecuting = state.synchronized(state.contains(Machine.State.Running))
override val canUpdate = true
override def update() = if (state.synchronized(state.top != Machine.State.Stopped)) {
@ -499,7 +511,9 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
state.pop() // Running, no switchTo to avoid new future.
state.push(Machine.State.SynchronizedReturn)
state.push(Machine.State.Paused)
case Machine.State.Stopping => // Nothing to do, we'll die anyway.
case Machine.State.Stopping =>
state.clear()
state.push(Machine.State.Stopping)
case _ => throw new AssertionError()
}
}
@ -514,7 +528,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
inSynchronizedCall = false
}
assert(state.top != Machine.State.Running)
assert(!isExecuting)
case _ => // Nothing special to do, just avoid match errors.
})
@ -643,7 +657,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
super.load(nbt)
state.pushAll(nbt.getIntArray("state").reverse.map(Machine.State(_)))
state.pushAll(nbt.getIntArray("state").reverseMap(Machine.State(_)))
nbt.getTagList("users", NBT.TAG_STRING).foreach((tag: NBTTagString) => _users += tag.func_150285_a_())
if (nbt.hasKey("message")) {
message = Some(nbt.getString("message"))
@ -703,7 +717,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
}
override def save(nbt: NBTTagCompound): Unit = Machine.this.synchronized {
assert(state.top != Machine.State.Running) // Lock on 'this' should guarantee this.
assert(!isExecuting) // Lock on 'this' should guarantee this.
// Make sure we don't continue running until everything has saved.
pause(0.05)
@ -798,16 +812,25 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
false
}
def tryClose(): Boolean =
if (isExecuting) false
else {
close()
true
}
private def close() = state.synchronized(
if (state.size == 0 || state.top != Machine.State.Stopped) {
state.clear()
state.push(Machine.State.Stopped)
Option(architecture).foreach(_.close())
signals.clear()
uptime = 0
cpuTotal = 0
cpuStart = 0
remainIdle = 0
this.synchronized {
state.clear()
state.push(Machine.State.Stopped)
Option(architecture).foreach(_.close())
signals.clear()
uptime = 0
cpuTotal = 0
cpuStart = 0
remainIdle = 0
}
// Mark state change in owner, to send it to clients.
host.markChanged()
@ -906,10 +929,12 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
crash(Option(result.message).getOrElse("unknown error"))
}
state.push(Machine.State.Paused)
case Machine.State.Stopping => // Nothing to do, we'll die anyway.
case Machine.State.Stopping =>
state.clear()
state.push(Machine.State.Stopping)
case _ => throw new AssertionError("Invalid state in executor post-processing.")
}
assert(state.top != Machine.State.Running)
assert(!isExecuting)
}
}
catch {