mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-19 04:06:43 -04:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
36f93eae9e
26
LICENSE
Normal file
26
LICENSE
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Copyright (c) 2013-2014 Florian "Sangar" Nücke
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
All images / textures and localization strings (resources) are put in the
|
||||||
|
public domain. More specicially, see CC0 1.0 Universal:
|
||||||
|
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
25
LICENSE-jnlua
Normal file
25
LICENSE-jnlua
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
OpenComputers uses the JNLua library, with a patch to allow memory limits:
|
||||||
|
|
||||||
|
http://code.google.com/p/jnlua/issues/detail?id=9
|
||||||
|
|
||||||
|
JNLua is copyrighted and licensed as follows:
|
||||||
|
|
||||||
|
Copyright (C) 2008,2012 Andre Naef
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
19
LICENSE-luaj
Normal file
19
LICENSE-luaj
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2007 LuaJ. All rights reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
22
LICENSE-mods
Normal file
22
LICENSE-mods
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
OpenComputers uses APIs from a couple of other mods.
|
||||||
|
|
||||||
|
To support accepting energy from their respective power systems:
|
||||||
|
- BuildCraft [1], license: Minecraft Mod Public License, see homepage.
|
||||||
|
- Universal Electricity [3], license: Lesser General Public License [4].
|
||||||
|
|
||||||
|
To support bundled redstone input and output:
|
||||||
|
- RedLogic [6], license: MIT License, see thread.
|
||||||
|
- MineFactory Reloaded [7], license: custom, see thread.
|
||||||
|
- Project: Red [9], license: Restricted Public Software License [10].
|
||||||
|
|
||||||
|
For providing a peripheral and reading their floppy disks:
|
||||||
|
- ComputerCraft [8], copyright Daniel Ratcliffe.
|
||||||
|
|
||||||
|
[1] http://www.mod-buildcraft.com/
|
||||||
|
[3] http://universalelectricity.com/
|
||||||
|
[4] http://www.gnu.org/copyleft/lesser.html
|
||||||
|
[6] http://www.minecraftforum.net/topic/1852277-162-redlogic-wip-replacement-for-rp2-wiringlogiccontrollighting/
|
||||||
|
[7] http://www.minecraftforum.net/topic/2016680-162164-powercrystals-mods-minefactoryreloaded-powercrystalscore-and-netherores-updated/
|
||||||
|
[8] http://www.computercraft.info/
|
||||||
|
[9] http://projectredwiki.com/
|
||||||
|
[10] https://github.com/MrTJP/ProjectRed/blob/master/LICENSE.md
|
207
LICENSE-typesafe
Normal file
207
LICENSE-typesafe
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
OpenComputers uses the typesafe config library, it is copyrighted as follows:
|
||||||
|
|
||||||
|
Copyright (C) 2011-2012 Typesafe Inc. <http://typesafe.com>
|
||||||
|
|
||||||
|
It is licensed as follows:
|
||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
@ -1,11 +1,13 @@
|
|||||||
package li.cil.oc.api.fs;
|
package li.cil.oc.api.fs;
|
||||||
|
|
||||||
|
import li.cil.oc.api.Persistable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used by file system components to get and set the file system's label.
|
* Used by file system components to get and set the file system's label.
|
||||||
*
|
*
|
||||||
* @see li.cil.oc.api.FileSystem#asManagedEnvironment(FileSystem, Label)
|
* @see li.cil.oc.api.FileSystem#asManagedEnvironment(FileSystem, Label)
|
||||||
*/
|
*/
|
||||||
public interface Label {
|
public interface Label extends Persistable {
|
||||||
/**
|
/**
|
||||||
* Get the current value of this label.
|
* Get the current value of this label.
|
||||||
* <p/>
|
* <p/>
|
||||||
|
@ -37,5 +37,5 @@
|
|||||||
@cpw.mods.fml.common.API(
|
@cpw.mods.fml.common.API(
|
||||||
owner = "OpenComputers|Core",
|
owner = "OpenComputers|Core",
|
||||||
provides = "OpenComputersAPI",
|
provides = "OpenComputersAPI",
|
||||||
apiVersion = "1.3.0")
|
apiVersion = "1.4.0")
|
||||||
package li.cil.oc.api;
|
package li.cil.oc.api;
|
@ -489,7 +489,7 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
override def installedMemory = 96 * 1024
|
override def installedMemory = 128 * 1024
|
||||||
|
|
||||||
override def tier = 0
|
override def tier = 0
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
|
|||||||
@Callback(doc = """function():boolean -- Returns whether the screen is currently on.""")
|
@Callback(doc = """function():boolean -- Returns whether the screen is currently on.""")
|
||||||
def isOn(computer: Context, args: Arguments): Array[AnyRef] = result(origin.isOn)
|
def isOn(computer: Context, args: Arguments): Array[AnyRef] = result(origin.isOn)
|
||||||
|
|
||||||
@Callback(doc = """function():boolean -- Turns off the screen. Returns true if it was on.""")
|
@Callback(doc = """function():boolean -- Turns the screen on. Returns true if it was off.""")
|
||||||
def turnOn(computer: Context, args: Arguments): Array[AnyRef] = {
|
def turnOn(computer: Context, args: Arguments): Array[AnyRef] = {
|
||||||
if (!origin.isOn) {
|
if (!origin.isOn) {
|
||||||
origin.turnOn()
|
origin.turnOn()
|
||||||
@ -37,7 +37,7 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
|
|||||||
else result(false, origin.isOn)
|
else result(false, origin.isOn)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(doc = """function():boolean -- Turns the screen on. Returns true if it was off.""")
|
@Callback(doc = """function():boolean -- Turns off the screen. Returns true if it was on.""")
|
||||||
def turnOff(computer: Context, args: Arguments): Array[AnyRef] = {
|
def turnOff(computer: Context, args: Arguments): Array[AnyRef] = {
|
||||||
if (origin.isOn) {
|
if (origin.isOn) {
|
||||||
origin.turnOff()
|
origin.turnOff()
|
||||||
|
@ -20,13 +20,15 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
|||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def getLabel(context: Context, args: Arguments): Array[AnyRef] = label match {
|
def getLabel(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
case value: Label => result(label.getLabel)
|
label match {
|
||||||
case _ => null
|
case value: Label => result(label.getLabel)
|
||||||
|
case _ => null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
def setLabel(context: Context, args: Arguments): Array[AnyRef] = {
|
def setLabel(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
if (label == null) throw new Exception("filesystem does not support labeling")
|
if (label == null) throw new Exception("filesystem does not support labeling")
|
||||||
if (args.checkAny(0) == null) label.setLabel(null)
|
if (args.checkAny(0) == null) label.setLabel(null)
|
||||||
else label.setLabel(args.checkString(0))
|
else label.setLabel(args.checkString(0))
|
||||||
@ -34,12 +36,12 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def isReadOnly(context: Context, args: Arguments): Array[AnyRef] = {
|
def isReadOnly(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
result(fileSystem.isReadOnly)
|
result(fileSystem.isReadOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def spaceTotal(context: Context, args: Arguments): Array[AnyRef] = {
|
def spaceTotal(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
val space = fileSystem.spaceTotal
|
val space = fileSystem.spaceTotal
|
||||||
if (space < 0)
|
if (space < 0)
|
||||||
Array("unlimited")
|
Array("unlimited")
|
||||||
@ -48,32 +50,32 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def spaceUsed(context: Context, args: Arguments): Array[AnyRef] = {
|
def spaceUsed(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
result(fileSystem.spaceUsed)
|
result(fileSystem.spaceUsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def exists(context: Context, args: Arguments): Array[AnyRef] = {
|
def exists(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
result(fileSystem.exists(clean(args.checkString(0))))
|
result(fileSystem.exists(clean(args.checkString(0))))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def size(context: Context, args: Arguments): Array[AnyRef] = {
|
def size(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
result(fileSystem.size(clean(args.checkString(0))))
|
result(fileSystem.size(clean(args.checkString(0))))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def isDirectory(context: Context, args: Arguments): Array[AnyRef] = {
|
def isDirectory(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
result(fileSystem.isDirectory(clean(args.checkString(0))))
|
result(fileSystem.isDirectory(clean(args.checkString(0))))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(direct = true)
|
@Callback(direct = true)
|
||||||
def lastModified(context: Context, args: Arguments): Array[AnyRef] = {
|
def lastModified(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
result(fileSystem.lastModified(clean(args.checkString(0))))
|
result(fileSystem.lastModified(clean(args.checkString(0))))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
def list(context: Context, args: Arguments): Array[AnyRef] = {
|
def list(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
Option(fileSystem.list(clean(args.checkString(0)))) match {
|
Option(fileSystem.list(clean(args.checkString(0)))) match {
|
||||||
case Some(list) => Array(list)
|
case Some(list) => Array(list)
|
||||||
case _ => null
|
case _ => null
|
||||||
@ -81,26 +83,26 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
def makeDirectory(context: Context, args: Arguments): Array[AnyRef] = {
|
def makeDirectory(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
def recurse(path: String): Boolean = !fileSystem.exists(path) && (fileSystem.makeDirectory(path) ||
|
def recurse(path: String): Boolean = !fileSystem.exists(path) && (fileSystem.makeDirectory(path) ||
|
||||||
(recurse(path.split("/").dropRight(1).mkString("/")) && fileSystem.makeDirectory(path)))
|
(recurse(path.split("/").dropRight(1).mkString("/")) && fileSystem.makeDirectory(path)))
|
||||||
result(recurse(clean(args.checkString(0))))
|
result(recurse(clean(args.checkString(0))))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
def remove(context: Context, args: Arguments): Array[AnyRef] = {
|
def remove(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
def recurse(parent: String): Boolean = (!fileSystem.isDirectory(parent) ||
|
def recurse(parent: String): Boolean = (!fileSystem.isDirectory(parent) ||
|
||||||
fileSystem.list(parent).forall(child => recurse(parent + "/" + child))) && fileSystem.delete(parent)
|
fileSystem.list(parent).forall(child => recurse(parent + "/" + child))) && fileSystem.delete(parent)
|
||||||
result(recurse(clean(args.checkString(0))))
|
result(recurse(clean(args.checkString(0))))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
def rename(context: Context, args: Arguments): Array[AnyRef] = {
|
def rename(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
result(fileSystem.rename(clean(args.checkString(0)), clean(args.checkString(1))))
|
result(fileSystem.rename(clean(args.checkString(0)), clean(args.checkString(1))))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback(direct = true)
|
||||||
def close(context: Context, args: Arguments): Array[AnyRef] = {
|
def close(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
val handle = args.checkInteger(0)
|
val handle = args.checkInteger(0)
|
||||||
Option(fileSystem.getHandle(handle)) match {
|
Option(fileSystem.getHandle(handle)) match {
|
||||||
case Some(file) =>
|
case Some(file) =>
|
||||||
@ -113,8 +115,8 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback(direct = true, limit = 4)
|
||||||
def open(context: Context, args: Arguments): Array[AnyRef] = {
|
def open(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
if (owners.get(context.node.address).fold(false)(_.size >= Settings.get.maxHandles)) {
|
if (owners.get(context.node.address).fold(false)(_.size >= Settings.get.maxHandles)) {
|
||||||
throw new IOException("too many open handles")
|
throw new IOException("too many open handles")
|
||||||
}
|
}
|
||||||
@ -127,8 +129,8 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
|||||||
result(handle)
|
result(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback(direct = true, limit = 4)
|
||||||
def read(context: Context, args: Arguments): Array[AnyRef] = {
|
def read(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
val handle = args.checkInteger(0)
|
val handle = args.checkInteger(0)
|
||||||
val n = math.min(Settings.get.maxReadBuffer, math.max(0, args.checkInteger(1)))
|
val n = math.min(Settings.get.maxReadBuffer, math.max(0, args.checkInteger(1)))
|
||||||
checkOwner(context.node.address, handle)
|
checkOwner(context.node.address, handle)
|
||||||
@ -158,8 +160,8 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback(direct = true, limit = 4)
|
||||||
def seek(context: Context, args: Arguments): Array[AnyRef] = {
|
def seek(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
val handle = args.checkInteger(0)
|
val handle = args.checkInteger(0)
|
||||||
val whence = args.checkString(1)
|
val whence = args.checkString(1)
|
||||||
val offset = args.checkInteger(2)
|
val offset = args.checkInteger(2)
|
||||||
@ -178,7 +180,7 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
def write(context: Context, args: Arguments): Array[AnyRef] = {
|
def write(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||||
val handle = args.checkInteger(0)
|
val handle = args.checkInteger(0)
|
||||||
val value = args.checkByteArray(1)
|
val value = args.checkByteArray(1)
|
||||||
if (!node.tryChangeBuffer(-Settings.get.hddWriteCost * value.length)) {
|
if (!node.tryChangeBuffer(-Settings.get.hddWriteCost * value.length)) {
|
||||||
@ -243,6 +245,7 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
label.load(nbt.getCompoundTag("label"))
|
||||||
fileSystem.load(nbt.getCompoundTag("fs"))
|
fileSystem.load(nbt.getCompoundTag("fs"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,6 +265,7 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
|||||||
}
|
}
|
||||||
nbt.setTag("owners", ownersNbt)
|
nbt.setTag("owners", ownersNbt)
|
||||||
|
|
||||||
|
nbt.setNewCompoundTag("label", label.save)
|
||||||
nbt.setNewCompoundTag("fs", fileSystem.save)
|
nbt.setNewCompoundTag("fs", fileSystem.save)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +65,15 @@ trait Architecture {
|
|||||||
*/
|
*/
|
||||||
def init(): Boolean
|
def init(): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the owning machine was connected to the component network.
|
||||||
|
*
|
||||||
|
* This can be useful for connecting custom file systems (read only memory)
|
||||||
|
* in case init() was called from the machine's load() method (where it was
|
||||||
|
* not yet connected to the network).
|
||||||
|
*/
|
||||||
|
def onConnect()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a computer stopped. Used to clean up any handles, memory and
|
* Called when a computer stopped. Used to clean up any handles, memory and
|
||||||
* so on. For example, for Lua this destroys the Lua state.
|
* so on. For example, for Lua this destroys the Lua state.
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
package li.cil.oc.server.component.machine
|
||||||
|
|
||||||
|
import li.cil.oc.api.FileSystem
|
||||||
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
|
import li.cil.oc.{Settings, OpenComputers}
|
||||||
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
|
||||||
|
abstract class LuaArchitecture(val machine: Machine) extends Architecture {
|
||||||
|
val rom = Option(FileSystem.asManagedEnvironment(FileSystem.
|
||||||
|
fromClass(OpenComputers.getClass, Settings.resourceDomain, "lua/rom"), "rom"))
|
||||||
|
|
||||||
|
override def init() = {
|
||||||
|
if (machine.node.network != null) {
|
||||||
|
rom.foreach(fs => machine.node.connect(fs.node))
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
override def onConnect() {
|
||||||
|
rom.foreach(fs => machine.node.connect(fs.node))
|
||||||
|
}
|
||||||
|
|
||||||
|
override def close() {
|
||||||
|
rom.foreach(_.node.remove())
|
||||||
|
}
|
||||||
|
|
||||||
|
override def load(nbt: NBTTagCompound) {
|
||||||
|
rom.foreach(fs => fs.load(nbt.getCompoundTag("rom")))
|
||||||
|
}
|
||||||
|
|
||||||
|
override def save(nbt: NBTTagCompound) {
|
||||||
|
rom.foreach(fs => nbt.setNewCompoundTag("rom", fs.save))
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@ import org.luaj.vm3.lib.jse.JsePlatform
|
|||||||
import scala.Some
|
import scala.Some
|
||||||
import scala.collection.convert.WrapAsScala._
|
import scala.collection.convert.WrapAsScala._
|
||||||
|
|
||||||
class LuaJLuaArchitecture(machine: Machine) extends Architecture {
|
class LuaJLuaArchitecture(machine: Machine) extends LuaArchitecture(machine) {
|
||||||
private var lua: Globals = _
|
private var lua: Globals = _
|
||||||
|
|
||||||
private var thread: LuaThread = _
|
private var thread: LuaThread = _
|
||||||
@ -132,6 +132,8 @@ class LuaJLuaArchitecture(machine: Machine) extends Architecture {
|
|||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
override def init() = {
|
override def init() = {
|
||||||
|
super.init()
|
||||||
|
|
||||||
lua = JsePlatform.debugGlobals()
|
lua = JsePlatform.debugGlobals()
|
||||||
lua.set("package", LuaValue.NIL)
|
lua.set("package", LuaValue.NIL)
|
||||||
lua.set("io", LuaValue.NIL)
|
lua.set("io", LuaValue.NIL)
|
||||||
@ -251,13 +253,13 @@ class LuaJLuaArchitecture(machine: Machine) extends Architecture {
|
|||||||
computer.set("pushSignal", (args: Varargs) => LuaValue.valueOf(machine.signal(args.checkjstring(1), toSimpleJavaObjects(args, 2): _*)))
|
computer.set("pushSignal", (args: Varargs) => LuaValue.valueOf(machine.signal(args.checkjstring(1), toSimpleJavaObjects(args, 2): _*)))
|
||||||
|
|
||||||
// And its ROM address.
|
// And its ROM address.
|
||||||
computer.set("romAddress", (_: Varargs) => machine.rom.fold(LuaValue.NIL)(rom => Option(rom.node.address) match {
|
computer.set("romAddress", (_: Varargs) => rom.fold(LuaValue.NIL)(fs => Option(fs.node.address) match {
|
||||||
case Some(address) => LuaValue.valueOf(address)
|
case Some(address) => LuaValue.valueOf(address)
|
||||||
case _ => LuaValue.NIL
|
case _ => LuaValue.NIL
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// And it's /tmp address...
|
// And it's /tmp address...
|
||||||
computer.set("tmpAddress", (_: Varargs) => machine.tmp.fold(LuaValue.NIL)(tmp => Option(tmp.node.address) match {
|
computer.set("tmpAddress", (_: Varargs) => machine.tmp.fold(LuaValue.NIL)(fs => Option(fs.node.address) match {
|
||||||
case Some(address) => LuaValue.valueOf(address)
|
case Some(address) => LuaValue.valueOf(address)
|
||||||
case _ => LuaValue.NIL
|
case _ => LuaValue.NIL
|
||||||
}))
|
}))
|
||||||
@ -375,6 +377,8 @@ class LuaJLuaArchitecture(machine: Machine) extends Architecture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override def close() = {
|
override def close() = {
|
||||||
|
super.close()
|
||||||
|
|
||||||
lua = null
|
lua = null
|
||||||
thread = null
|
thread = null
|
||||||
synchronizedCall = null
|
synchronizedCall = null
|
||||||
@ -385,11 +389,11 @@ class LuaJLuaArchitecture(machine: Machine) extends Architecture {
|
|||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
override def load(nbt: NBTTagCompound) {
|
override def load(nbt: NBTTagCompound) {
|
||||||
|
super.load(nbt)
|
||||||
|
|
||||||
if (machine.isRunning) {
|
if (machine.isRunning) {
|
||||||
machine.stop()
|
machine.stop()
|
||||||
machine.start()
|
machine.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override def save(nbt: NBTTagCompound) {}
|
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,6 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
|||||||
withConnector(if (isRobot) Settings.get.bufferRobot + 30 * Settings.get.bufferPerLevel else Settings.get.bufferComputer).
|
withConnector(if (isRobot) Settings.get.bufferRobot + 30 * Settings.get.bufferPerLevel else Settings.get.bufferComputer).
|
||||||
create()
|
create()
|
||||||
|
|
||||||
val rom = Option(FileSystem.asManagedEnvironment(FileSystem.
|
|
||||||
fromClass(OpenComputers.getClass, Settings.resourceDomain, "lua/rom"), "rom"))
|
|
||||||
|
|
||||||
val tmp = if (Settings.get.tmpSize > 0) {
|
val tmp = if (Settings.get.tmpSize > 0) {
|
||||||
Option(FileSystem.asManagedEnvironment(FileSystem.
|
Option(FileSystem.asManagedEnvironment(FileSystem.
|
||||||
fromMemory(Settings.get.tmpSize * 1024), "tmpfs"))
|
fromMemory(Settings.get.tmpSize * 1024), "tmpfs"))
|
||||||
@ -208,7 +205,7 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
|||||||
Option(node.network.node(address)) match {
|
Option(node.network.node(address)) match {
|
||||||
case Some(component: server.network.Component) if component.canBeSeenFrom(node) || component == node =>
|
case Some(component: server.network.Component) if component.canBeSeenFrom(node) || component == node =>
|
||||||
val direct = component.isDirect(method)
|
val direct = component.isDirect(method)
|
||||||
if (direct) callCounts.synchronized {
|
if (direct && architecture.isInitialized) callCounts.synchronized {
|
||||||
val limit = component.limit(method)
|
val limit = component.limit(method)
|
||||||
val counts = callCounts.getOrElseUpdate(component.address, mutable.Map.empty[String, Int])
|
val counts = callCounts.getOrElseUpdate(component.address, mutable.Map.empty[String, Int])
|
||||||
val count = counts.getOrElseUpdate(method, 0)
|
val count = counts.getOrElseUpdate(method, 0)
|
||||||
@ -424,8 +421,8 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
|||||||
override def onConnect(node: Node) {
|
override def onConnect(node: Node) {
|
||||||
if (node == this.node) {
|
if (node == this.node) {
|
||||||
components += this.node.address -> this.node.name
|
components += this.node.address -> this.node.name
|
||||||
rom.foreach(rom => node.connect(rom.node))
|
|
||||||
tmp.foreach(tmp => node.connect(tmp.node))
|
tmp.foreach(tmp => node.connect(tmp.node))
|
||||||
|
architecture.onConnect()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
node match {
|
node match {
|
||||||
@ -439,8 +436,7 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
|||||||
|
|
||||||
override def onDisconnect(node: Node) {
|
override def onDisconnect(node: Node) {
|
||||||
if (node == this.node) {
|
if (node == this.node) {
|
||||||
stop()
|
close()
|
||||||
rom.foreach(_.node.remove())
|
|
||||||
tmp.foreach(_.node.remove())
|
tmp.foreach(_.node.remove())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -522,7 +518,6 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
|||||||
components ++= nbt.getTagList("components").iterator[NBTTagCompound].map(c =>
|
components ++= nbt.getTagList("components").iterator[NBTTagCompound].map(c =>
|
||||||
c.getString("address") -> c.getString("name"))
|
c.getString("address") -> c.getString("name"))
|
||||||
|
|
||||||
rom.foreach(rom => rom.load(nbt.getCompoundTag("rom")))
|
|
||||||
tmp.foreach(tmp => tmp.load(nbt.getCompoundTag("tmp")))
|
tmp.foreach(tmp => tmp.load(nbt.getCompoundTag("tmp")))
|
||||||
|
|
||||||
if (state.size > 0 && state.top != Machine.State.Stopped && init()) {
|
if (state.size > 0 && state.top != Machine.State.Stopped && init()) {
|
||||||
@ -587,7 +582,6 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
|||||||
}
|
}
|
||||||
nbt.setTag("components", componentsNbt)
|
nbt.setTag("components", componentsNbt)
|
||||||
|
|
||||||
rom.foreach(rom => nbt.setNewCompoundTag("rom", rom.save))
|
|
||||||
tmp.foreach(tmp => nbt.setNewCompoundTag("tmp", tmp.save))
|
tmp.foreach(tmp => nbt.setNewCompoundTag("tmp", tmp.save))
|
||||||
|
|
||||||
if (state.top != Machine.State.Stopped) {
|
if (state.top != Machine.State.Stopped) {
|
||||||
@ -637,7 +631,6 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi
|
|||||||
// Connect the ROM and `/tmp` node to our owner. We're not in a network in
|
// Connect the ROM and `/tmp` node to our owner. We're not in a network in
|
||||||
// case we're loading, which is why we have to check it here.
|
// case we're loading, which is why we have to check it here.
|
||||||
if (node.network != null) {
|
if (node.network != null) {
|
||||||
rom.foreach(rom => node.connect(rom.node))
|
|
||||||
tmp.foreach(tmp => node.connect(tmp.node))
|
tmp.foreach(tmp => node.connect(tmp.node))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import scala.Some
|
|||||||
import scala.collection.convert.WrapAsScala._
|
import scala.collection.convert.WrapAsScala._
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
|
|
||||||
class NativeLuaArchitecture(val machine: Machine) extends Architecture {
|
class NativeLuaArchitecture(machine: Machine) extends LuaArchitecture(machine) {
|
||||||
private var lua: LuaState = null
|
private var lua: LuaState = null
|
||||||
|
|
||||||
private var kernelMemory = 0
|
private var kernelMemory = 0
|
||||||
@ -179,6 +179,8 @@ class NativeLuaArchitecture(val machine: Machine) extends Architecture {
|
|||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
override def init(): Boolean = {
|
override def init(): Boolean = {
|
||||||
|
super.init()
|
||||||
|
|
||||||
// Creates a new state with all base libraries and the persistence library
|
// Creates a new state with all base libraries and the persistence library
|
||||||
// loaded into it. This means the state has much more power than it
|
// loaded into it. This means the state has much more power than it
|
||||||
// rightfully should have, so we sandbox it a bit in the following.
|
// rightfully should have, so we sandbox it a bit in the following.
|
||||||
@ -321,7 +323,7 @@ class NativeLuaArchitecture(val machine: Machine) extends Architecture {
|
|||||||
|
|
||||||
// And its ROM address.
|
// And its ROM address.
|
||||||
lua.pushScalaFunction(lua => {
|
lua.pushScalaFunction(lua => {
|
||||||
machine.rom.foreach(rom => Option(rom.node.address) match {
|
rom.foreach(fs => Option(fs.node.address) match {
|
||||||
case None => lua.pushNil()
|
case None => lua.pushNil()
|
||||||
case Some(address) => lua.pushString(address)
|
case Some(address) => lua.pushString(address)
|
||||||
})
|
})
|
||||||
@ -331,7 +333,7 @@ class NativeLuaArchitecture(val machine: Machine) extends Architecture {
|
|||||||
|
|
||||||
// And it's /tmp address...
|
// And it's /tmp address...
|
||||||
lua.pushScalaFunction(lua => {
|
lua.pushScalaFunction(lua => {
|
||||||
machine.tmp.foreach(tmp => Option(tmp.node.address) match {
|
machine.tmp.foreach(fs => Option(fs.node.address) match {
|
||||||
case None => lua.pushNil()
|
case None => lua.pushNil()
|
||||||
case Some(address) => lua.pushString(address)
|
case Some(address) => lua.pushString(address)
|
||||||
})
|
})
|
||||||
@ -563,6 +565,8 @@ class NativeLuaArchitecture(val machine: Machine) extends Architecture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override def close() {
|
override def close() {
|
||||||
|
super.close()
|
||||||
|
|
||||||
if (lua != null) {
|
if (lua != null) {
|
||||||
lua.setTotalMemory(Integer.MAX_VALUE)
|
lua.setTotalMemory(Integer.MAX_VALUE)
|
||||||
lua.close()
|
lua.close()
|
||||||
@ -574,6 +578,8 @@ class NativeLuaArchitecture(val machine: Machine) extends Architecture {
|
|||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
override def load(nbt: NBTTagCompound) {
|
override def load(nbt: NBTTagCompound) {
|
||||||
|
super.load(nbt)
|
||||||
|
|
||||||
// Unlimit memory use while unpersisting.
|
// Unlimit memory use while unpersisting.
|
||||||
lua.setTotalMemory(Integer.MAX_VALUE)
|
lua.setTotalMemory(Integer.MAX_VALUE)
|
||||||
|
|
||||||
@ -609,6 +615,8 @@ class NativeLuaArchitecture(val machine: Machine) extends Architecture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override def save(nbt: NBTTagCompound) {
|
override def save(nbt: NBTTagCompound) {
|
||||||
|
super.save(nbt)
|
||||||
|
|
||||||
// Unlimit memory while persisting.
|
// Unlimit memory while persisting.
|
||||||
lua.setTotalMemory(Integer.MAX_VALUE)
|
lua.setTotalMemory(Integer.MAX_VALUE)
|
||||||
|
|
||||||
|
@ -121,24 +121,22 @@ class Player(val robot: tileentity.Robot) extends EntityPlayer(robot.world, Sett
|
|||||||
val block = Block.blocksList(blockId)
|
val block = Block.blocksList(blockId)
|
||||||
val canActivate = block != null && Settings.get.allowActivateBlocks
|
val canActivate = block != null && Settings.get.allowActivateBlocks
|
||||||
val shouldActivate = canActivate && (!isSneaking || (item == null || item.shouldPassSneakingClickToBlock(world, x, y, z)))
|
val shouldActivate = canActivate && (!isSneaking || (item == null || item.shouldPassSneakingClickToBlock(world, x, y, z)))
|
||||||
if (shouldActivate && block.onBlockActivated(world, x, y, z, this, side, hitX, hitY, hitZ)) {
|
val result =
|
||||||
return ActivationType.BlockActivated
|
if (shouldActivate && block.onBlockActivated(world, x, y, z, this, side, hitX, hitY, hitZ))
|
||||||
}
|
ActivationType.BlockActivated
|
||||||
|
else if (tryPlaceBlockWhileHandlingFunnySpecialCases(stack, x, y, z, side, hitX, hitY, hitZ))
|
||||||
|
ActivationType.ItemPlaced
|
||||||
|
else if (tryUseItem(stack, duration))
|
||||||
|
ActivationType.ItemUsed
|
||||||
|
else
|
||||||
|
ActivationType.None
|
||||||
|
|
||||||
if (stack != null) {
|
if (stack != null) {
|
||||||
val didPlace = tryPlaceBlockWhileHandlingFunnySpecialCases(stack, x, y, z, side, hitX, hitY, hitZ)
|
|
||||||
if (stack.stackSize <= 0) ForgeEventFactory.onPlayerDestroyItem(this, stack)
|
if (stack.stackSize <= 0) ForgeEventFactory.onPlayerDestroyItem(this, stack)
|
||||||
if (stack.stackSize <= 0) inventory.setInventorySlotContents(0, null)
|
if (stack.stackSize <= 0) inventory.setInventorySlotContents(0, null)
|
||||||
if (didPlace) {
|
|
||||||
return ActivationType.ItemPlaced
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tryUseItem(stack, duration)) {
|
|
||||||
return ActivationType.ItemUsed
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ActivationType.None
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
def useEquippedItem(duration: Double) = {
|
def useEquippedItem(duration: Double) = {
|
||||||
@ -324,14 +322,16 @@ class Player(val robot: tileentity.Robot) extends EntityPlayer(robot.world, Sett
|
|||||||
}
|
}
|
||||||
|
|
||||||
private def tryPlaceBlockWhileHandlingFunnySpecialCases(stack: ItemStack, x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float) = {
|
private def tryPlaceBlockWhileHandlingFunnySpecialCases(stack: ItemStack, x: Int, y: Int, z: Int, side: Int, hitX: Float, hitY: Float, hitZ: Float) = {
|
||||||
val fakeEyeHeight = if (rotationPitch < 0 && isSomeKindOfPiston(stack)) 1.82 else 0
|
stack != null && stack.stackSize > 0 && {
|
||||||
setPosition(posX, posY - fakeEyeHeight, posZ)
|
val fakeEyeHeight = if (rotationPitch < 0 && isSomeKindOfPiston(stack)) 1.82 else 0
|
||||||
val didPlace = stack.tryPlaceItemIntoWorld(this, world, x, y, z, side, hitX, hitY, hitZ)
|
setPosition(posX, posY - fakeEyeHeight, posZ)
|
||||||
setPosition(posX, posY + fakeEyeHeight, posZ)
|
val didPlace = stack.tryPlaceItemIntoWorld(this, world, x, y, z, side, hitX, hitY, hitZ)
|
||||||
if (didPlace) {
|
setPosition(posX, posY + fakeEyeHeight, posZ)
|
||||||
robot.addXp(Settings.get.robotActionXp)
|
if (didPlace) {
|
||||||
|
robot.addXp(Settings.get.robotActionXp)
|
||||||
|
}
|
||||||
|
didPlace
|
||||||
}
|
}
|
||||||
didPlace
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private def isSomeKindOfPiston(stack: ItemStack) =
|
private def isSomeKindOfPiston(stack: ItemStack) =
|
||||||
|
@ -72,17 +72,32 @@ object FileSystem extends Item {
|
|||||||
override def setLabel(value: String) {
|
override def setLabel(value: String) {
|
||||||
media.setLabel(stack, value)
|
media.setLabel(stack, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def load(nbt: NBTTagCompound) {}
|
||||||
|
|
||||||
|
override def save(nbt: NBTTagCompound) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ItemLabel(val stack: ItemStack) extends Label {
|
private class ItemLabel(val stack: ItemStack) extends Label {
|
||||||
override def getLabel =
|
var label: Option[String] = None
|
||||||
if (dataTag(stack).hasKey(Settings.namespace + "fs.label"))
|
|
||||||
dataTag(stack).getString(Settings.namespace + "fs.label")
|
override def getLabel = label.orNull
|
||||||
else null
|
|
||||||
|
|
||||||
override def setLabel(value: String) {
|
override def setLabel(value: String) {
|
||||||
dataTag(stack).setString(Settings.namespace + "fs.label",
|
label = Option(if (value != null && value.length > 16) value.substring(0, 16) else value)
|
||||||
if (value.length > 16) value.substring(0, 16) else value)
|
}
|
||||||
|
|
||||||
|
override def load(nbt: NBTTagCompound) {
|
||||||
|
if (dataTag(stack).hasKey(Settings.namespace + "fs.label")) {
|
||||||
|
label = Option(dataTag(stack).getString(Settings.namespace + "fs.label"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def save(nbt: NBTTagCompound) {
|
||||||
|
label match {
|
||||||
|
case Some(value) => dataTag(stack).setString(Settings.namespace + "fs.label", value)
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import li.cil.oc.api.fs.Label
|
|||||||
import li.cil.oc.server.component
|
import li.cil.oc.server.component
|
||||||
import li.cil.oc.{Settings, api}
|
import li.cil.oc.{Settings, api}
|
||||||
import net.minecraftforge.common.DimensionManager
|
import net.minecraftforge.common.DimensionManager
|
||||||
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
|
||||||
object FileSystem extends api.detail.FileSystemAPI {
|
object FileSystem extends api.detail.FileSystemAPI {
|
||||||
override def fromClass(clazz: Class[_], domain: String, root: String): api.fs.FileSystem = {
|
override def fromClass(clazz: Class[_], domain: String, root: String): api.fs.FileSystem = {
|
||||||
@ -84,6 +85,10 @@ object FileSystem extends api.detail.FileSystemAPI {
|
|||||||
def setLabel(value: String) = throw new IllegalArgumentException("label is read only")
|
def setLabel(value: String) = throw new IllegalArgumentException("label is read only")
|
||||||
|
|
||||||
def getLabel = label
|
def getLabel = label
|
||||||
|
|
||||||
|
override def load(nbt: NBTTagCompound) {}
|
||||||
|
|
||||||
|
override def save(nbt: NBTTagCompound) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ReadOnlyFileSystem(protected val root: io.File)
|
private class ReadOnlyFileSystem(protected val root: io.File)
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
local event = require("event")
|
local event = require("event")
|
||||||
local fs = require("filesystem")
|
local fs = require("filesystem")
|
||||||
local shell = require("shell")
|
local process = require("process")
|
||||||
|
|
||||||
local proxy = ...
|
local proxy = ...
|
||||||
|
|
||||||
-- Install symlinks if they don't already exist.
|
-- Install symlinks if they don't already exist.
|
||||||
local links = {}
|
local links = {}
|
||||||
local fsroot = fs.path(shell.running())
|
local fsroot = fs.path(process.running())
|
||||||
local function inject(path)
|
local function inject(path)
|
||||||
for file in fs.list(fs.concat(fsroot, path)) do
|
for file in fs.list(fs.concat(fsroot, path)) do
|
||||||
local source = fs.concat(fsroot, path, file)
|
local source = fs.concat(fsroot, path, file)
|
||||||
|
@ -6,7 +6,7 @@ local internet = require("internet")
|
|||||||
local shell = require("shell")
|
local shell = require("shell")
|
||||||
|
|
||||||
if not component.isAvailable("internet") then
|
if not component.isAvailable("internet") then
|
||||||
io.write("This program requires an internet card to run.")
|
io.stderr:write("This program requires an internet card to run.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ local args, options = shell.parse(...)
|
|||||||
local function get(pasteId, filename)
|
local function get(pasteId, filename)
|
||||||
local f, reason = io.open(filename, "w")
|
local f, reason = io.open(filename, "w")
|
||||||
if not f then
|
if not f then
|
||||||
io.write("Failed opening file for writing: ", reason)
|
io.stderr:write("Failed opening file for writing: ", reason)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -35,9 +35,10 @@ local function get(pasteId, filename)
|
|||||||
f:close()
|
f:close()
|
||||||
io.write("Saved data to ", filename, "\n")
|
io.write("Saved data to ", filename, "\n")
|
||||||
else
|
else
|
||||||
|
io.write("failed.\n")
|
||||||
f:close()
|
f:close()
|
||||||
fs.remove(filename)
|
fs.remove(filename)
|
||||||
io.write("HTTP request failed: ", response, "\n")
|
io.stderr:write("HTTP request failed: ", response, "\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -61,7 +62,7 @@ function run(pasteId, ...)
|
|||||||
|
|
||||||
local success, reason = shell.execute(tmpFile, nil, ...)
|
local success, reason = shell.execute(tmpFile, nil, ...)
|
||||||
if not success then
|
if not success then
|
||||||
io.write(reason)
|
io.stderr:write(reason)
|
||||||
end
|
end
|
||||||
fs.remove(tmpFile)
|
fs.remove(tmpFile)
|
||||||
end
|
end
|
||||||
@ -73,14 +74,14 @@ function put(path)
|
|||||||
if configFile then
|
if configFile then
|
||||||
local result, reason = pcall(configFile)
|
local result, reason = pcall(configFile)
|
||||||
if not result then
|
if not result then
|
||||||
io.write("Failed loading config: ", reason)
|
io.stderr:write("Failed loading config: ", reason)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
config.key = config.key or "fd92bd40a84c127eeb6804b146793c97"
|
config.key = config.key or "fd92bd40a84c127eeb6804b146793c97"
|
||||||
local file, reason = io.open(path, "r")
|
local file, reason = io.open(path, "r")
|
||||||
|
|
||||||
if not file then
|
if not file then
|
||||||
io.write("Failed opening file for reading: ", reason)
|
io.stderr:write("Failed opening file for reading: ", reason)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -112,7 +113,8 @@ function put(path)
|
|||||||
io.write('Run "pastebin get ', pasteId, '" to download anywhere.')
|
io.write('Run "pastebin get ', pasteId, '" to download anywhere.')
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
io.write("failed: ", response)
|
io.write("failed.\n")
|
||||||
|
io.stderr:write(response)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -127,7 +129,7 @@ elseif command == "get" then
|
|||||||
local path = shell.resolve(args[3])
|
local path = shell.resolve(args[3])
|
||||||
if fs.exists(path) then
|
if fs.exists(path) then
|
||||||
if not options.f or not os.remove(path) then
|
if not options.f or not os.remove(path) then
|
||||||
io.write("file already exists")
|
io.stderr:write("file already exists")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -5,7 +5,7 @@ local shell = require("shell")
|
|||||||
local text = require("text")
|
local text = require("text")
|
||||||
|
|
||||||
if not component.isAvailable("internet") then
|
if not component.isAvailable("internet") then
|
||||||
io.write("This program requires an internet card to run.")
|
io.stderr:write("This program requires an internet card to run.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -33,21 +33,21 @@ if not filename then
|
|||||||
end
|
end
|
||||||
filename = text.trim(filename)
|
filename = text.trim(filename)
|
||||||
if filename == "" then
|
if filename == "" then
|
||||||
io.write("could not infer filename, please specify one")
|
io.stderr:write("could not infer filename, please specify one")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
filename = shell.resolve(filename)
|
filename = shell.resolve(filename)
|
||||||
|
|
||||||
if fs.exists(filename) then
|
if fs.exists(filename) then
|
||||||
if not options.f or not os.remove(filename) then
|
if not options.f or not os.remove(filename) then
|
||||||
io.write("file already exists")
|
io.stderr:write("file already exists")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local f, reason = io.open(filename, "wb")
|
local f, reason = io.open(filename, "wb")
|
||||||
if not f then
|
if not f then
|
||||||
io.write("Failed opening file for writing: ", reason)
|
io.stderr:write("failed opening file for writing: ", reason)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -68,7 +68,10 @@ if result then
|
|||||||
io.write("Saved data to ", filename, "\n")
|
io.write("Saved data to ", filename, "\n")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
if not options.q then
|
||||||
|
io.write("failed.\n")
|
||||||
|
end
|
||||||
f:close()
|
f:close()
|
||||||
fs.remove(filename)
|
fs.remove(filename)
|
||||||
io.write("HTTP request failed: ", response, "\n")
|
io.stderr:write("HTTP request failed: ", response, "\n")
|
||||||
end
|
end
|
@ -1,12 +1,12 @@
|
|||||||
local event = require("event")
|
local event = require("event")
|
||||||
local fs = require("filesystem")
|
local fs = require("filesystem")
|
||||||
local shell = require("shell")
|
local process = require("process")
|
||||||
|
|
||||||
local proxy = ...
|
local proxy = ...
|
||||||
|
|
||||||
-- Install symlinks if they don't already exist.
|
-- Install symlinks if they don't already exist.
|
||||||
local links = {}
|
local links = {}
|
||||||
local fsroot = fs.path(shell.running())
|
local fsroot = fs.path(process.running())
|
||||||
local function inject(path)
|
local function inject(path)
|
||||||
for file in fs.list(fs.concat(fsroot, path)) do
|
for file in fs.list(fs.concat(fsroot, path)) do
|
||||||
local source = fs.concat(fsroot, path, file)
|
local source = fs.concat(fsroot, path, file)
|
||||||
|
@ -5,7 +5,8 @@ local shell = require("shell")
|
|||||||
local sides = require("sides")
|
local sides = require("sides")
|
||||||
|
|
||||||
if not computer.isRobot() then
|
if not computer.isRobot() then
|
||||||
error("can only run on robots", 0)
|
io.stderr:write("can only run on robots")
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local args, options = shell.parse(...)
|
local args, options = shell.parse(...)
|
||||||
@ -17,7 +18,8 @@ end
|
|||||||
|
|
||||||
local size = tonumber(args[1])
|
local size = tonumber(args[1])
|
||||||
if not size then
|
if not size then
|
||||||
error("invalid size", 0)
|
io.stderr:write("invalid size")
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local r = component.computer
|
local r = component.computer
|
||||||
|
@ -50,12 +50,27 @@ end
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local running = setmetatable({}, {__mode="k"})
|
||||||
|
|
||||||
|
local function findProcess(co)
|
||||||
|
co = co or coroutine.running()
|
||||||
|
for _, process in pairs(running) do
|
||||||
|
for _, instance in pairs(process.instances) do
|
||||||
|
if instance == co then
|
||||||
|
return process
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
--[[ This is the global environment we make available to userland programs. ]]
|
--[[ This is the global environment we make available to userland programs. ]]
|
||||||
-- You'll notice that we do a lot of wrapping of native functions and adding
|
-- You'll notice that we do a lot of wrapping of native functions and adding
|
||||||
-- parameter checks in those wrappers. This is to avoid errors from the host
|
-- parameter checks in those wrappers. This is to avoid errors from the host
|
||||||
-- side that would push error objects - which are userdata and cannot be
|
-- side that would push error objects - which are userdata and cannot be
|
||||||
-- persisted.
|
-- persisted.
|
||||||
local sandbox
|
local sandbox, libprocess
|
||||||
sandbox = {
|
sandbox = {
|
||||||
assert = assert,
|
assert = assert,
|
||||||
dofile = nil, -- in boot/*_base.lua
|
dofile = nil, -- in boot/*_base.lua
|
||||||
@ -70,10 +85,7 @@ sandbox = {
|
|||||||
if not allowBytecode() then
|
if not allowBytecode() then
|
||||||
mode = "t"
|
mode = "t"
|
||||||
end
|
end
|
||||||
pcall(function()
|
env = env or select(2, libprocess.running())
|
||||||
local _, penv = sandbox.require("shell").running()
|
|
||||||
env = env or penv
|
|
||||||
end)
|
|
||||||
return load(ld, source, mode, env or sandbox)
|
return load(ld, source, mode, env or sandbox)
|
||||||
end,
|
end,
|
||||||
loadfile = nil, -- in boot/*_base.lua
|
loadfile = nil, -- in boot/*_base.lua
|
||||||
@ -96,9 +108,7 @@ sandbox = {
|
|||||||
coroutine = {
|
coroutine = {
|
||||||
create = function(f)
|
create = function(f)
|
||||||
local co = coroutine.create(f)
|
local co = coroutine.create(f)
|
||||||
pcall(function()
|
table.insert(findProcess().instances, co)
|
||||||
sandbox.require("shell").register(co)
|
|
||||||
end)
|
|
||||||
return co
|
return co
|
||||||
end,
|
end,
|
||||||
resume = function(co, ...) -- custom resume part for bubbling sysyields
|
resume = function(co, ...) -- custom resume part for bubbling sysyields
|
||||||
@ -257,7 +267,7 @@ sandbox = {
|
|||||||
sandbox._G = sandbox
|
sandbox._G = sandbox
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- Start of non-standard stuff made available via package.preload.
|
-- Start of non-standard stuff.
|
||||||
|
|
||||||
local libcomponent
|
local libcomponent
|
||||||
libcomponent = {
|
libcomponent = {
|
||||||
@ -359,6 +369,51 @@ local libcomputer = {
|
|||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libprocess = {
|
||||||
|
load = function(path, env, init, name)
|
||||||
|
checkArg(1, path, "string")
|
||||||
|
checkArg(2, env, "table", "nil")
|
||||||
|
checkArg(3, init, "function", "nil")
|
||||||
|
checkArg(4, name, "string", "nil")
|
||||||
|
|
||||||
|
local process = findProcess()
|
||||||
|
if process then
|
||||||
|
env = env or process.env
|
||||||
|
end
|
||||||
|
env = setmetatable({}, {__index=env or sandbox})
|
||||||
|
local code, reason = sandbox.loadfile(path, "t", env)
|
||||||
|
if not code then
|
||||||
|
return nil, reason
|
||||||
|
end
|
||||||
|
|
||||||
|
local thread = coroutine.create(function(...)
|
||||||
|
if init then
|
||||||
|
init()
|
||||||
|
end
|
||||||
|
return code(...)
|
||||||
|
end)
|
||||||
|
running[thread] = {
|
||||||
|
path = path,
|
||||||
|
command = name,
|
||||||
|
env = env,
|
||||||
|
parent = process,
|
||||||
|
instances = setmetatable({thread}, {__mode="v"})
|
||||||
|
}
|
||||||
|
return thread
|
||||||
|
end,
|
||||||
|
running = function(level)
|
||||||
|
level = level or 1
|
||||||
|
local process = findProcess()
|
||||||
|
while level > 1 and process do
|
||||||
|
process = process.parent
|
||||||
|
level = level - 1
|
||||||
|
end
|
||||||
|
if process then
|
||||||
|
return process.path, process.env, process.command
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
local libunicode = {
|
local libunicode = {
|
||||||
char = function(...)
|
char = function(...)
|
||||||
local args = table.pack(...)
|
local args = table.pack(...)
|
||||||
@ -396,107 +451,103 @@ local libunicode = {
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
local function main()
|
local function bootstrap()
|
||||||
local args
|
-- Minimalistic hard-coded pure async proxy for our ROM.
|
||||||
local function bootstrap()
|
local rom = {}
|
||||||
-- Minimalistic hard-coded pure async proxy for our ROM.
|
function rom.invoke(method, ...)
|
||||||
local rom = {}
|
return invoke(true, computer.romAddress(), method, ...)
|
||||||
function rom.invoke(method, ...)
|
|
||||||
return invoke(true, computer.romAddress(), method, ...)
|
|
||||||
end
|
|
||||||
function rom.open(file) return rom.invoke("open", file) end
|
|
||||||
function rom.read(handle) return rom.invoke("read", handle, math.huge) end
|
|
||||||
function rom.close(handle) return rom.invoke("close", handle) end
|
|
||||||
function rom.inits(file) return ipairs(rom.invoke("list", "boot")) end
|
|
||||||
function rom.isDirectory(path) return rom.invoke("isDirectory", path) end
|
|
||||||
|
|
||||||
-- Custom low-level loadfile/dofile implementation reading from our ROM.
|
|
||||||
local function loadfile(file)
|
|
||||||
local handle, reason = rom.open(file)
|
|
||||||
if not handle then
|
|
||||||
error(reason)
|
|
||||||
end
|
|
||||||
if handle then
|
|
||||||
local buffer = ""
|
|
||||||
repeat
|
|
||||||
local data, reason = rom.read(handle)
|
|
||||||
if not data and reason then
|
|
||||||
error(reason)
|
|
||||||
end
|
|
||||||
buffer = buffer .. (data or "")
|
|
||||||
until not data
|
|
||||||
rom.close(handle)
|
|
||||||
return load(buffer, "=" .. file, "t", sandbox)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local function dofile(file)
|
|
||||||
local program, reason = loadfile(file)
|
|
||||||
if program then
|
|
||||||
local result = table.pack(pcall(program))
|
|
||||||
if result[1] then
|
|
||||||
return table.unpack(result, 2, result.n)
|
|
||||||
else
|
|
||||||
error(result[2])
|
|
||||||
end
|
|
||||||
else
|
|
||||||
error(reason)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Make all calls in the bootstrapper direct to speed up booting. This is
|
|
||||||
-- safe because all invokes are rom fs related - or should be, anyway.
|
|
||||||
local realInvoke = invoke
|
|
||||||
invoke = function(_, ...) return realInvoke(true, ...) end
|
|
||||||
|
|
||||||
-- Load file system related libraries we need to load other stuff moree
|
|
||||||
-- comfortably. This is basically wrapper stuff for the file streams
|
|
||||||
-- provided by the filesystem components.
|
|
||||||
local buffer = loadfile("/lib/buffer.lua")
|
|
||||||
local fs = loadfile("/lib/filesystem.lua")
|
|
||||||
local io = loadfile("/lib/io.lua")
|
|
||||||
local package = dofile("/lib/package.lua")
|
|
||||||
|
|
||||||
-- Initialize the package module with some of our own APIs.
|
|
||||||
package.preload["buffer"] = buffer
|
|
||||||
package.preload["component"] = function() return libcomponent end
|
|
||||||
package.preload["computer"] = function() return libcomputer end
|
|
||||||
package.preload["filesystem"] = fs
|
|
||||||
package.preload["io"] = io
|
|
||||||
package.preload["unicode"] = function() return libunicode end
|
|
||||||
|
|
||||||
-- Inject the package and io modules into the global namespace, as in Lua.
|
|
||||||
sandbox.package = package
|
|
||||||
sandbox.io = sandbox.require("io")
|
|
||||||
|
|
||||||
-- Mount the ROM and temporary file systems to allow working on the file
|
|
||||||
-- system module from this point on.
|
|
||||||
sandbox.require("filesystem").mount(computer.romAddress(), "/")
|
|
||||||
if computer.tmpAddress() then
|
|
||||||
sandbox.require("filesystem").mount(computer.tmpAddress(), "/tmp")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Run library startup scripts. These mostly initialize event handlers.
|
|
||||||
local scripts = {}
|
|
||||||
for _, file in rom.inits() do
|
|
||||||
local path = "boot/" .. file
|
|
||||||
if not rom.isDirectory(path) then
|
|
||||||
table.insert(scripts, path)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
table.sort(scripts)
|
|
||||||
for i = 1, #scripts do
|
|
||||||
dofile(scripts[i])
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Step out of the fast lane, all the basic stuff should now be loaded.
|
|
||||||
invoke = realInvoke
|
|
||||||
|
|
||||||
-- Yield once to get a memory baseline.
|
|
||||||
coroutine.yield()
|
|
||||||
|
|
||||||
return coroutine.create(function() dofile("/init.lua") end)
|
|
||||||
end
|
end
|
||||||
local co, args = bootstrap(), {n=0}
|
function rom.open(file) return rom.invoke("open", file) end
|
||||||
|
function rom.read(handle) return rom.invoke("read", handle, math.huge) end
|
||||||
|
function rom.close(handle) return rom.invoke("close", handle) end
|
||||||
|
function rom.inits(file) return ipairs(rom.invoke("list", "boot")) end
|
||||||
|
function rom.isDirectory(path) return rom.invoke("isDirectory", path) end
|
||||||
|
|
||||||
|
-- Custom low-level loadfile/dofile implementation reading from our ROM.
|
||||||
|
local function loadfile(file)
|
||||||
|
local handle, reason = rom.open(file)
|
||||||
|
if not handle then
|
||||||
|
error(reason)
|
||||||
|
end
|
||||||
|
local buffer = ""
|
||||||
|
repeat
|
||||||
|
local data, reason = rom.read(handle)
|
||||||
|
if not data and reason then
|
||||||
|
error(reason)
|
||||||
|
end
|
||||||
|
buffer = buffer .. (data or "")
|
||||||
|
until not data
|
||||||
|
rom.close(handle)
|
||||||
|
return load(buffer, "=" .. file, "t", sandbox)
|
||||||
|
end
|
||||||
|
local function dofile(file)
|
||||||
|
local program, reason = loadfile(file)
|
||||||
|
if program then
|
||||||
|
local result = table.pack(pcall(program))
|
||||||
|
if result[1] then
|
||||||
|
return table.unpack(result, 2, result.n)
|
||||||
|
else
|
||||||
|
error(result[2])
|
||||||
|
end
|
||||||
|
else
|
||||||
|
error(reason)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Load file system related libraries we need to load other stuff moree
|
||||||
|
-- comfortably. This is basically wrapper stuff for the file streams
|
||||||
|
-- provided by the filesystem components.
|
||||||
|
local package = dofile("/lib/package.lua")
|
||||||
|
|
||||||
|
-- Initialize the package module with some of our own APIs.
|
||||||
|
package.preload["buffer"] = loadfile("/lib/buffer.lua")
|
||||||
|
package.preload["component"] = function() return libcomponent end
|
||||||
|
package.preload["computer"] = function() return libcomputer end
|
||||||
|
package.preload["filesystem"] = loadfile("/lib/filesystem.lua")
|
||||||
|
package.preload["io"] = loadfile("/lib/io.lua")
|
||||||
|
package.preload["process"] = function() return libprocess end
|
||||||
|
package.preload["unicode"] = function() return libunicode end
|
||||||
|
|
||||||
|
-- Inject the package and io modules into the global namespace, as in Lua.
|
||||||
|
sandbox.package = package
|
||||||
|
sandbox.io = sandbox.require("io")
|
||||||
|
|
||||||
|
-- Mount the ROM and temporary file systems to allow working on the file
|
||||||
|
-- system module from this point on.
|
||||||
|
sandbox.require("filesystem").mount(computer.romAddress(), "/")
|
||||||
|
if computer.tmpAddress() then
|
||||||
|
sandbox.require("filesystem").mount(computer.tmpAddress(), "/tmp")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Run library startup scripts. These mostly initialize event handlers.
|
||||||
|
local scripts = {}
|
||||||
|
for _, file in rom.inits() do
|
||||||
|
local path = "boot/" .. file
|
||||||
|
if not rom.isDirectory(path) then
|
||||||
|
table.insert(scripts, path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(scripts)
|
||||||
|
for i = 1, #scripts do
|
||||||
|
dofile(scripts[i])
|
||||||
|
end
|
||||||
|
|
||||||
|
return coroutine.create(function() dofile("/init.lua") end), {n=0}
|
||||||
|
end
|
||||||
|
|
||||||
|
local function main()
|
||||||
|
-- Make all calls in the bootstrapper direct to speed up booting.
|
||||||
|
local realInvoke = invoke
|
||||||
|
invoke = function(_, ...) return realInvoke(true, ...) end
|
||||||
|
|
||||||
|
local co, args = bootstrap()
|
||||||
|
|
||||||
|
-- Step out of the fast lane, all the basic stuff should now be loaded.
|
||||||
|
invoke = realInvoke
|
||||||
|
|
||||||
|
-- Yield once to get a memory baseline.
|
||||||
|
coroutine.yield()
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
deadline = computer.realTime() + timeout -- timeout global is set by host
|
deadline = computer.realTime() + timeout -- timeout global is set by host
|
||||||
debug.sethook(co, checkDeadline, "", hookInterval)
|
debug.sethook(co, checkDeadline, "", hookInterval)
|
||||||
|
@ -11,7 +11,7 @@ elseif #args == 1 then
|
|||||||
if value then
|
if value then
|
||||||
io.write(value)
|
io.write(value)
|
||||||
else
|
else
|
||||||
io.write("no such alias")
|
io.stderr:write("no such alias")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
shell.setAlias(args[1], args[2])
|
shell.setAlias(args[1], args[2])
|
||||||
|
@ -12,7 +12,7 @@ else
|
|||||||
for i = 1, #args do
|
for i = 1, #args do
|
||||||
local file, reason = io.open(shell.resolve(args[i]))
|
local file, reason = io.open(shell.resolve(args[i]))
|
||||||
if not file then
|
if not file then
|
||||||
io.write(reason)
|
io.stderr:write(reason)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
repeat
|
repeat
|
||||||
|
@ -6,6 +6,6 @@ if #args == 0 then
|
|||||||
else
|
else
|
||||||
local result, reason = shell.setWorkingDirectory(shell.resolve(args[1]))
|
local result, reason = shell.setWorkingDirectory(shell.resolve(args[1]))
|
||||||
if not result then
|
if not result then
|
||||||
io.write(reason)
|
io.stderr:write(reason)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -14,9 +14,10 @@ if fs.isDirectory(to) then
|
|||||||
to = to .. "/" .. fs.name(from)
|
to = to .. "/" .. fs.name(from)
|
||||||
end
|
end
|
||||||
if fs.exists(to) and not options.f then
|
if fs.exists(to) and not options.f then
|
||||||
error("target file exists")
|
io.stderr:write("target file exists")
|
||||||
|
return
|
||||||
end
|
end
|
||||||
local result, reason = fs.copy(from, to)
|
local result, reason = fs.copy(from, to)
|
||||||
if not result then
|
if not result then
|
||||||
io.write(reason)
|
io.stderr:write(reason)
|
||||||
end
|
end
|
@ -12,7 +12,7 @@ else
|
|||||||
for i = 1, #args do
|
for i = 1, #args do
|
||||||
local proxy, path = fs.get(args[i])
|
local proxy, path = fs.get(args[i])
|
||||||
if not proxy then
|
if not proxy then
|
||||||
io.write(args[i], ": no such file or directory\n")
|
io.stderr:write(args[i], ": no such file or directory\n")
|
||||||
else
|
else
|
||||||
mounts[path] = proxy
|
mounts[path] = proxy
|
||||||
end
|
end
|
||||||
|
@ -22,7 +22,7 @@ local filename = shell.resolve(args[1])
|
|||||||
local readonly = options.r or fs.get(filename) == nil or fs.get(filename).isReadOnly()
|
local readonly = options.r or fs.get(filename) == nil or fs.get(filename).isReadOnly()
|
||||||
|
|
||||||
if fs.isDirectory(filename) or readonly and not fs.exists(filename) then
|
if fs.isDirectory(filename) or readonly and not fs.exists(filename) then
|
||||||
io.write("file not found")
|
io.stderr:write("file not found")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -15,15 +15,15 @@ else
|
|||||||
proxy, reaons = fs.get(args[1])
|
proxy, reaons = fs.get(args[1])
|
||||||
end
|
end
|
||||||
if not proxy then
|
if not proxy then
|
||||||
io.write(reason)
|
io.stderr:write(reason)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if #args < 2 then
|
if #args < 2 then
|
||||||
io.write(proxy.getLabel() or "no label")
|
io.stderr:write(proxy.getLabel() or "no label")
|
||||||
else
|
else
|
||||||
local result, reason = proxy.setLabel(args[2])
|
local result, reason = proxy.setLabel(args[2])
|
||||||
if not result then
|
if not result then
|
||||||
io.write(reason or "could not set label")
|
io.stderr:write(reason or "could not set label")
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -18,5 +18,5 @@ end
|
|||||||
|
|
||||||
local result, reason = fs.link(target, linkpath)
|
local result, reason = fs.link(target, linkpath)
|
||||||
if not result then
|
if not result then
|
||||||
io.write(reason)
|
io.stderr:write(reason)
|
||||||
end
|
end
|
@ -46,7 +46,7 @@ while term.isAvailable() do
|
|||||||
if type(result[2]) == "table" and result[2].reason == "terminated" then
|
if type(result[2]) == "table" and result[2].reason == "terminated" then
|
||||||
os.exit(result[2].code)
|
os.exit(result[2].code)
|
||||||
end
|
end
|
||||||
io.write(tostring(result[2]), "\n")
|
io.stderr:write(tostring(result[2]), "\n")
|
||||||
else
|
else
|
||||||
for i = 2, result.n do
|
for i = 2, result.n do
|
||||||
io.write(text.serialize(result[i], true), "\t")
|
io.write(text.serialize(result[i], true), "\t")
|
||||||
@ -56,6 +56,6 @@ while term.isAvailable() do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
io.write(reason, "\n")
|
io.stderr:write(reason, "\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -16,4 +16,4 @@ for path in string.gmatch(os.getenv("MANPATH"), "[^:]+") do
|
|||||||
os.exit()
|
os.exit()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
io.write("No manual entry for " .. topic)
|
io.stderr:write("No manual entry for " .. topic)
|
@ -18,6 +18,6 @@ for i = 1, #args do
|
|||||||
reason = "unknown reason"
|
reason = "unknown reason"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
io.write(path, ": ", reason, "\n")
|
io.stderr:write(path, ": ", reason, "\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -12,7 +12,7 @@ end
|
|||||||
|
|
||||||
local file, reason = io.open(shell.resolve(args[1]))
|
local file, reason = io.open(shell.resolve(args[1]))
|
||||||
if not file then
|
if not file then
|
||||||
io.write(reason)
|
io.stderr:write(reason)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -18,11 +18,11 @@ end
|
|||||||
|
|
||||||
local proxy, reason = fs.proxy(args[1])
|
local proxy, reason = fs.proxy(args[1])
|
||||||
if not proxy then
|
if not proxy then
|
||||||
io.write(reason)
|
io.stderr:write(reason)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local result, reason = fs.mount(proxy, shell.resolve(args[2]))
|
local result, reason = fs.mount(proxy, shell.resolve(args[2]))
|
||||||
if not result then
|
if not result then
|
||||||
io.write(reason)
|
io.stderr:write(reason)
|
||||||
end
|
end
|
@ -15,11 +15,11 @@ if fs.isDirectory(to) then
|
|||||||
end
|
end
|
||||||
if fs.exists(to) then
|
if fs.exists(to) then
|
||||||
if not options.f then
|
if not options.f then
|
||||||
io.write("target file exists")
|
io.stderr:write("target file exists")
|
||||||
end
|
end
|
||||||
fs.remove(to)
|
fs.remove(to)
|
||||||
end
|
end
|
||||||
local result, reason = os.rename(from, to)
|
local result, reason = os.rename(from, to)
|
||||||
if not result then
|
if not result then
|
||||||
io.write(reason or "unknown error")
|
io.stderr:write(reason or "unknown error")
|
||||||
end
|
end
|
||||||
|
@ -13,7 +13,7 @@ local componentType = args[1]
|
|||||||
if #args > 1 then
|
if #args > 1 then
|
||||||
local address = args[2]
|
local address = args[2]
|
||||||
if not component.get(address) then
|
if not component.get(address) then
|
||||||
io.write("no component with this address")
|
io.stderr:write("no component with this address")
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
component.setPrimary(componentType, address)
|
component.setPrimary(componentType, address)
|
||||||
@ -23,5 +23,5 @@ end
|
|||||||
if component.isAvailable(componentType) then
|
if component.isAvailable(componentType) then
|
||||||
io.write(component.getPrimary(componentType).address)
|
io.write(component.getPrimary(componentType).address)
|
||||||
else
|
else
|
||||||
io.write("no primary component for this type")
|
io.stderr:write("no primary component for this type")
|
||||||
end
|
end
|
||||||
|
@ -3,6 +3,10 @@ local component = require("component")
|
|||||||
local shell = require("shell")
|
local shell = require("shell")
|
||||||
local sides = require("sides")
|
local sides = require("sides")
|
||||||
|
|
||||||
|
if not component.isAvailable("redstone") then
|
||||||
|
io.stderr:write("This program requires a redstone card or redstone I/O block.")
|
||||||
|
return
|
||||||
|
end
|
||||||
local rs = component.redstone
|
local rs = component.redstone
|
||||||
|
|
||||||
local args, options = shell.parse(...)
|
local args, options = shell.parse(...)
|
||||||
@ -17,7 +21,8 @@ end
|
|||||||
|
|
||||||
local side = sides[args[1]]
|
local side = sides[args[1]]
|
||||||
if not side then
|
if not side then
|
||||||
error("Invalid side.")
|
io.stderr:write("invalid side")
|
||||||
|
return
|
||||||
end
|
end
|
||||||
if type(side) == "string" then
|
if type(side) == "string" then
|
||||||
side = sides[side]
|
side = sides[side]
|
||||||
@ -25,11 +30,13 @@ end
|
|||||||
|
|
||||||
if options.b then
|
if options.b then
|
||||||
if not rs.setBundledOutput then
|
if not rs.setBundledOutput then
|
||||||
error("Bundled redstone not available.")
|
io.stderr:write("bundled redstone not available")
|
||||||
|
return
|
||||||
end
|
end
|
||||||
local color = colors[args[2]]
|
local color = colors[args[2]]
|
||||||
if not color then
|
if not color then
|
||||||
error("Invalid color.")
|
io.stderr:write("invalid color")
|
||||||
|
return
|
||||||
end
|
end
|
||||||
if type(color) == "string" then
|
if type(color) == "string" then
|
||||||
color = colors[color]
|
color = colors[color]
|
||||||
|
@ -17,12 +17,13 @@ end
|
|||||||
local w = tonumber(args[1])
|
local w = tonumber(args[1])
|
||||||
local h = tonumber(args[2])
|
local h = tonumber(args[2])
|
||||||
if not w or not h then
|
if not w or not h then
|
||||||
io.write("invalid width or height")
|
io.stderr:write("invalid width or height")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local result, reason = component.gpu.setResolution(w, h)
|
local result, reason = component.gpu.setResolution(w, h)
|
||||||
if not result then
|
if not result then
|
||||||
io.write(reason)
|
io.stderr:write(reason)
|
||||||
|
return
|
||||||
end
|
end
|
||||||
term.clear()
|
term.clear()
|
@ -9,6 +9,6 @@ end
|
|||||||
for i = 1, #args do
|
for i = 1, #args do
|
||||||
local path = shell.resolve(args[i])
|
local path = shell.resolve(args[i])
|
||||||
if not os.remove(path) then
|
if not os.remove(path) then
|
||||||
io.write(path, ": no such file, or permission denied\n")
|
io.stderr:write(path, ": no such file, or permission denied\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -2,7 +2,7 @@ local args = {...}
|
|||||||
|
|
||||||
if #args < 1 then
|
if #args < 1 then
|
||||||
for k,v in pairs(os.getenv()) do
|
for k,v in pairs(os.getenv()) do
|
||||||
io.write(k..'='..v..'\n')
|
io.write(k, "='", string.gsub(v, "'", [['"'"']]), "'\n")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local count = 0
|
local count = 0
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
local component = require("component")
|
local component = require("component")
|
||||||
local computer = require("computer")
|
local computer = require("computer")
|
||||||
local event = require("event")
|
local event = require("event")
|
||||||
|
local process = require("process")
|
||||||
local shell = require("shell")
|
local shell = require("shell")
|
||||||
local term = require("term")
|
local term = require("term")
|
||||||
local text = require("text")
|
local text = require("text")
|
||||||
@ -8,8 +9,8 @@ local text = require("text")
|
|||||||
local args, options = shell.parse(...)
|
local args, options = shell.parse(...)
|
||||||
local history = {}
|
local history = {}
|
||||||
|
|
||||||
if options.v or not shell.running(2) then
|
if options.v or not process.running(2) then
|
||||||
print(_OSVERSION .. " (" .. math.floor(computer.totalMemory() / 1024) .. "k RAM)")
|
io.write(_OSVERSION .. " (" .. math.floor(computer.totalMemory() / 1024) .. "k RAM)\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
@ -19,7 +20,7 @@ while true do
|
|||||||
end
|
end
|
||||||
term.clear()
|
term.clear()
|
||||||
if options.v then
|
if options.v then
|
||||||
print(_OSVERSION .. " (" .. math.floor(computer.totalMemory() / 1024) .. "k RAM)")
|
io.write(_OSVERSION .. " (" .. math.floor(computer.totalMemory() / 1024) .. "k RAM)\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
while term.isAvailable() do
|
while term.isAvailable() do
|
||||||
@ -28,7 +29,7 @@ while true do
|
|||||||
component.gpu.setForeground(foreground)
|
component.gpu.setForeground(foreground)
|
||||||
local command = term.read(history)
|
local command = term.read(history)
|
||||||
if not command then
|
if not command then
|
||||||
print("exit")
|
io.write("exit\n")
|
||||||
return -- eof
|
return -- eof
|
||||||
end
|
end
|
||||||
while #history > 10 do
|
while #history > 10 do
|
||||||
@ -40,10 +41,10 @@ while true do
|
|||||||
elseif command ~= "" then
|
elseif command ~= "" then
|
||||||
local result, reason = os.execute(command)
|
local result, reason = os.execute(command)
|
||||||
if not result then
|
if not result then
|
||||||
print(reason)
|
io.stderr:write(reason .. "\n")
|
||||||
elseif term.getCursor() > 1 then
|
elseif term.getCursor() > 1 then
|
||||||
print()
|
io.write("\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -21,16 +21,16 @@ else
|
|||||||
if proxy then
|
if proxy then
|
||||||
proxy = reason -- = path
|
proxy = reason -- = path
|
||||||
if proxy ~= path then
|
if proxy ~= path then
|
||||||
io.write("not a mount point")
|
io.stderr:write("not a mount point")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not proxy then
|
if not proxy then
|
||||||
io.write(reason)
|
io.stderr:write(reason)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not fs.umount(proxy) then
|
if not fs.umount(proxy) then
|
||||||
io.write("nothing to unmount here")
|
io.stderr:write("nothing to unmount here")
|
||||||
end
|
end
|
@ -8,7 +8,7 @@ end
|
|||||||
|
|
||||||
local result = shell.getAlias(args[1])
|
local result = shell.getAlias(args[1])
|
||||||
if not result then
|
if not result then
|
||||||
io.write("no such alias")
|
io.stderr:write("no such alias")
|
||||||
else
|
else
|
||||||
shell.setAlias(args[1], nil)
|
shell.setAlias(args[1], nil)
|
||||||
io.write("alias removed: ", args[1], " -> ", result)
|
io.write("alias removed: ", args[1], " -> ", result)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
local args = {...}
|
local args = {...}
|
||||||
|
|
||||||
if #args < 1 then
|
if #args < 1 then
|
||||||
print "You have to specify which arguments to unset!"
|
print("Usage: unset <varname>[ <varname2> [...]]")
|
||||||
else
|
else
|
||||||
for _, k in ipairs(args) do
|
for _, k in ipairs(args) do
|
||||||
os.setenv(k, nil)
|
os.setenv(k, nil)
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -9,5 +9,5 @@ end
|
|||||||
|
|
||||||
local result, reason = computer.addUser(args[1])
|
local result, reason = computer.addUser(args[1])
|
||||||
if not result then
|
if not result then
|
||||||
io.write(reason)
|
io.stderr:write(reason)
|
||||||
end
|
end
|
@ -8,5 +8,5 @@ if #args < 1 then
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not computer.removeUser(args[1]) then
|
if not computer.removeUser(args[1]) then
|
||||||
io.write("no such user")
|
io.stderr:write("no such user")
|
||||||
end
|
end
|
@ -16,6 +16,6 @@ for i = 1, #args do
|
|||||||
if result then
|
if result then
|
||||||
io.write(result, "\n")
|
io.write(result, "\n")
|
||||||
else
|
else
|
||||||
io.write(args[i], ": ", reason, "\n")
|
io.stderr:write(args[i], ": ", reason, "\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -3,6 +3,7 @@ local term = require("term")
|
|||||||
|
|
||||||
local stdinStream = {handle="stdin"}
|
local stdinStream = {handle="stdin"}
|
||||||
local stdoutStream = {handle="stdout"}
|
local stdoutStream = {handle="stdout"}
|
||||||
|
local stderrStream = {handle="stderr"}
|
||||||
local stdinHistory = {}
|
local stdinHistory = {}
|
||||||
|
|
||||||
local function badFileDescriptor()
|
local function badFileDescriptor()
|
||||||
@ -13,6 +14,7 @@ function stdinStream:close()
|
|||||||
return nil, "cannot close standard file"
|
return nil, "cannot close standard file"
|
||||||
end
|
end
|
||||||
stdoutStream.close = stdinStream.close
|
stdoutStream.close = stdinStream.close
|
||||||
|
stderrStream.close = stdinStream.close
|
||||||
|
|
||||||
function stdinStream:read(n)
|
function stdinStream:read(n)
|
||||||
local result = term.read(stdinHistory)
|
local result = term.read(stdinHistory)
|
||||||
@ -27,16 +29,32 @@ function stdoutStream:write(str)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function stderrStream:write(str)
|
||||||
|
local component = require("component")
|
||||||
|
if component.isAvailable("gpu") and component.gpu.getDepth() > 1 then
|
||||||
|
local foreground = component.gpu.getForeground()
|
||||||
|
component.gpu.setForeground(0xFF0000)
|
||||||
|
term.write(str, true)
|
||||||
|
component.gpu.setForeground(foreground)
|
||||||
|
else
|
||||||
|
term.write(str, true)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
stdinStream.seek = badFileDescriptor
|
stdinStream.seek = badFileDescriptor
|
||||||
stdinStream.write = badFileDescriptor
|
stdinStream.write = badFileDescriptor
|
||||||
stdoutStream.read = badFileDescriptor
|
stdoutStream.read = badFileDescriptor
|
||||||
stdoutStream.seek = badFileDescriptor
|
stdoutStream.seek = badFileDescriptor
|
||||||
|
stderrStream.read = badFileDescriptor
|
||||||
|
stderrStream.seek = badFileDescriptor
|
||||||
|
|
||||||
io.stdin = buffer.new("r", stdinStream)
|
io.stdin = buffer.new("r", stdinStream)
|
||||||
io.stdout = buffer.new("w", stdoutStream)
|
io.stdout = buffer.new("w", stdoutStream)
|
||||||
io.stderr = io.stdout
|
io.stderr = buffer.new("w", stderrStream)
|
||||||
|
|
||||||
io.stdout:setvbuf("no")
|
io.stdout:setvbuf("no")
|
||||||
|
io.stderr:setvbuf("no")
|
||||||
|
|
||||||
io.input(io.stdin)
|
io.input(io.stdin)
|
||||||
io.output(io.stdout)
|
io.output(io.stdout)
|
@ -3,7 +3,7 @@ local unicode = require("unicode")
|
|||||||
|
|
||||||
local filesystem, fileStream = {}, {}
|
local filesystem, fileStream = {}, {}
|
||||||
local isAutorunEnabled = true
|
local isAutorunEnabled = true
|
||||||
local mtab = {children={}, links={}}
|
local mtab = {name="", children={}, links={}}
|
||||||
|
|
||||||
local function segments(path)
|
local function segments(path)
|
||||||
path = path:gsub("\\", "/")
|
path = path:gsub("\\", "/")
|
||||||
@ -258,7 +258,7 @@ function filesystem.exists(path)
|
|||||||
if not vrest or vnode.links[vrest] then -- virtual directory or symbolic link
|
if not vrest or vnode.links[vrest] then -- virtual directory or symbolic link
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
if node.fs then
|
if node and node.fs then
|
||||||
return node.fs.exists(rest)
|
return node.fs.exists(rest)
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
@ -472,18 +472,9 @@ function filesystem.open(path, mode)
|
|||||||
|
|
||||||
local stream = {fs = node.fs, handle = handle}
|
local stream = {fs = node.fs, handle = handle}
|
||||||
|
|
||||||
-- stream:close does a syscall, which yields, and that's not possible in
|
|
||||||
-- the __gc metamethod. So we start a timer to do the yield/cleanup.
|
|
||||||
local function cleanup(self)
|
local function cleanup(self)
|
||||||
if not self.handle then return end
|
if not self.handle then return end
|
||||||
-- save non-gc'ed values as upvalues
|
pcall(self.fs.close, self.handle)
|
||||||
local fs = self.fs
|
|
||||||
local handle = self.handle
|
|
||||||
local function close()
|
|
||||||
fs.close(handle)
|
|
||||||
end
|
|
||||||
-- Required locally because this is a bootstrapped file.
|
|
||||||
require("event").timer(0, close)
|
|
||||||
end
|
end
|
||||||
local metatable = {__index = fileStream,
|
local metatable = {__index = fileStream,
|
||||||
__gc = cleanup,
|
__gc = cleanup,
|
||||||
|
@ -8,7 +8,6 @@ local loaded = {
|
|||||||
["_G"] = _G,
|
["_G"] = _G,
|
||||||
["bit32"] = bit32,
|
["bit32"] = bit32,
|
||||||
["coroutine"] = coroutine,
|
["coroutine"] = coroutine,
|
||||||
["io"] = io,
|
|
||||||
["math"] = math,
|
["math"] = math,
|
||||||
["os"] = os,
|
["os"] = os,
|
||||||
["package"] = package,
|
["package"] = package,
|
||||||
@ -29,13 +28,14 @@ function package.searchpath(name, path, sep, rep)
|
|||||||
rep = rep or '/'
|
rep = rep or '/'
|
||||||
sep, rep = '%' .. sep, rep
|
sep, rep = '%' .. sep, rep
|
||||||
name = string.gsub(name, sep, rep)
|
name = string.gsub(name, sep, rep)
|
||||||
|
local fs = require("filesystem")
|
||||||
local errorFiles = {}
|
local errorFiles = {}
|
||||||
for subPath in string.gmatch(path, "([^;]+)") do
|
for subPath in string.gmatch(path, "([^;]+)") do
|
||||||
subPath = string.gsub(subPath, "?", name)
|
subPath = string.gsub(subPath, "?", name)
|
||||||
if loaded.shell then
|
if subPath:sub(1, 1) ~= "/" and os.getenv then
|
||||||
subPath = require("shell").resolve(subPath)
|
subPath = fs.concat(os.getenv("PWD") or "/", subPath)
|
||||||
end
|
end
|
||||||
if require("filesystem").exists(subPath) then
|
if fs.exists(subPath) then
|
||||||
local file = io.open(subPath, "r")
|
local file = io.open(subPath, "r")
|
||||||
if file then
|
if file then
|
||||||
file:close()
|
file:close()
|
||||||
@ -80,8 +80,11 @@ function require(module)
|
|||||||
loading[module] = true
|
loading[module] = true
|
||||||
local loader, value, errorMsg = nil, nil, {"module '" .. module .. "' not found:"}
|
local loader, value, errorMsg = nil, nil, {"module '" .. module .. "' not found:"}
|
||||||
for i = 1, #package.searchers do
|
for i = 1, #package.searchers do
|
||||||
local f, extra = package.searchers[i](module)
|
-- the pcall is mostly for out of memory errors
|
||||||
if f and type(f) ~= "string" then
|
local ok, f, extra = pcall(package.searchers[i], module)
|
||||||
|
if not ok then
|
||||||
|
table.insert(errorMsg, "\t" .. f)
|
||||||
|
elseif f and type(f) ~= "string" then
|
||||||
loader = f
|
loader = f
|
||||||
value = extra
|
value = extra
|
||||||
break
|
break
|
||||||
|
@ -5,23 +5,13 @@ local text = require("text")
|
|||||||
|
|
||||||
local shell = {}
|
local shell = {}
|
||||||
local aliases = {}
|
local aliases = {}
|
||||||
local running = setmetatable({}, {__mode="k"})
|
|
||||||
local isLoading = false
|
|
||||||
|
|
||||||
local function findProcess(co)
|
|
||||||
co = co or coroutine.running()
|
|
||||||
for _, process in pairs(running) do
|
|
||||||
for _, instance in pairs(process.instances) do
|
|
||||||
if instance == co then
|
|
||||||
return process
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function findFile(name, ext)
|
local function findFile(name, ext)
|
||||||
checkArg(1, name, "string")
|
checkArg(1, name, "string")
|
||||||
local function findIn(dir)
|
local function findIn(dir)
|
||||||
|
if dir:sub(1, 1) ~= "/" then
|
||||||
|
dir = shell.resolve(dir)
|
||||||
|
end
|
||||||
dir = fs.concat(fs.concat(dir, name), "..")
|
dir = fs.concat(fs.concat(dir, name), "..")
|
||||||
name = fs.name(name)
|
name = fs.name(name)
|
||||||
local list = fs.list(dir)
|
local list = fs.list(dir)
|
||||||
@ -475,52 +465,11 @@ function shell.execute(command, env, ...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function shell.load(path, env, init, name)
|
function shell.load(path, env, init, name)
|
||||||
checkArg(1, path, "string")
|
local path, reason = shell.resolve(path, "lua")
|
||||||
checkArg(2, env, "table", "nil")
|
if not path then
|
||||||
checkArg(3, init, "function", "nil")
|
|
||||||
checkArg(4, name, "string", "nil")
|
|
||||||
local filename, reason = shell.resolve(path, "lua")
|
|
||||||
if not filename then
|
|
||||||
return nil, reason
|
return nil, reason
|
||||||
end
|
end
|
||||||
|
return require("process").load(path, env, init, name)
|
||||||
local process = findProcess()
|
|
||||||
if process then
|
|
||||||
env = env or process.env
|
|
||||||
end
|
|
||||||
env = setmetatable({}, {__index=env or _ENV})
|
|
||||||
local code, reason = loadfile(filename, "t", env)
|
|
||||||
if not code then
|
|
||||||
return nil, reason
|
|
||||||
end
|
|
||||||
|
|
||||||
isLoading = true
|
|
||||||
local thread = coroutine.create(function(...)
|
|
||||||
if init then
|
|
||||||
init()
|
|
||||||
end
|
|
||||||
return code(...)
|
|
||||||
end)
|
|
||||||
isLoading = false
|
|
||||||
running[thread] = {
|
|
||||||
path = filename,
|
|
||||||
command = name,
|
|
||||||
env = env,
|
|
||||||
parent = process,
|
|
||||||
instances = setmetatable({thread}, {__mode="v"})
|
|
||||||
}
|
|
||||||
return thread
|
|
||||||
end
|
|
||||||
|
|
||||||
function shell.register(thread) -- called from coroutine.create
|
|
||||||
checkArg(1, thread, "thread")
|
|
||||||
if findProcess(thread) then
|
|
||||||
return false -- already attached somewhere
|
|
||||||
end
|
|
||||||
if not isLoading then
|
|
||||||
table.insert(findProcess().instances, thread)
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function shell.parse(...)
|
function shell.parse(...)
|
||||||
@ -540,16 +489,8 @@ function shell.parse(...)
|
|||||||
return args, options
|
return args, options
|
||||||
end
|
end
|
||||||
|
|
||||||
function shell.running(level)
|
function shell.running(level) -- deprecated
|
||||||
level = level or 1
|
return require("process").running(level)
|
||||||
local process = findProcess()
|
|
||||||
while level > 1 and process do
|
|
||||||
process = process.parent
|
|
||||||
level = level - 1
|
|
||||||
end
|
|
||||||
if process then
|
|
||||||
return process.path, process.env, process.command
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
@ -588,7 +588,7 @@ opencomputers {
|
|||||||
# allocations regardless of the amount of RAM installed in the computer it
|
# allocations regardless of the amount of RAM installed in the computer it
|
||||||
# runs on. As a side effect this pretty much determines the read
|
# runs on. As a side effect this pretty much determines the read
|
||||||
# performance of file systems.
|
# performance of file systems.
|
||||||
maxReadBuffer: 8192
|
maxReadBuffer: 2048
|
||||||
}
|
}
|
||||||
|
|
||||||
# Internet settings, security related.
|
# Internet settings, security related.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user